diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 49e475046f79c..51d9b2432e848 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.20254.3", + "version": "1.0.0-prerelease.20271.3", "commands": [ "xharness" ] diff --git a/.editorconfig b/.editorconfig index bb9c61f6623de..28e3eaba64e83 100644 --- a/.editorconfig +++ b/.editorconfig @@ -155,6 +155,7 @@ csharp_space_between_square_brackets = false # Analyzers dotnet_code_quality.ca1802.api_surface = private, internal +dotnet_code_quality.CA2208.api_surface = public # C++ Files [*.{cpp,h,in}] diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.md b/.github/ISSUE_TEMPLATE/01_bug_report.md new file mode 100644 index 0000000000000..ddca1a08888f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01_bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + + + +### Description + + + +### Configuration + + + +### Regression? + + + +### Other information + + diff --git a/.github/ISSUE_TEMPLATE/02_api_proposal.md b/.github/ISSUE_TEMPLATE/02_api_proposal.md new file mode 100644 index 0000000000000..4ba85d6256ab5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02_api_proposal.md @@ -0,0 +1,52 @@ +--- +name: API proposal +about: Propose a change to the public API surface +title: '' +labels: api-suggestion +assignees: '' + +--- + +## Background and Motivation + + + +## Proposed API + + + +## Usage Examples + + + +## Alternative Designs + + + +## Risks + + diff --git a/.github/ISSUE_TEMPLATE/03_performance_issue.md b/.github/ISSUE_TEMPLATE/03_performance_issue.md new file mode 100644 index 0000000000000..6da186f0453df --- /dev/null +++ b/.github/ISSUE_TEMPLATE/03_performance_issue.md @@ -0,0 +1,50 @@ +--- +name: Performance issue +about: Report a performance problem or regression +title: '' +labels: 'tenet-performance' +assignees: '' + +--- + + + +### Description + + + +### Configuration + + + +### Regression? + + + +### Data + + + +### Analysis + + diff --git a/.github/ISSUE_TEMPLATE/04_blank_issue.md b/.github/ISSUE_TEMPLATE/04_blank_issue.md new file mode 100644 index 0000000000000..d1429bfd4c1d9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/04_blank_issue.md @@ -0,0 +1,8 @@ +--- +name: Blank issue +about: Something that doesn't fit the other categories +title: '' +labels: '' +assignees: '' + +--- diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..54d8c5740bad6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,20 @@ +blank_issues_enabled: true +contact_links: + - name: Issue with ASP.NET Core + url: https://github.com/dotnet/aspnetcore/issues/new/choose + about: Please open issues relating to ASP.NET Core in dotnet/aspnetcore. + - name: Issue with .NET SDK + url: https://github.com/dotnet/sdk/issues/new/choose + about: Please open issues relating to the .NET SDK in dotnet/sdk. + - name: Issue with Entity Framework + url: https://github.com/dotnet/efcore/issues/new/choose + about: Please open issues relating to Entity Framework in dotnet/efcore. + - name: Issue with Roslyn compiler + url: https://github.com/dotnet/roslyn/issues/new/choose + about: Please open issues relating to the Roslyn .NET compiler in dotnet/roslyn. + - name: Issue with Windows Forms + url: https://github.com/dotnet/winforms/issues/new/choose + about: Please open issues relating to Windows Forms in dotnet/winforms. + - name: Issue with WPF + url: https://github.com/dotnet/wpf/issues/new/choose + about: Please open issues relating to WPF in dotnet/wpf. diff --git a/Build.proj b/Build.proj index 047ec19ac493d..dc4a15ab5f413 100644 --- a/Build.proj +++ b/Build.proj @@ -5,10 +5,7 @@ Reference the projects for traversal build. Ordering matters here. --> - - - - + - - - - - - - - - - - - - - - $(RepoTasksDir) - $(ArtifactsObjDir)runtime.tasks\Debug\build-semaphore.txt - - - - - + + $([MSBuild]::NormalizeDirectory('$(LibrariesProjectRoot)', 'System.Private.CoreLib', 'src')) + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleAppBuilder', 'Debug', '$(NetCoreAppCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidAppBuilder', 'Debug', '$(NetCoreAppCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(NetCoreAppCurrent)', 'publish')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoAOTCompiler', 'Debug', '$(NetCoreAppCurrent)')) + + $([MSBuild]::NormalizePath('$(AppleAppBuilderDir)', 'AppleAppBuilder.dll')) + $([MSBuild]::NormalizePath('$(AndroidAppBuilderDir)', 'AndroidAppBuilder.dll')) + $([MSBuild]::NormalizePath('$(WasmAppBuilderDir)', 'WasmAppBuilder.dll')) + $([MSBuild]::NormalizePath('$(MonoAOTCompilerDir)', 'MonoAOTCompiler.dll')) + + true - - - false diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index 33b2268a7f2fa..707bd024f8f86 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -820,3 +820,43 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +License notice for DirectX Math Library +--------------------------------------- + +https://github.com/microsoft/DirectXMath/blob/master/LICENSE + + The MIT License (MIT) + +Copyright (c) 2011-2020 Microsoft Corp + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be included in all copies +or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for ldap4net +--------------------------- + +The MIT License (MIT) + +Copyright (c) 2018 Alexander Chermyanin + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/docs/area-owners.md b/docs/area-owners.md index ca92b6fadc6c3..ed99186090f57 100644 --- a/docs/area-owners.md +++ b/docs/area-owners.md @@ -4,8 +4,8 @@ Below table shows the combined area owners on this repository: |-------------|------------------|------------------| | area-AssemblyLoader-coreclr | @jeffschwMSFT @vitek-karas | | | area-CodeGen-coreclr | @BruceForstall @dotnet/jit-contrib | | -| area-CrossGen/NGEN-coreclr | @fadimounir | | -| area-crossgen2-coreclr | @nattress @MichalStrehovsky @trylek @fadimounir | | +| area-CrossGen/NGEN-coreclr | @nattress | | +| area-crossgen2-coreclr | @nattress @trylek @dotnet/crossgen-contrib | | | area-DependencyModel | @eerhardt | Microsoft.Extensions.DependencyModel | | area-Diagnostics-coreclr | @tommcdon | | | area-ExceptionHandling-coreclr | @janvorli | | @@ -30,9 +30,9 @@ Below table shows the combined area owners on this repository: | area-TieredCompilation-coreclr | @kouvel | | | area-Tizen | @alpencolt @gbalykov | | | area-Tracing-coreclr | @sywhang @josalem | | -| area-TypeSystem-coreclr | @davidwrighton @MichalStrehovsky @fadimounir | | +| area-TypeSystem-coreclr | @davidwrighton @MichalStrehovsky @janvorli @mangod9 | | | area-UWP | @nattress | UWP-specific issues including Microsoft.NETCore.UniversalWindowsPlatform and Microsoft.Net.UWPCoreRuntimeSdk | -| area-VM-coreclr | @jeffschwMSFT | | +| area-VM-coreclr | @mangod9 | | | area-AssemblyLoader-mono | @CoffeeFlux | | | area-Codegen-meta-mono | @vargaz | | | area-Codegen-JIT-mono | @SamMonoRT | | diff --git a/docs/coding-guidelines/api-guidelines/nullability.md b/docs/coding-guidelines/api-guidelines/nullability.md index 062189469fad1..997c2b38ac79f 100644 --- a/docs/coding-guidelines/api-guidelines/nullability.md +++ b/docs/coding-guidelines/api-guidelines/nullability.md @@ -95,6 +95,9 @@ The C# compiler respects a set of attributes that impact its flow analysis. We - **DO** annotate properties where a getter will never return `null` but a setter allows `null` as being non-nullable but also `[AllowNull]`. - **DO** annotate properties where a getter may return `null` but a setter throws for `null` as being nullable but also `[DisallowNull]`. - **DO** add `[NotNullWhen(true)]` to nullable arguments of `Try` methods that will definitively be non-`null` if the method returns `true`. For example, if `Int32.TryParse(string? s)` returns `true`, `s` is known to not be `null`, and so the method should be `public static bool TryParse([NotNullWhen(true)] string? s, out int result)`. +- **DO** add `[NotNullIfNotNull(string)]` if nullable ref argument will be non-`null` upon exit, when an other argument passed evaluated to non-`null`, pass that argument name as string. Example: `public void Exchange([NotNullIfNotNull("value")] ref object? location, object? value);`. +- **DO** add `[return: NotNullIfNotNull(string)]` if a method would not return `null` in case an argument passed evaluated to non-`null`, pass that argument name as string. Example: `[return: NotNullIfNotNull("name")] public string? FormatName(string? name);` +- **DO** add `[MemberNotNull(params string[])]` for a helper method which initializes member field(s), pass the field name. Example: `[MemberNotNull("_buffer")] private void InitializeBuffer()` ## Code Review Guidance diff --git a/docs/coding-guidelines/project-guidelines.md b/docs/coding-guidelines/project-guidelines.md index 1f9793eb298e3..f0050a5858809 100644 --- a/docs/coding-guidelines/project-guidelines.md +++ b/docs/coding-guidelines/project-guidelines.md @@ -97,6 +97,46 @@ When building an individual project the `BuildTargetFramework` and `TargetOS` wi - .NET Framework latest -> `$(NetFrameworkCurrent)-Windows_NT` # Library project guidelines + +## TargetFramework conditions +`TargetFramework` conditions should be avoided in the first PropertyGroup as that causes DesignTimeBuild issues: https://github.com/dotnet/project-system/issues/6143 + +1. Use an equality check if the TargetFramework isn't overloaded with the OS portion. +Example: +``` + + netstandard2.0;netstandard2.1 + +... +``` +2. Use a StartsWith when you want to test for multiple .NETStandard or .NETFramework versions. +Example: +``` + + netstandard2.0;netstandard2.1 + +... +``` +4. Use negations if that makes the conditions easier. +Example: +``` + + netstandard2.0;net461;net472;net5.0 + +... +``` + +## Directory layout + Library projects should use the following directory layout. ``` diff --git a/docs/coding-guidelines/updating-ref-source.md b/docs/coding-guidelines/updating-ref-source.md index d702db01f695f..6ca0e56cc2629 100644 --- a/docs/coding-guidelines/updating-ref-source.md +++ b/docs/coding-guidelines/updating-ref-source.md @@ -2,16 +2,16 @@ This document provides the steps you need to take to update the reference assemb ## For most assemblies within libraries -1. Implement the API in the source assembly and [build it](../workflow/building/libraries/README.md#building-individual-libraries). -2. Run the following command (from the src directory) `msbuild /t:GenerateReferenceSource` to update the reference assembly**. +1. Implement the API in the source assembly and [build it](../workflow/building/libraries/README.md#building-individual-libraries). Note that when adding new public types, this might fail with a `TypeMustExist` error. The deadlock can be worked around by disabling the `RunApiCompat` property: `dotnet build /p:RunApiCompat=false`. +2. Run the following command (from the src directory) `msbuild /t:GenerateReferenceAssemblySource` to update the reference assembly**. 3. Navigate to the ref directory and build the reference assembly. 4. Add, build, and run tests. -** **Note:** If you already added the new API to the reference source, re-generating it (after building the source assembly) will update it to be fully qualified and placed in the correct order. This can be done by running the `GenerateReferenceSource` command from the ref directory. +** **Note:** If you already added the new API to the reference source, re-generating it (after building the source assembly) will update it to be fully qualified and placed in the correct order. This can be done by running the `GenerateReferenceAssemblySource` command from the ref directory. ## For System.Runtime These steps can also be applied to some unique assemblies which depend on changes in System.Private.Corelib. (partial facades like System.Memory, for example). -1) Run `dotnet build -c Release /t:GenerateReferenceSource` from the System.Runtime/ref directory. +1) Run `dotnet build -c Release /t:GenerateReferenceAssemblySource` from the System.Runtime/ref directory. 2) Filter out all unrelated changes and extract the changes you care about (ignore certain attributes being removed). Generally, this step is not required for other reference assemblies. diff --git a/docs/design/coreclr/botr/README.md b/docs/design/coreclr/botr/README.md index fde9992daeb9c..4c6e6cb5b3bf6 100644 --- a/docs/design/coreclr/botr/README.md +++ b/docs/design/coreclr/botr/README.md @@ -19,7 +19,7 @@ Below is a table of contents. - [Method Descriptor](method-descriptor.md) - [Virtual Stub Dispatch](virtual-stub-dispatch.md) - [Stack Walking](stackwalking.md) -- [Mscorlib and Calling Into the Runtime](mscorlib.md) +- [`System.Private.CoreLib` and calling into the runtime](corelib.md) - [Data Access Component (DAC) Notes](dac-notes.md) - [Profiling](profiling.md) - [Implementing Profilability](profilability.md) diff --git a/docs/design/coreclr/botr/corelib.md b/docs/design/coreclr/botr/corelib.md new file mode 100644 index 0000000000000..9b6f5dbb7f4c2 --- /dev/null +++ b/docs/design/coreclr/botr/corelib.md @@ -0,0 +1,352 @@ +`System.Private.CoreLib` and calling into the runtime +=== + +# Introduction + +`System.Private.CoreLib.dll` is the assembly for defining the core parts of the type system, and a good portion of the Base Class Library in .NET Framework. It was originally named `mscorlib` in .NET Core, though many places in the code and documentation still refer to it as `mscorlib`. This document will endeavour to stick to using `System.Private.CoreLib` or CoreLib. Base data types live in this assembly, and it has a tight coupling with the CLR. Here you will learn exactly how and why CoreLib is special and the basics about calling into the CLR from managed code via QCall and FCall methods. It also discusses calling from within the CLR into managed code. + +## Dependencies + +Since CoreLib defines base data types like `Object`, `Int32`, and `String`, CoreLib cannot depend on other managed assemblies. However, there is a strong dependency between CoreLib and the CLR. Many of the types in CoreLib need to be accessed from native code, so the layout of many managed types is defined both in managed code and in native code inside the CLR. Additionally, some fields may be defined only in Debug, Checked, or Release builds, so typically CoreLib must be compiled separately for each type of build. + +`System.Private.CoreLib.dll` builds separately for 64 bit and 32 bit, and some public constants it exposes differ by bitness. By using these constants, such as `IntPtr.Size`, most libraries above CoreLib should not need to build separately for 32 bit vs. 64 bit. + +## What makes `System.Private.CoreLib` special? + +CoreLib has several unique properties, many of which are due to its tight coupling to the CLR. + +- CoreLib defines the core types necessary to implement the CLR's Virtual Object System, such as the base data types (`Object`, `Int32`, `String`, etc). +- The CLR must load CoreLib on startup to load certain system types. +- Can only have one CoreLib loaded in the process at a time, due to layout issues. Loading multiple CoreLibs would require formalizing a contract of behavior, FCall methods, and datatype layout between CLR and CoreLib, and keeping that contract relatively stable across versions. +- CoreLib's types are used heavily for native interop and managed exceptions should map correctly to native error codes/formats. +- The CLR's multiple JIT compilers may special case a small group of certain methods in CoreLib for performance reasons, both in terms of optimizing away the method (such as `Math.Cos(double)`), or calling a method in peculiar ways (such as `Array.Length`, or some implementation details on `StringBuilder` for getting the current thread). +- CoreLib will need to call into native code, via P/Invoke where appropriate, primarily into the underlying operating system or occasionally a platform adaptation layer. +- CoreLib will require calling into the CLR to expose some CLR-specific functionality, such as triggering a garbage collection, to load classes, or to interact with the type system in a non-trivial way. This requires a bridge between managed code and native, "manually managed" code within the CLR. +- The CLR will need to call into managed code to call managed methods, and to get at certain functionality that is only implemented in managed code. + +# Interface between managed and CLR code + +To reiterate, the needs of managed code in CoreLib include: + +- The ability to access fields of some managed data structures in both managed code and "manually managed" code within the CLR. +- Managed code must be able to call into the CLR. +- The CLR must be able to call managed code. + +To implement these, we need a way for the CLR to specify and optionally verify the layout of a managed object in native code, a managed mechanism for calling into native code, and a native mechanism for calling into managed code. + +The managed mechanism for calling into native code must also support the special managed calling convention used by `String`'s constructors, where the constructor allocates the memory used by the object (instead of the typical convention where the constructor is called after the GC allocates memory). + +The CLR provides a [`mscorlib` binder](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/binder.cpp) internally, providing a mapping between unmanaged types and fields to managed types and fields. The binder will look up and load classes and allows the calling of managed methods. It also performs simple verification to ensure the correctness of any layout information specified in both managed and native code. The binder ensures that the managed class attempting to load exists in mscorlib, has been loaded, and the field offsets are correct. It also needs the ability to differentiate between method overloads with different signatures. + +# Calling from managed to native code + +Two techniques exist for calling into the CLR from managed code. FCall allows you to call directly into the CLR code, and provides a lot of flexibility in terms of manipulating objects, though it is easy to cause GC holes by not tracking object references correctly. QCall also allows you to call into the CLR via the P/Invoke, but is much harder to accidentally mis-use. FCalls are identified in managed code as extern methods with the [`MethodImplOptions.InternalCall`](https://docs.microsoft.com/dotnet/api/system.runtime.compilerservices.methodimploptions) bit set. QCalls are marked `static extern` methods similar to regular P/Invokes, but are directed toward a library called `"QCall"`. + +There is a small variant of FCall called HCall (for Helper call) for implementing JIT helpers. The HCall is intended for doing things like accessing multi-dimensional array elements, range checks, etc. The only difference between HCall and FCall is that HCall methods won't show up in an exception stack trace. + +### Choosing between FCall, QCall, P/Invoke, and writing in managed code + +First, remember that you should be writing as much as possible in managed code. You avoid a raft of potential GC hole issues, you get a better debugging experience, and the code is often simpler. + +Reasons to write FCalls in the past generally fell into three camps: missing language features, better performance, or implementing unique interactions with the runtime. C# now has almost every useful language feature that you could get from C++, including unsafe code and stack-allocated buffers, and this eliminates the first two reasons for FCalls. We have ported some parts of the CLR that were heavily reliant on FCalls to managed code in the past (such as Reflection, some Encoding, and String operations) and we intend to continue this momentum. + +If the only reason you're defining a FCall method is to call a native method, you should be using P/Invoke to call the method directly. [P/Invoke](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute) is the public native method interface and should be doing everything you need in a correct manner. + +If you still need to implement a feature inside the runtime, consider if there is a way to reduce the frequency of transitioning to native code. Can you write the common case in managed and only call into native for some rare corner cases? You're usually best off keeping as much as possible in managed code. + +QCalls are the preferred mechanism going forward. You should only use FCalls when you are "forced" to. This happens when there is common "short path" through the code that is important to optimize. This short path should not be more than a few hundred instructions, cannot allocate GC memory, take locks or throw exceptions (`GC_NOTRIGGER`, `NOTHROWS`). In all other circumstances (and especially when you enter a FCall and then simply erect HelperMethodFrame), you should be using QCall. + +FCalls were specifically designed for short paths of code that must be optimized. They allowed explicit control over when erecting a frame was done. However, it is error prone and not worth the complexity for many APIs. QCalls are essentially P/Invokes into the CLR. In the event the performance of an FCall is required consider creating a QCall and marking it with [`SuppressGCTransitionAttribute`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.suppressgctransitionattribute). + +As a result, QCalls give you some advantageous marshaling for `SafeHandle`s automatically – your native method just takes a `HANDLE` type, and can be used without worrying whether someone will free the handle while in that method body. The resulting FCall method would need to use a `SafeHandleHolder` and may need to protect the `SafeHandle`, etc. Leveraging the P/Invoke marshaler can avoid this additional plumbing code. + +## QCall functional behavior + +QCalls are very much like a normal P/Invoke from CoreLib to CLR. Unlike FCalls, QCalls will marshal all arguments as unmanaged types like a normal P/Invoke. QCall also switch to preemptive GC mode like a normal P/Invoke. These two features should make QCalls easier to write reliably compared to FCalls. QCalls are not prone to GC holes and GC starvation bugs that are common with FCalls. + +QCalls perform better than FCalls that erect a `HelperMethodFrame`. The overhead is about 1.4x less compared to FCall w/ `HelperMethodFrame` overhead on x86 and x64. + +The preferred types for QCall arguments are primitive types that are efficiently handled by the P/Invoke marshaler (`INT32`, `LPCWSTR`, `BOOL`). Notice that `BOOL` is the correct boolean flavor for QCall arguments. On the other hand, `CLR_BOOL` is the correct boolean flavor for FCall arguments. + +The pointers to common unmanaged EE structures should be wrapped into handle types. This is to make the managed implementation type safe and avoid falling into unsafe C# everywhere. See AssemblyHandle in [vm\qcall.h][qcall] for an example. + +[qcall]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/qcall.h + +Passing object references in and out of QCalls is done by wrapping a pointer to a local variable in a handle. It is intentionally cumbersome and should be avoided if reasonably possible. See the `StringHandleOnStack` in the example below. Returning objects, especially strings, from QCalls is the only common pattern where passing the raw objects is widely acceptable. (For reasoning on why this set of restrictions helps make QCalls less prone to GC holes, read the ["GC Holes, FCall, and QCall"](#gcholes) section below.) + +### QCall example - managed + +Do not replicate the comments into your actual QCall implementation. This is for illustrative purposes. + +```CSharp +class Foo +{ + // All QCalls should have the following DllImport attribute + [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] + + // QCalls should always be static extern. + private static extern bool BarInternal(int flags, string inString, StringHandleOnStack retString); + + // Many QCalls have a thin managed wrapper around them to perform + // as much work prior to the transition as possible. An example would be + // argument validation which is easier in managed than native code. + public string Bar(int flags) + { + if (flags != 0) + throw new ArgumentException("Invalid flags"); + + string retString = null; + // The strings are returned from QCalls by taking address + // of a local variable using StringHandleOnStack + if (!BarInternal(flags, this.Id, new StringHandleOnStack(ref retString))) + FatalError(); + + return retString; + } +} +``` + +### QCall example - unmanaged + +Do not replicate the comments into your actual QCall implementation. + +The QCall entrypoint has to be registered in tables in [vm\ecalllist.h][ecalllist] using `QCFuncEntry` macro. See ["Registering your QCall or FCall Method"](#register) below. + +[ecalllist]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/ecalllist.h + +```C++ +class FooNative +{ +public: + // All QCalls should be static and tagged with QCALLTYPE + static + BOOL QCALLTYPE BarInternal(int flags, LPCWSTR wszString, QCall::StringHandleOnStack retString); +}; + +BOOL QCALLTYPE FooNative::BarInternal(int flags, LPCWSTR wszString, QCall::StringHandleOnStack retString) +{ + // All QCalls should have QCALL_CONTRACT. + // It is alias for THROWS; GC_TRIGGERS; MODE_PREEMPTIVE. + QCALL_CONTRACT; + + // Optionally, use QCALL_CHECK instead and the expanded form of the contract + // if you want to specify preconditions: + // CONTRACTL { + // QCALL_CHECK; + // PRECONDITION(wszString != NULL); + // } CONTRACTL_END; + + // The only line between QCALL_CONTRACT and BEGIN_QCALL + // should be the return value declaration if there is one. + BOOL retVal = FALSE; + + // The body has to be enclosed in BEGIN_QCALL/END_QCALL macro. + // It is necessary for exception handling. + BEGIN_QCALL; + + // Argument validation would ideally be in managed, but in some cases + // needs to be done in native. If argument validation is done in + // managed asserting in native is warranted. + _ASSERTE(flags != 0); + + // No need to worry about GC moving strings passed into QCall. + // Marshalling pins them for us. + printf("%S\n", wszString); + + // This is the most efficient way to return strings back + // to managed code. No need to use StringBuilder. + retString.Set(L"Hello"); + + // You can not return from inside of BEGIN_QCALL/END_QCALL. + // The return value has to be passed out in helper variable. + retVal = TRUE; + + END_QCALL; + + return retVal; +} +``` + +## FCall functional behavior + +FCalls allow more flexibility in terms of passing object references around, but with higher code complexity and more opportunities to make mistakes. Additionally, FCall methods must either erect a helper method frame along their common code paths, or for any FCall of non-trivial length, explicitly poll for whether a garbage collection must occur. Failing to do so will lead to starvation issues if managed code repeatedly calls the FCall method in a tight loop, because FCalls execute while the thread only allows the GC to run in a cooperative manner. + +FCalls require a lot of boilerplate code, too much to describe here. Refer to [fcall.h][fcall] for details. + +[fcall]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/fcall.h + +### GC holes, FCall, and QCall + +A more complete discussion on GC holes can be found in the [CLR Code Guide](../../../coding-guidelines/clr-code-guide.md). Look for ["Is your code GC-safe?"](../../../coding-guidelines/clr-code-guide.md#2.1). This tailored discussion motivates some of the reasons why FCall and QCall have some of their strange conventions. + +Object references passed as parameters to FCall methods are not GC-protected, meaning that if a GC occurs, those references will point to the old location in memory of an object, not the new location. For this reason, FCalls usually follow the discipline of accepting something like `StringObject*` as their parameter type, then explicitly converting that to a `STRINGREF` before doing operations that may trigger a GC. If you expect to use an object reference later, you must GC protect object references before triggering a GC. + +All GC heap allocations within an FCall method must happen within a helper method frame. If you allocate memory on the GC heap, the GC may collect dead objects and move objects around in unpredictable ways, with some low probability. For this reason, you must manually report any object references in your method to the GC, so that if a garbage collection occurs, your object reference will be updated to refer to the new location in memory. Any pointers into managed objects (like arrays or Strings) within your code will not be updated automatically, and must be re-fetched after any operation that may allocate memory and before your first usage. Reporting a reference can be done via the `GCPROTECT_*` macros or as parameters when erecting a helper method frame. + +Failing to properly report an `OBJECTREF` or to update an interior pointer is commonly referred to as a "GC hole", because the `OBJECTREF` class will do some validation that it points to a valid object every time you dereference it in Debug and Checked builds. When an `OBJECTREF` pointing to an invalid object is dereferenced, an assert will trigger saying something like "Detected an invalid object reference. Possible GC hole?". This assert is unfortunately easy to hit when writing "manually managed" code. + +Note that QCall's programming model is restrictive to sidestep GC holes by forcing you to pass in the address of an object reference on the stack. This guarantees that the object reference is GC protected by the JIT's reporting logic, and that the actual object reference will not move because it is not allocated in the GC heap. QCall is our recommended approach, precisely because it makes GC holes harder to write. + +### FCall epilog walker for x86 + +The managed stack walker needs to be able to find its way from FCalls. It is relative easy on newer platforms that define conventions for stack unwinding as part of the ABI. The stack unwinding conventions are not defined by an ABI for x86. The runtime works around this by implementing an epilog walker. The epilog walker computes the FCall return address and callee save registers by simulating the FCall execution. This imposes limits on what constructs are allowed in the FCall implementation. + +Complex constructs like stack allocated objects with destructors or exception handling in the FCall implementation may confuse the epilog walker. This can lead to GC holes or crashes during stack walking. There is no comprehensive list of what constructs should be avoided to prevent this class of bugs. An FCall implementation that is fine one day may break with the next C++ compiler update. We depend on stress runs and code coverage to find bugs in this area. + +Setting a breakpoint inside an FCall implementation may confuse the epilog walker. It leads to an "Invalid breakpoint in a helpermethod frame epilog" assert inside [vm\i386\gmsx86.cpp](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/i386/gmsx86.cpp). + +### FCall example – managed + +Here's a real-world example from the `String` class: + +```CSharp +public partial sealed class String +{ + [MethodImpl(MethodImplOptions.InternalCall)] + private extern string? IsInterned(); + + public static string? IsInterned(string str) + { + if (str == null) + { + throw new ArgumentNullException(nameof(str)); + } + + return str.IsInterned(); + } +} +``` + +### FCall example – unmanaged + +The FCall entrypoint has to be registered in tables in [vm\ecalllist.h][ecalllist] using `FCFuncEntry` macro. See ["Registering your QCall or FCall Method"](#register). + +This method is an instance method in managed code, with the "this" parameter passed as the first argument. We use `StringObject*` as the argument type, then copy it into a `STRINGREF` so we get some error checking when we use it. + +```C++ +FCIMPL1(Object*, AppDomainNative::IsStringInterned, StringObject* pStringUNSAFE) +{ + FCALL_CONTRACT; + + STRINGREF refString = ObjectToSTRINGREF(pStringUNSAFE); + STRINGREF* prefRetVal = NULL; + + HELPER_METHOD_FRAME_BEGIN_RET_1(refString); + + if (refString == NULL) + COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); + + prefRetVal = GetAppDomain()->IsStringInterned(&refString); + + HELPER_METHOD_FRAME_END(); + + if (prefRetVal == NULL) + return NULL; + + return OBJECTREFToObject(*prefRetVal); +} +FCIMPLEND +``` + +## Registering your QCall or FCall method + +The CLR must know the name of your QCall and FCall methods, both in terms of the managed class and method names, as well as which native methods to call. That is done in [ecalllist.h][ecalllist], with two arrays. The first array maps namespace and class names to an array of function elements. That array of function elements then maps individual method names and signatures to function pointers. + +Say we defined an FCall method for `String.IsInterned()`, in the example above. First, we need to ensure that we have an array of function elements for the String class. + +``` C++ +// Note these have to remain sorted by name:namespace pair + ... + FCClassElement("String", "System", gStringFuncs) + ... +``` + +Second, we must then ensure that `gStringFuncs` contains a proper entry for `IsInterned`. Note that if a method name has multiple overloads then we can specify a signature: + +```C++ +FCFuncStart(gStringFuncs) + ... + FCFuncElement("IsInterned", AppDomainNative::IsStringInterned) + ... +FCFuncEnd() +``` + +There is a parallel `QCFuncElement` macro. + +## Naming convention + +FCalls and QCalls should not be publicly exposed. Instead wrap the actual FCall or QCall and provide a API approved name. + +The internal FCall or QCall should use the "Internal" suffix to disambiguate the name of the FCall or QCall from public entry point (e.g. the public entry point does error checking and then calls shared worker function with exactly same signature). This is no different from how you would deal with this situation in pure managed code in BCL. + +# Types with a managed/unmanaged duality + +Certain managed types must have a representation available in both managed and native code. You could ask whether the canonical definition of a type is in managed code or native code within the CLR, but the answer doesn't matter – the key thing is they must both be identical. This will allow the CLR's native code to access fields within a managed object in a fast and efficient manner. There is a more complex way of using essentially the CLR's equivalent of Reflection over `MethodTable`s and `FieldDesc`s to retrieve field values, but this doesn't perform as well as desired and isn't very usable. For commonly used types, it makes sense to declare a data structure in native code and keep the two in sync. + +The CLR provides a binder for this purpose. After you define your managed and native classes, you should provide some clues to the binder to help ensure that the field offsets remain the same to quickly spot when someone accidentally adds a field to only one definition of a type. + +In [mscorlib.h][mscorlib.h], use macros ending in "_U" to describe a type, the name of fields in managed code, and the name of fields in a corresponding native data structure. Additionally, you can specify a list of methods, and reference them by name when you attempt to call them later. + +[mscorlib.h]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/mscorlib.h + +``` C++ +DEFINE_CLASS_U(SAFE_HANDLE, Interop, SafeHandle, SafeHandle) +DEFINE_FIELD(SAFE_HANDLE, HANDLE, handle) +DEFINE_FIELD_U(SAFE_HANDLE, STATE, _state, SafeHandle, m_state) +DEFINE_FIELD_U(SAFE_HANDLE, OWNS_HANDLE, _ownsHandle, SafeHandle, m_ownsHandle) +DEFINE_FIELD_U(SAFE_HANDLE, INITIALIZED, _fullyInitialized, SafeHandle, m_fullyInitialized) +DEFINE_METHOD(SAFE_HANDLE, GET_IS_INVALID, get_IsInvalid, IM_RetBool) +DEFINE_METHOD(SAFE_HANDLE, RELEASE_HANDLE, ReleaseHandle, IM_RetBool) +DEFINE_METHOD(SAFE_HANDLE, DISPOSE, Dispose, IM_RetVoid) +DEFINE_METHOD(SAFE_HANDLE, DISPOSE_BOOL, Dispose, IM_Bool_RetVoid) +``` + +Then, you can use the `REF` template to create a type name like `SAFEHANDLEREF`. All the error checking from `OBJECTREF` is built into the `REF` template, and you can freely dereference this `SAFEHANDLEREF` and use fields off of it in native code. You still must GC protect these references. + +# Calling into managed code from unmanaged code + +Clearly there are places where the CLR must call into managed code from native. For this purpose, we have added a `MethodDescCallSite` class to handle a lot of plumbing for you. Conceptually, all you need to do is find the `MethodDesc*` for the method you want to call, find a managed object for the "this" pointer (if you're calling an instance method), pass in an array of arguments, and deal with the return value. Internally, you'll need to potentially toggle your thread's state to allow the GC to run in preemptive mode, etc. + +Here's a simplified example. Note how this instance uses the binder described in the previous section to call `SafeHandle`'s virtual `ReleaseHandle` method. + +```C++ +void SafeHandle::RunReleaseMethod(SafeHandle* psh) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } CONTRACTL_END; + + SAFEHANDLEREF sh(psh); + + GCPROTECT_BEGIN(sh); + + MethodDescCallSite releaseHandle(s_pReleaseHandleMethod, METHOD__SAFE_HANDLE__RELEASE_HANDLE, (OBJECTREF*)&sh, TypeHandle(), TRUE); + + ARG_SLOT releaseArgs[] = { ObjToArgSlot(sh) }; + if (!(BOOL)releaseHandle.Call_RetBool(releaseArgs)) { + MDA_TRIGGER_ASSISTANT(ReleaseHandleFailed, ReportViolation)(sh->GetTypeHandle(), sh->m_handle); + } + + GCPROTECT_END(); +} +``` + +# Interactions with other subsystems + +## Debugger + +One limitation of FCalls today is that you cannot easily debug both managed code and FCalls easily in Visual Studio's Interop (or mixed mode) debugging. Setting a breakpoint today in an FCall and debugging with Interop debugging just doesn't work. This most likely won't be fixed. + +# Physical architecture + +When the CLR starts up, CoreLib is loaded by a method called `SystemDomain::LoadBaseSystemClasses()`. Here, the base data types and other similar classes (like `Exception`) are loaded, and appropriate global pointers are set up to refer to CoreLib's types. + +For FCalls, look in [fcall.h][fcall] for infrastructure, and [ecalllist.h][ecalllist] to properly inform the runtime about your FCall method. + +For QCalls, look in [qcall.h][qcall] for associated infrastructure, and [ecalllist.h][ecalllist] to properly inform the runtime about your QCall method. + +More general infrastructure and some native type definitions can be found in [object.h][object.h]. The binder uses `mscorlib.h` to associate managed and native classes. + +[object.h]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/object.h diff --git a/docs/design/coreclr/botr/method-descriptor.md b/docs/design/coreclr/botr/method-descriptor.md index ea5123bdc4b9a..7d3f24ccf40f1 100644 --- a/docs/design/coreclr/botr/method-descriptor.md +++ b/docs/design/coreclr/botr/method-descriptor.md @@ -42,7 +42,7 @@ Used for less common IL methods that have generic instantiation or that do not h **FCall** -Internal methods implemented in unmanaged code. These are [methods marked with MethodImplAttribute(MethodImplOptions.InternalCall) attribute](mscorlib.md), delegate constructors and tlbimp constructors. +Internal methods implemented in unmanaged code. These are [methods marked with MethodImplAttribute(MethodImplOptions.InternalCall) attribute](corelib.md), delegate constructors and tlbimp constructors. **NDirect** diff --git a/docs/design/coreclr/botr/mscorlib.md b/docs/design/coreclr/botr/mscorlib.md deleted file mode 100644 index c2d995567f491..0000000000000 --- a/docs/design/coreclr/botr/mscorlib.md +++ /dev/null @@ -1,355 +0,0 @@ -Mscorlib and Calling Into the Runtime -=== - -Author: Brian Grunkemeyer ([@briangru](https://github.com/briangru)) - 2006 - -# Introduction - -Mscorlib is the assembly for defining the core parts of the type system, and a good portion of the Base Class Library in .NET Framework. It has been renamed to System.Private.CoreLib in .NET Core, though many places in the code and documentation still refer to it as mscorlib. Base data types live in this assembly, and it has a tight coupling with the CLR. Here you will learn exactly how & why mscorlib.dll is special, and the basics about calling into the CLR from managed code via QCall and FCall methods. It also discusses calling from within the CLR into managed code. - -## Dependencies - -Since mscorlib defines base data types like Object, Int32, and String, mscorlib cannot depend on other managed assemblies. However, there is a strong dependency between mscorlib and the CLR. Many of the types in mscorlib need to be accessed from native code, so the layout of many managed types is defined both in managed code and in native code inside the CLR. Additionally, some fields may be defined only in debug or checked builds, so typically mscorlib must be compiled separately for checked vs. retail builds. - -For 64 bit platforms, some constants are also defined at compile time. So a 64 bit mscorlib.dll is slightly different from a 32 bit mscorlib.dll. Due to these constants, such as IntPtr.Size, most libraries above mscorlib should not need to build separately for 32 bit vs. 64 bit. - -## What Makes Mscorlib Special? - -Mscorlib has several unique properties, many of which are due to its tight coupling to the CLR. - -- Mscorlib defines the core types necessary to implement the CLR's Virtual Object System, such as the base data types (Object, Int32, String, etc). -- The CLR must load mscorlib on startup to load certain system types. -- Can only have one mscorlib loaded in the process at a time, due to layout issues. Loading multiple mscorlibs would require formalizing a contract of behavior, FCall methods, and datatype layout between CLR & mscorlib, and keeping that contract relatively stable across versions. -- Mscorlib's types will be used heavily for native interop, and managed exceptions should map correctly to native error codes/formats. -- The CLR's multiple JIT compilers may special case a small group of certain methods in mscorlib for performance reasons, both in terms of optimizing away the method (such as Math.Cos(double)), or calling a method in peculiar ways (such as Array.Length, or some implementation details on StringBuilder for getting the current thread). -- Mscorlib will need to call into native code, via P/Invoke where appropriate, primarily into the underlying operating system or occasionally a platform adaptation layer. -- Mscorlib will require calling into the CLR to expose some CLR-specific functionality, such as triggering a garbage collection, to load classes, or to interact with the type system in a non-trivial way. This requires a bridge between managed code and native, "manually managed" code within the CLR. -- The CLR will need to call into managed code to call managed methods, and to get at certain functionality that is only implemented in managed code. - -# Interface between managed & CLR code - -To reiterate, the needs of managed code in mscorlib include: - -- The ability to access fields of some managed data structures in both managed code and "manually managed" code within the CLR -- Managed code must be able to call into the CLR -- The CLR must be able to call managed code. - -To implement these, we need a way for the CLR to specify and optionally verify the layout of a managed object in native code, a managed mechanism for calling into native code, and a native mechanism for calling into managed code. - -The managed mechanism for calling into native code must also support the special managed calling convention used by String's constructors, where the constructor allocates the memory used by the object (instead of the typical convention where the constructor is called after the GC allocates memory). - -The CLR provides a [mscorlib binder](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/binder.cpp) internally, providing a mapping between unmanaged types and fields to managed types & fields. The binder will look up & load classes, allow you to call managed methods. It also does some simple verification to ensure the correctness of any layout information specified in both managed & native code. The binder ensures that the managed class you're attempting to use exists in mscorlib, has been loaded, and the field offsets are correct. It also needs the ability to differentiate between method overloads with different signatures. - -# Calling from managed to native code - -We have two techniques for calling into the CLR from managed code. FCall allows you to call directly into the CLR code, and provides a lot of flexibility in terms of manipulating objects, though it is easy to cause GC holes by not tracking object references correctly. QCall allows you to call into the CLR via the P/Invoke, and is much harder to accidentally mis-use than FCall. FCalls are identified in managed code as extern methods with the MethodImplOptions.InternalCall bit set. QCalls are _static_ extern methods that look like regular P/Invokes, but to a library called "QCall". - -There is a small variant of FCall called HCall (for Helper call) for implementing JIT helpers, for doing things like accessing multi-dimensional array elements, range checks, etc. The only difference between HCall and FCall is that HCall methods won't show up in an exception stack trace. - -### Choosing between FCall, QCall, P/Invoke, and writing in managed code - -First, remember that you should be writing as much as possible in managed code. You avoid a raft of potential GC hole issues, you get a good debugging experience, and the code is often simpler. It also is preparation for ongoing refactoring of mscorlib into smaller layered fully [managed libraries](https://github.com/dotnet/runtime/src/libraries). - -Reasons to write FCalls in the past generally fell into three camps: missing language features, better performance, or implementing unique interactions with the runtime. C# now has almost every useful language feature that you could get from C++, including unsafe code & stack-allocated buffers, and this eliminates the first two reasons for FCalls. We have ported some parts of the CLR that were heavily reliant on FCalls to managed code in the past (such as Reflection and some Encoding & String operations), and we want to continue this momentum. We may port our number formatting & String comparison code to managed in the future. - -If the only reason you're defining a FCall method is to call a native Win32 method, you should be using P/Invoke to call Win32 directly. P/Invoke is the public native method interface, and should be doing everything you need in a correct manner. - -If you still need to implement a feature inside the runtime, now consider if there is a way to reduce the frequency of transitioning to native code. Can you write the common case in managed, and only call into native for some rare corner cases? You're usually best off keeping as much as possible in managed code. - -QCalls are the preferred mechanism going forward. You should only use FCalls when you are "forced" to. This happens when there is common "short path" through the code that is important to optimize. This short path should not be more than a few hundred instructions, cannot allocate GC memory, take locks or throw exceptions (GC_NOTRIGGER, NOTHROWS). In all other circumstances (and especially when you enter a FCall and then simply erect HelperMethodFrame), you should be using QCall. - -FCalls were specifically designed for short paths of code that must be optimized. They allowed you to take explicit control over when erecting a frame was done. However it is error prone and is not worth it for many APIs. QCalls are essentially P/Invokes into CLR. - -As a result, QCalls give you some advantageous marshaling for SafeHandles automatically – your native method just takes a HANDLE type, and can use it without worrying whether someone will free the handle while you are in that method body. The resulting FCall method would need to use a SafeHandleHolder, and may need to protect the SafeHandle, etc. Leveraging the P/Invoke marshaler can avoid this additional plumbing code. - -## QCall Functional Behavior - -QCalls are very much like a normal P/Invoke from mscorlib.dll to CLR. Unlike FCalls, QCalls will marshal all arguments as unmanaged types like a normal P/Invoke. QCall also switch to preemptive GC mode like a normal P/Invoke. These two features should make QCalls easier to write reliably compared to FCalls. QCalls are not prone to GC holes and GC starvation bugs that are common with FCalls. - -QCalls perform better than FCalls that erect a HelperMethodFrame. The overhead is about 1.4x less compared to FCall w/ HelperMethodFrame overhead on x86 and x64. - -The preferred types for QCall arguments are primitive types that are efficiently handled by the P/Invoke marshaler (INT32, LPCWSTR, BOOL). Notice that BOOL is the correct boolean flavor for QCall arguments. On the other hand, CLR_BOOL is the correct boolean flavor for FCall arguments. - -The pointers to common unmanaged EE structures should be wrapped into handle types. This is to make the managed implementation type safe and avoid falling into unsafe C# everywhere. See AssemblyHandle in [vm\qcall.h][qcall] for an example. - -[qcall]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/qcall.h - -There is a way to pass a raw object references in and out of QCalls. It is done by wrapping a pointer to a local variable in a handle. It is intentionally cumbersome and should be avoided if reasonably possible. See the StringHandleOnStack in the example below. Returning objects, especially strings, from QCalls is the only common pattern where passing the raw objects is widely acceptable. (For reasoning on why this set of restrictions helps make QCalls less prone to GC holes, read the "GC Holes, FCall, and QCall" section below.) - -### QCall Example - Managed Part - -Do not replicate the comments into your actual QCall implementation. This is for illustrative purposes. - - class Foo - { - // All QCalls should have the following DllImport attribute - [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] - // QCalls should always be static extern. - private static extern bool Bar(int flags, string inString, StringHandleOnStack retString); - - // Many QCalls have a thin managed wrapper around them to expose them to - // the world in more meaningful way. - public string Bar(int flags) - { - string retString = null; - - // The strings are returned from QCalls by taking address - // of a local variable using StringHandleOnStack - if (!Bar(flags, this.Id, new StringHandleOnStack(ref retString))) - FatalError(); - - return retString; - } - } - -### QCall Example - Unmanaged Part - -Do not replicate the comments into your actual QCall implementation. - -The QCall entrypoint has to be registered in tables in [vm\ecalllist.h][ecalllist] using QCFuncEntry macro. See "Registering your QCall or FCall Method" below. - -[ecalllist]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/ecalllist.h - - class FooNative - { - public: - // All QCalls should be static and should be tagged with QCALLTYPE - static - BOOL QCALLTYPE Bar(int flags, LPCWSTR wszString, QCall::StringHandleOnStack retString); - }; - - BOOL QCALLTYPE FooNative::Bar(int flags, LPCWSTR wszString, QCall::StringHandleOnStack retString) - { - // All QCalls should have QCALL_CONTRACT. - // It is alias for THROWS; GC_TRIGGERS; MODE_PREEMPTIVE. - QCALL_CONTRACT; - - // Optionally, use QCALL_CHECK instead and the expanded form of the contract - // if you want to specify preconditions: - // CONTRACTL { - // QCALL_CHECK; - // PRECONDITION(wszString != NULL); - // } CONTRACTL_END; - - // The only line between QCALL_CONTRACT and BEGIN_QCALL - // should be the return value declaration if there is one. - BOOL retVal = FALSE; - - // The body has to be enclosed in BEGIN_QCALL/END_QCALL macro. It is necessary - // to make the exception handling work. - BEGIN_QCALL; - - // Validate arguments if necessary and throw exceptions. - // There is no convention currently on whether the argument validation should be - // done in managed or unmanaged code. - if (flags != 0) - COMPlusThrow(kArgumentException, L"InvalidFlags"); - - // No need to worry about GC moving strings passed into QCall. - // Marshalling pins them for us. - printf("%S", wszString); - - // This is most the efficient way to return strings back - // to managed code. No need to use StringBuilder. - retString.Set(L"Hello"); - - // You can not return from inside of BEGIN_QCALL/END_QCALL. - // The return value has to be passed out in helper variable. - retVal = TRUE; - - END_QCALL; - - return retVal; - } - -## FCall Functional Behavior - -FCalls allow more flexibility in terms of passing object references around, with a higher code complexity and more opportunities to hang yourself. Additionally, FCall methods must either erect a helper method frame along their common code paths, or for any FCall of non-trivial length, explicitly poll for whether a garbage collection must occur. Failing to do so will lead to starvation issues if managed code repeatedly calls the FCall method in a tight loop, because FCalls execute while the thread only allows the GC to run in a cooperative manner. - -FCalls require a lot of glue, too much to describe here. Look at [fcall.h][fcall] for details. - -[fcall]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/fcall.h - -### GC Holes, FCall, and QCall - -A much more complete discussion on GC holes can be found in the [CLR Code Guide](../../../coding-guidelines/clr-code-guide.md). Look for ["Is your code GC-safe?"](../../../coding-guidelines/clr-code-guide.md#2.1). This tailored discussion motivates some of the reasons why FCall and QCall have some of their strange conventions. - -Object references passed as parameters to FCall methods are not GC-protected, meaning that if a GC occurs, those references will point to the old location in memory of an object, not the new location. For this reason, FCalls usually follow the discipline of accepting something like "StringObject*" as their parameter type, then explicitly converting that to a STRINGREF before doing operations that may trigger a GC. You must GC protect object references before triggering a GC, if you expect to be able to use that object reference later. - -All GC heap allocations within an FCall method must happen within a helper method frame. If you allocate memory on the GC's heap, the GC may collect dead objects & move objects around in unpredictable ways, with some low probability. For this reason, you must manually report any object references in your method to the GC, so that if a garbage collection occurs, your object reference will be updated to refer to the new location in memory. Any pointers into managed objects (like arrays or Strings) within your code will not be updated automatically, and must be re-fetched after any operation that may allocate memory and before your first usage. Reporting a reference can be done via the GCPROTECT macros, or as parameters when you erect a helper method frame. - -Failing to properly report an OBJECTREF or to update an interior pointer is commonly referred to as a "GC hole", because the OBJECTREF class will do some validation that it points to a valid object every time you dereference it in checked builds. When an OBJECTREF pointing to an invalid object is dereferenced, you'll get an assert saying something like "Detected an invalid object reference. Possible GC hole?". This assert is unfortunately easy to hit when writing "manually managed" code. - -Note that QCall's programming model is restrictive to sidestep GC holes most of the time, by forcing you to pass in the address of an object reference on the stack. This guarantees that the object reference is GC protected by the JIT's reporting logic, and that the actual object reference will not move because it is not allocated in the GC heap. QCall is our recommended approach, precisely because it makes GC holes harder to write. - -### FCall Epilogue Walker for x86 - -The managed stack walker needs to be able to find its way from FCalls. It is relative easy on newer platforms that define conventions for stack unwinding as part of the ABI. The stack unwinding conventions are not defined by ABI for x86. The runtime works around it by implementing a epilog walker. The epilog walker computes the FCall return address and callee save registers by simulating the FCall execution. This imposes limits on what constructs are allowed in the FCall implementation. - -Complex constructs like stack allocated objects with destructors or exception handling in the FCall implementation may confuse the epilog walker. It leads to GC holes or crashes during stack walking. There is no exact list of what constructs should be avoided to prevent this class of bugs. An FCall implementation that is fine one day may break with the next C++ compiler update. We depend on stress runs & code coverage to find bugs in this area. - -Setting a breakpoint inside an FCall implementation may confuse the epilog walker. It leads to an "Invalid breakpoint in a helpermethod frame epilog" assert inside [vm\i386\gmsx86.cpp](https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/i386/gmsx86.cpp). - -### FCall Example – Managed Part - -Here's a real-world example from the String class: - - public partial sealed class String - { - // Replaces all instances of oldChar with newChar. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern String Replace (char oldChar, char newChar); - } - -### FCall Example – Native Part - -The FCall entrypoint has to be registered in tables in [vm\ecalllist.h][ecalllist] using FCFuncEntry macro. See "Registering your QCall or FCall Method". - -Notice how oldBuffer and newBuffer (interior pointers into String instances) are re-fetched after allocating memory. Also, this method is an instance method in managed code, with the "this" parameter passed as the first argument. We use StringObject* as the argument type, then copy it into a STRINGREF so we get some error checking when we use it. - - FCIMPL3(LPVOID, COMString::Replace, StringObject* thisRefUNSAFE, CLR_CHAR oldChar, CLR_CHAR newChar) - { - FCALL_CONTRACT; - - int length = 0; - int firstFoundIndex = -1; - WCHAR *oldBuffer = NULL; - WCHAR *newBuffer; - - STRINGREF newString = NULL; - STRINGREF thisRef = (STRINGREF)thisRefUNSAFE; - - if (thisRef==NULL) { - FCThrowRes(kNullReferenceException, L"NullReference_This"); - } - - [... Removed some uninteresting code here for illustrative purposes...] - - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_RETURNOBJ, newString, thisRef); - - //Get the length and allocate a new String - //We will definitely do an allocation here. - newString = NewString(length); - - //After allocation, thisRef may have moved - oldBuffer = thisRef->GetBuffer(); - - //Get the buffers in both of the Strings. - newBuffer = newString->GetBuffer(); - - //Copy the characters, doing the replacement as we go. - for (int i=0; i template to create a type name like SAFEHANDLEREF. All the error checking from OBJECTREF is built into the REF macro, and you can freely dereference this SAFEHANDLEREF & use fields off of it in native code. You still must GC protect these references. - -# Calling Into Managed Code From Native - -Clearly there are places where the CLR must call into managed code from native. For this purpose, we have added a MethodDescCallSite class to handle a lot of plumbing for you. Conceptually, all you need to do is find the MethodDesc\* for the method you want to call, find a managed object for the "this" pointer (if you're calling an instance method), pass in an array of arguments, and deal with the return value. Internally, you'll need to potentially toggle your thread's state to allow the GC to run in preemptive mode, etc. - -Here's a simplified example. Note how this instance uses the binder described in the previous section to call SafeHandle's virtual ReleaseHandle method. - - void SafeHandle::RunReleaseMethod(SafeHandle* psh) - { - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } CONTRACTL_END; - - SAFEHANDLEREF sh(psh); - - GCPROTECT_BEGIN(sh); - - MethodDescCallSite releaseHandle(s_pReleaseHandleMethod, METHOD__SAFE_HANDLE__RELEASE_HANDLE, (OBJECTREF*)&sh, TypeHandle(), TRUE); - - ARG_SLOT releaseArgs[] = { ObjToArgSlot(sh) }; - if (!(BOOL)releaseHandle.Call_RetBool(releaseArgs)) { - MDA_TRIGGER_ASSISTANT(ReleaseHandleFailed, ReportViolation)(sh->GetTypeHandle(), sh->m_handle); - } - - GCPROTECT_END(); - } - -# Interactions with Other Subsystems - -## Debugger - -One limitation of FCalls today is that you cannot easily debug both managed code and FCalls easily in Visual Studio's Interop (or mixed mode) debugging. Setting a breakpoint today in an FCall and debugging with Interop debugging just doesn't work. This most likely won't be fixed. - -# Physical Architecture - -When the CLR starts up, mscorlib is loaded by a method called LoadBaseSystemClasses. Here, the base data types & other similar classes (like Exception) are loaded, and appropriate global pointers are set up to refer to mscorlib's types. - -For FCalls, look in [fcall.h][fcall] for infrastructure, and [ecalllist.h][ecalllist] to properly inform the runtime about your FCall method. - -For QCalls, look in [qcall.h][qcall] for associated infrastructure, and [ecalllist.h][ecalllist] to properly inform the runtime about your QCall method. - -More general infrastructure and some native type definitions can be found in [object.h][object.h]. The binder uses mscorlib.h to associate managed & native classes. - -[object.h]: https://github.com/dotnet/runtime/blob/master/src/coreclr/src/vm/object.h diff --git a/docs/design/coreclr/botr/readytorun-format.md b/docs/design/coreclr/botr/readytorun-format.md index 51fcd1cab56b4..8db3423dbadfe 100644 --- a/docs/design/coreclr/botr/readytorun-format.md +++ b/docs/design/coreclr/botr/readytorun-format.md @@ -28,8 +28,9 @@ in the COFF header represent a full copy of the input IL and MSIL metadata it wa **Composite R2R files** currently conform to Windows PE executable file format as the native envelope. Moving forward we plan to gradually add support for platform-native -executable formats (ELF on Linux, MachO on OSX) as the native envelopes. As a natural corollary -there is no global CLI / COR header in the file. The ReadyToRun header structure is pointed to +executable formats (ELF on Linux, MachO on OSX) as the native envelopes. There is a +global CLI / COR header in the file, but it only exists to facilitate pdb generation, and does +not participate in any usages by the CoreCLR runtime. The ReadyToRun header structure is pointed to by the well-known export symbol `RTR_HEADER` and has the `READYTORUN_FLAG_COMPOSITE` flag set. Input MSIL metadata and IL streams can be either embedded in the composite R2R file or left diff --git a/docs/design/coreclr/jit/ryujit-tutorial.md b/docs/design/coreclr/jit/ryujit-tutorial.md index 77462044483ca..050c11495b6a8 100644 --- a/docs/design/coreclr/jit/ryujit-tutorial.md +++ b/docs/design/coreclr/jit/ryujit-tutorial.md @@ -5,9 +5,8 @@ ### .NET Runtime - An implementation of the Common Language Infrastructure [ECMA 335] - Supports multiple languages, including C#, F# and VB -- Sources are mostly shared between the "desktop" version and the open-source coreclr implementation: - http://www.github.com/dotnet/runtime/src/coreclr - RyuJIT is the "next generation" just in time compiler for .NET +- Sources are at https://github.com/dotnet/runtime/tree/master/src/coreclr/src/jit #### Notes For context, the .NET runtime has been around since about the turn of the millennium. It is a virtual machine that supports the execution of a number of languages, primarily C#, Visual Basic, and F#. @@ -19,7 +18,6 @@ RyuJIT is the re-architected JIT for .NET. ### Why "RyuJIT"? - Ryujin is a Japanese Sea Dragon -We came up with the code name "RyuJIT" because our original code name had possible issues. We wanted something with "JIT" in the name, and the idea of a dragon came to mind because of the Dragon book that we all know and love. So – we just adapted the name of the Japanese sea dragon, Ryujin. diff --git a/docs/workflow/README.md b/docs/workflow/README.md index 57c10f7a9d472..7a17fecd50eff 100644 --- a/docs/workflow/README.md +++ b/docs/workflow/README.md @@ -10,7 +10,7 @@ The repo can be built for the following platforms, using the provided setup and | x86 | ✔ | | | | | ARM | ✔ | ✔ | | | | ARM64 | ✔ | ✔ | | | -| | [Requirements](requirements/windows-requirements.md) | [Requirements](requirements/linux-requirements.md) | [Requirements](requirements/macos-requirements.md) | +| | [Requirements](requirements/windows-requirements.md) | [Requirements](requirements/linux-requirements.md) | [Requirements](requirements/macos-requirements.md) | [Requirements](requirements/freebsd-requirements.md) Before proceeding further, please click on the link above that matches your machine and ensure you have installed all the prerequisites for the build to work. diff --git a/docs/workflow/building/coreclr/linux-instructions.md b/docs/workflow/building/coreclr/linux-instructions.md index 8ebbb3b2e1906..6328037313992 100644 --- a/docs/workflow/building/coreclr/linux-instructions.md +++ b/docs/workflow/building/coreclr/linux-instructions.md @@ -19,7 +19,7 @@ Please note that when choosing an image choosing the same image as the host os y Once you have chosen an image the build is one command run from the root of the runtime repository: ```sh -docker run --rm -v :/runtime -w /runtime mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-a50a721-20191120200116 ./src/coreclr/build.sh -clang9 +docker run --rm -v :/runtime -w /runtime mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-20200508132555-78cbb55 ./build.sh --subset clr -clang9 ``` Dissecting the command: @@ -30,16 +30,18 @@ Dissecting the command: `-w: /runtime`: set /runtime as working directory for the container -`mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-a50a721-20191120200116`: image name. +`mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-20200508132555-78cbb55`: image name. -`./src/coreclr/build.sh`: command to be run in the container, run the build to coreclr. +`./build.sh`: command to be run in the container, run the build to coreclr. + +`--subset clr`: build the runtime subset (excluding libraries and installers) `-clang9`: argument to use clang 9 for the build, only compiler in the build image. -If you are attempting to cross build for arm/arm64 then use the crossrootfs location to set the ROOTFS_DIR. The command would add `-e ROOTFS_DIR=`. See [Docker Images](#Docker-Images) for the crossrootfs location. In addition you will need to specify `cross`. +If you are attempting to cross build for arm/arm64 then use the crossrootfs location to set the ROOTFS_DIR. The command would add `-e ROOTFS_DIR=`. See [Docker Images](#Docker-Images) for the crossrootfs location. In addition you will need to specify `--cross`. ```sh -docker run --rm -v :/runtime -w /runtime -e ROOTFS_DIR=/crossrootfs/arm64 mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-20200413125008-cfdd435 ./src/coreclr/build.sh arm64 cross +docker run --rm -v :/runtime -w /runtime -e ROOTFS_DIR=/crossrootfs/arm64 mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-20200508132638-b2c2436 ./build.sh --arch arm64 --cross --subset clr ``` Note that instructions on building the crossrootfs location can be found at [cross-building.md](cross-building.md). These instructions are suggested only if there are plans to change the rootfs, or the Docker images for arm/arm64 are insufficient for you build. @@ -69,47 +71,7 @@ Minimum RAM required to build is 1GB. The build is known to fail on 512 MB VMs ( Toolchain Setup --------------- -Add Kitware's APT feed to your configuration for a newer version of CMake. See their instructions at . - -Install the following packages for the toolchain: - -- cmake (at least 3.15.5) -- llvm-3.9 -- clang-9 -- libunwind8 -- libunwind8-dev -- gettext -- libicu-dev -- liblttng-ust-dev -- libcurl4-openssl-dev -- libssl-dev -- libkrb5-dev -- libnuma-dev (optional, enables numa support) - -Note: ARM clang has a known issue with CompareExchange -([#15074](https://github.com/dotnet/coreclr/issues/15074)), so for ARM you must -use clang-4.0 or higher. Moreover, when building with clang-5.0, the -following errors occur: - -``` -src/coreclr/src/debug/inc/arm/primitives.h:66:1: error: __declspec attribute 'selectany' is - not supported [-Werror,-Wignored-attributes] -``` - -This is fixed in clang-5.0.2, which can be installed from the apt -repository listed below. - -For other version of Debian/Ubuntu, please visit http://apt.llvm.org/. - -Then install the packages you need: - - ~$ sudo apt-get install cmake llvm-3.9 clang-9 libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libcurl4-openssl-dev libssl-dev libnuma-dev libkrb5-dev - -You now have all the required components. - -If you are using Fedora, then you will need to install the following packages: - - ~$ sudo dnf install llvm cmake clang lldb-devel libunwind-devel lttng-ust-devel libicu-devel numactl-devel +Follow instructions and install dependencies listed [here](https://github.com/dotnet/runtime/blob/master/docs/workflow/requirements/linux-requirements.md#toolchain-setup). Git Setup --------- diff --git a/docs/workflow/building/libraries/README.md b/docs/workflow/building/libraries/README.md index e790e9997659c..c64f34d705470 100644 --- a/docs/workflow/building/libraries/README.md +++ b/docs/workflow/building/libraries/README.md @@ -205,6 +205,6 @@ If you are working on Windows, and use Visual Studio, you can open individual li ## Running tests -For more details about running tests inside Visual Studio, [go here](../../testing/libraries/testing.md#running-tests-from-visual-studio ) +For more details about running tests inside Visual Studio, [go here](../../testing/visualstudio.md). For more about running tests, read the [running tests](../../testing/libraries/testing.md) document. diff --git a/docs/workflow/debugging/libraries/debugging-vscode.md b/docs/workflow/debugging/libraries/debugging-vscode.md index a27aa1dcbed57..4b82a4265811b 100644 --- a/docs/workflow/debugging/libraries/debugging-vscode.md +++ b/docs/workflow/debugging/libraries/debugging-vscode.md @@ -5,7 +5,7 @@ - Open the folder containing the source you want to debug in VS Code - i.e., if you are debugging a test failure in System.Net.Sockets, open `runtime/src/libraries/System.Net.Sockets` - Open the debug window: `ctrl-shift-D` or click on the button on the left - Click the gear button at the top to create a launch configuration, select `.NET Core` from the selection dropdown -- In the `.NET Core Launch (console)` configuration do the following +- In the ".NET Core Launch (console)" `launch.json` configuration file make the following changes: - delete the `preLaunchTask` property - set `program` to the full path to `dotnet` in the artifacts/bin/testhost directory. - something like `artifacts/bin/testhost/netcoreapp-{OS}-{Configuration}-{Architecture}`, plus the full path to your dotnet/runtime directory. @@ -13,5 +13,5 @@ - using the System.Net.Sockets example, it should be something like `artifacts/bin/System.Net.Sockets.Tests/netcoreapp-{OS}-{Configuration}-{Architecture}`, plus the full path to your dotnet/runtime directory. - set `args` to the command line arguments to pass to the test - something like: `[ "exec", "--runtimeconfig", "{TestProjectName}.runtimeconfig.json", "xunit.console.dll", "{TestProjectName}.dll", "-notrait", ... ]`, where TestProjectName would be `System.Net.Sockets.Tests` - - to run a specific test, you can append something like: `[ "method", "System.Net.Sockets.Tests.{ClassName}.{TestMethodName}", ...]` + - to run a specific test, you can append something like: `[ "-method", "System.Net.Sockets.Tests.{ClassName}.{TestMethodName}", ...]` - Set a breakpoint and launch the debugger, inspecting variables and call stacks will now work diff --git a/docs/workflow/requirements/freebsd-requirements.md b/docs/workflow/requirements/freebsd-requirements.md new file mode 100644 index 0000000000000..59b3c64d928f1 --- /dev/null +++ b/docs/workflow/requirements/freebsd-requirements.md @@ -0,0 +1,69 @@ +Requirements to build dotnet/runtime on FreeBSD +===================== + +This guide will walk you through the requirements needed to build dotnet/runtime on FreeBSD. We'll start by showing how to set up your environment from scratch. +Since there is no official build and FreeBSD package, native build on FreeBSD is not trivial. There are generally three options, sorted by ease of use: +- cross-compile on Linux using Docker +- cross-compile on Linux using Toolchain +- build on FreeBSD + + +Environment +=========== + +These instructions were validated for and on FreeBSD 11.3 and 12.1. + +Build using Docker on Linux +--------------------------- + +This is similar to [Linux](linux-requirements.md) instructions. https://github.com/dotnet/dotnet-buildtools-prereqs-docker repro provides images +with all needed prerequisites to build. As the example bellow may become stale, https://github.com/dotnet/versions/blob/master/build-info/docker/image-info.dotnet-dotnet-buildtools-prereqs-docker-master.json offers list of latest Docker tags. + +```sh +TAG=mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-freebsd-11-20200430154008-a84b0d2 +docker run --rm --volume $(pwd):$(pwd) --workdir $(pwd) --env ROOTFS_DIR=/crossrootfs/x64 -ti $TAG ./build.sh -cross -FreeBSD +``` + +Build using Toolchain Setup +--------------------------- +To build FreeBSD images, prerequisites described in [Linux](linux-requirements.md) are needed. Additionally, crossrootfs for FreeBSD needs to be constructed. +In order to successfully build FreeBSD crossrootfs, few more packages needs to be installed. Following example is for Ubuntu 18: +```sh +apt-get install -y libbz2-dev libz-dev liblzma-dev libarchive-dev libbsd-dev +``` +With prerequisites for crossrootfs one can run: +```sh +./eng/common/cross/build-rootfs.sh freebsd11 $(pwd)/rootfs/freebsd +``` +After that, FreeBSD build can be started by running +``` +ROOTFS_DIR=$(pwd)/rootfs/freebsd ./build.sh -cross -os FreeBSD +``` + + +Building on FreeBSD +------------------- + +Building dotnet/runtime depends on several tools to be installed. + +Install the following packages: + +- cmake +- autoconf +- automake +- libtool +- icu +- libunwind +- lttng-ust +- krb5 +- openssl (optional) + +The lines to install all the packages above using package manager. + +```sh +sudo pkg install --yes libunwind icu libinotify lttng-ust krb5 cmake autoconf automake openssl +``` + +Additionally, working dotnet cli with SDK is needed. On other platforms this would be downloaded automatically during build but it is not currently available for FreeBSD. +It needs to be built once on supported platform or obtained via community resources. + diff --git a/docs/workflow/requirements/linux-requirements.md b/docs/workflow/requirements/linux-requirements.md index 5cb61d12c20ed..6f13897bc6455 100644 --- a/docs/workflow/requirements/linux-requirements.md +++ b/docs/workflow/requirements/linux-requirements.md @@ -88,8 +88,12 @@ Install the following packages for the toolchain: - libnuma-dev (optional, enables numa support) - zlib1g-dev -A single line to install all packages above: +The following dependencies are needed if Mono Runtime is enabled (default behavior): - ~$ sudo apt-get install cmake llvm-9 clang-9 autoconf automake libtool build-essential python curl git lldb-6.0 liblldb-6.0-dev libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libssl-dev libnuma-dev libkrb5-dev zlib1g-dev +- autoconf +- automake +- libtool + + ~$ sudo apt-get install cmake llvm-9 clang-9 autoconf automake libtool build-essential python curl git lldb-6.0 liblldb-6.0-dev libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libssl-dev libnuma-dev libkrb5-dev zlib1g-dev autoconf automake libtool You now have all the required components. diff --git a/docs/workflow/requirements/macos-requirements.md b/docs/workflow/requirements/macos-requirements.md index 82a6610321bb5..4604b87f60f85 100644 --- a/docs/workflow/requirements/macos-requirements.md +++ b/docs/workflow/requirements/macos-requirements.md @@ -16,7 +16,7 @@ Install Apple Xcode developer tools from the Mac App Store ([link](https://apps. Toolchain Setup --------------- -Building dotnet/runtime depends on several tools to be installed. You can download them individually or use [Homebrew](http://brew.sh) for easier toolchain setup. +Building dotnet/runtime depends on several tools to be installed. You can download them individually or use [Homebrew](https://brew.sh) for easier toolchain setup. Install the following packages: @@ -29,8 +29,8 @@ Install the following packages: - pkg-config - python3 -The lines to install all the packages above using Homebrew. +You can install all the packages above using Homebrew by running this command in the repository root: ``` -brew install cmake autoconf automake icu4c libtool openssl@1.1 pkg-config python3 +brew bundle --no-lock --file eng/Brewfile ``` diff --git a/docs/workflow/requirements/windows-requirements.md b/docs/workflow/requirements/windows-requirements.md index dc928b0d55d83..5753ccf266a93 100644 --- a/docs/workflow/requirements/windows-requirements.md +++ b/docs/workflow/requirements/windows-requirements.md @@ -26,11 +26,11 @@ Visual Studio 2019 installation process: - .NET Desktop Development with all default components. - Desktop Development with C++ with all default components. - To build for Arm32 or Arm64, make sure that you have the right architecture specific compilers installed: - - In addition, ensure you install the ARM tools. In the "Individual components" window, in the "Compilers, build tools, and runtimes" section, check the box for "MSVC v142 - VS 2019 C++ ARM build tools (v14.23)". - - Also, ensure you install the ARM64 tools. In the "Individual components" window, in the "Compilers, build tools, and runtimes" section, check the box for "MSVC v142 - VS 2019 C++ ARM64 build tools (v14.23)". + - In addition, ensure you install the ARM tools. In the "Individual components" window, in the "Compilers, build tools, and runtimes" section, check the box for "MSVC v142 - VS 2019 C++ ARM build tools" (v14.23 or newer). + - Also, ensure you install the ARM64 tools. In the "Individual components" window, in the "Compilers, build tools, and runtimes" section, check the box for "MSVC v142 - VS 2019 C++ ARM64 build tools (v14.23 or newer)". - To build the tests, you will need some additional components: - Windows 10 SDK component version 10.0.18362 or newer. This component is installed by default as a part of 'Desktop Development with C++' workload. - - C++/CLI support for v142 build tools (14.23) + - C++/CLI support for v142 build tools (v14.23 or newer) A `.vsconfig` file is included in the root of the dotnet/runtime repository that includes all components needed to build the dotnet/runtime repository. You can [import `.vsconfig` in your Visual Studio installer](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2019#import-a-configuration) to install all necessary components. @@ -38,7 +38,7 @@ The dotnet/runtime repository requires at least Visual Studio 2019 16.6 Preview ## CMake -- Install [CMake](http://www.cmake.org/download) for Windows. +- Install [CMake](https://cmake.org/download) for Windows. - Add its location (e.g. C:\Program Files (x86)\CMake\bin) to the PATH environment variable. The installation script has a check box to do this, but you can do it yourself after the fact following the instructions at [Adding to the Default PATH variable](#adding-to-the-default-path-variable). @@ -67,9 +67,17 @@ The dotnet/runtime repository requires at least Git 2.22.0. ## .NET SDK -While not strictly needed to build or test this repository, having the .NET SDK installed lets you use the dotnet.exe command to run .NET applications in the 'normal' way. +While not strictly needed to build or test this repository, having the .NET SDK installed lets you browse solution files in this repository with Visual Studio and use the dotnet.exe command to run .NET applications in the 'normal' way. We use this in the [Using Your Build](../testing/using-your-build.md) instructions. -Visual Studio should have installed the .NET SDK, but in case it did not you can get it from the [Installing the .NET SDK](https://dotnet.microsoft.com/download) page. +The minimum required version of the SDK is specified in the [global.json file](https://github.com/dotnet/runtime/blob/master/global.json#L3). [You can find the installers and binaries for nightly builds of .NET SDK here](https://github.com/dotnet/installer#installers-and-binaries). + +Alternatively, to avoid modifying your machine state, you can use the repository's locally acquired SDK by passing in the solution to load via the `-vs` switch: + +``` +build.cmd -vs System.Text.RegularExpressions +``` + +This will set the `DOTNET_ROOT` and `PATH` environment variables to point to the locally acquired SDK under `runtime\.dotnet\` and will launch the Visual Studio instance which is registered for the `sln` extension. ## Adding to the default PATH variable diff --git a/docs/workflow/testing/libraries/testing-android.md b/docs/workflow/testing/libraries/testing-android.md new file mode 100644 index 0000000000000..7ac22f84062fa --- /dev/null +++ b/docs/workflow/testing/libraries/testing-android.md @@ -0,0 +1,91 @@ +# Testing Libraries on Android + +The following dependencies should be installed in order to be able to run tests: + +- Android NDK +- Android SDK +- OpenJDK +- OpenSSL + +OpenJDK can be installed on Linux (Ubuntu) using `apt-get`: +```bash +sudo apt-get install openjdk-8 unzip +``` + +Android SDK, NDK and OpenSSL can be automatically installed via the following script: +```bash +#!/usr/bin/env bash +set -e + +NDK_VER=r21b +SDK_VER=6200805_latest +SDK_API_LEVEL=29 +SDK_BUILD_TOOLS=29.0.3 +OPENSSL_VER=1.1.1g-alpha-1 + +if [[ "$OSTYPE" == "darwin"* ]]; then + HOST_OS=darwin + HOST_OS_SHORT=mac + BASHRC=~/.zprofile +else + HOST_OS=linux + HOST_OS_SHORT=linux + BASHRC=~/.bashrc +fi + +# download Android NDK +export ANDROID_NDK_ROOT=~/android-ndk-${NDK_VER} +curl https://dl.google.com/android/repository/android-ndk-${NDK_VER}-${HOST_OS}-x86_64.zip -L --output ~/andk.zip +unzip ~/andk.zip -d $(dirname ${ANDROID_NDK_ROOT}) && rm -rf ~/andk.zip + +# download Android SDK, accept licenses and download additional packages such as +# platform-tools, platforms and build-tools +export ANDROID_SDK_ROOT=~/android-sdk +curl https://dl.google.com/android/repository/commandlinetools-${HOST_OS_SHORT}-${SDK_VER}.zip -L --output ~/asdk.zip +unzip ~/asdk.zip -d ${ANDROID_SDK_ROOT} && rm -rf ~/asdk.zip +yes | ${ANDROID_SDK_ROOT}/tools/bin/./sdkmanager --sdk_root=${ANDROID_SDK_ROOT} --licenses +${ANDROID_SDK_ROOT}/tools/bin/./sdkmanager --sdk_root=${ANDROID_SDK_ROOT} "platform-tools" "platforms;android-${SDK_API_LEVEL}" "build-tools;${SDK_BUILD_TOOLS}" + +# We also need to download precompiled binaries and headers for OpenSSL from maven, this step is a temporary hack +# and will be removed once we figure out how to integrate OpenSSL properly as a dependency +export ANDROID_OPENSSL_AAR=~/openssl-android +curl https://maven.google.com/com/android/ndk/thirdparty/openssl/${OPENSSL_VER}/openssl-${OPENSSL_VER}.aar -L --output ~/openssl.zip +unzip ~/openssl.zip -d ${ANDROID_OPENSSL_AAR} && rm -rf ~/openssl.zip +printf "\n\nexport ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT}\nexport ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}\nexport ANDROID_OPENSSL_AAR=${ANDROID_OPENSSL_AAR}\n" >> ${BASHRC} +``` +Save it to a file (e.g. `deps.sh`) and execute using `source` (e.g. `chmod +x deps.sh && source ./deps.sh`) in order to propogate the `ANDROID_NDK_ROOT`, `ANDROID_SDK_ROOT` and `ANDROID_OPENSSL_AAR` environment variables to the current process. + +## Building Libs and Tests for Android + +Now we're ready to build everything for Android: +``` +./build.sh mono+libs -os Android -arch x64 +``` +and even run tests one by one for each library: +``` +./build.sh libs.tests -os Android -arch x64 -test +``` +Make sure an emulator is booted (see `AVD Manager`) or a device is plugged in and unlocked. +`AVD Manager` tool recommends to install `x86` images by default so if you follow that recommendation make sure `-arch x86` was used for the build script. + +### Running individual test suites +The following shows how to run tests for a specific library +``` +./dotnet.sh build /t:Test src/libraries/System.Numerics.Vectors/tests /p:TargetOS=Android /p:TargetArchitecture=x64 +``` + +### Test App Design +Android app is basically a [Java Instrumentation](https://github.com/dotnet/runtime/blob/master/src/mono/msbuild/AndroidAppBuilder/Templates/MonoRunner.java) and a simple Activity that inits the Mono Runtime via JNI. This Mono Runtime starts a simple xunit test +runner called XHarness.TestRunner (see https://github.com/dotnet/xharness) which runs tests for all `*.Tests.dll` libs in the bundle. There is also XHarness.CLI tool with ADB embedded to deploy `*.apk` to a target (device or emulator) and obtain logs once tests are completed. + +### Obtaining the logs +XHarness for Android doesn't talk much and only saves test results to a file. However, you can also subscribe to live logs via the following command: +``` +adb logcat -s "DOTNET" +``` +Or simply open `logcat` window in Android Studio or Visual Stuido. + +### Existing Limitations +- `-os Android` is not supported for Windows yet (`WSL` can be used instead) +- XHarness.CLI is not able to boot emulators yet (so you need to boot via `AVD Manager` or IDE) +- AOT and Interpreter modes are not supported yet \ No newline at end of file diff --git a/docs/workflow/testing/libraries/testing-apple.md b/docs/workflow/testing/libraries/testing-apple.md new file mode 100644 index 0000000000000..3f99570042065 --- /dev/null +++ b/docs/workflow/testing/libraries/testing-apple.md @@ -0,0 +1,32 @@ +# Testing Libraries on iOS and tvOS + +In order to build libraries and tests for iOS or tvOS you need recent version of XCode installed (e.g. 11.3 or higher). + +Build Libraries for iOS: +``` +./build.sh mono+libs -os iOS -arch x64 +``` +Run tests one by one for each test suite on a simulator: +``` +./build.sh libs.tests -os iOS -arch x64 -test +``` +In order to run the tests on a device you need to specify `DevTeamProvisioning` (see [developer.apple.com/account/#/membership](https://developer.apple.com/account/#/membership), scroll down to `Team ID`): +``` +./build.sh libs.tests -os iOS -arch x64 -test /p:DevTeamProvisioning=H1A2B3C4D5 +``` +[AppleAppBuilder](https://github.com/dotnet/runtime/blob/master/src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.cs) generates temp Xcode projects you can manually open and resolve provisioning issues there using native UI and deploy to your devices. + +### Running individual test suites +- The following shows how to run tests for a specific library: +``` +./dotnet.sh build src/libraries/System.Numerics.Vectors/tests /t:Test /p:TargetOS=iOS /p:TargetArchitecture=x64 +``` + +### Test App Design +iOS/tvOS `*.app` (or `*.ipa`) is basically a simple [ObjC app](https://github.com/dotnet/runtime/blob/master/src/mono/msbuild/AppleAppBuilder/Templates/main-console.m) that inits the Mono Runtime. This Mono Runtime starts a simple xunit test +runner called XHarness.TestRunner (see https://github.com/dotnet/xharness) which runs tests for all `*.Tests.dll` libs in the bundle. There is also XHarness.CLI tool to deploy `*.app` and `*.ipa` to a target (device or simulator) and listens for logs via network sockets. + +### Existing Limitations +- Most of the test suites crash on devices due to #35674 +- Simulator uses JIT mode only at the moment (to be extended with FullAOT and Interpreter) +- Interpreter is not enabled yet. diff --git a/docs/workflow/testing/libraries/testing.md b/docs/workflow/testing/libraries/testing.md index bf100c4ba485a..9ab30e12be41a 100644 --- a/docs/workflow/testing/libraries/testing.md +++ b/docs/workflow/testing/libraries/testing.md @@ -12,18 +12,18 @@ build.cmd/sh -subset libs.tests - The following builds and runs all tests in release configuration: ``` -build.cmd/sh -subset libs -test -c Release +build.cmd/sh -subset libs.tests -test -c Release ``` - The following example shows how to pass extra msbuild properties to ignore tests ignored in CI: ``` -build.cmd/sh -subset libs -test /p:WithoutCategories=IgnoreForCI +build.cmd/sh -subset libs.tests -test /p:WithoutCategories=IgnoreForCI ``` Unless you specifiy `-testnobuild`, test assemblies are implicitly built when invoking the `Test` action. - The following shows how to only test the libraries without building them ``` -build.cmd/sh -subset libs -test -testnobuild +build.cmd/sh -subset libs.tests -test -testnobuild ``` ## Running tests on the command line @@ -38,7 +38,7 @@ dotnet build /t:Test It is possible to pass parameters to the underlying xunit runner via the `XUnitOptions` parameter, e.g.: ```cmd -dotnet build /t:Test "/p:XUnitOptions=-class Test.ClassUnderTests" +dotnet build /t:Test /p:XUnitOptions="-class Test.ClassUnderTests" ``` There may be multiple projects in some directories so you may need to specify the path to a specific test project to get it to build and run the tests. @@ -63,13 +63,3 @@ Each test project can potentially have multiple target frameworks. There are som ```cmd dotnet build src\libraries\System.Runtime\tests\System.Runtime.Tests.csproj /p:BuildTargetFramework=net472 ``` - -## Running tests from Visual Studio - -**Test Explorer** will be able to discover the tests only if the solution is opened with `build -vs` command, e.g.: -```cmd -build -vs System.Net.Http -``` -If running the tests from **Test Explorer** does nothing, it probably tries to use x86 dotnet installation instead of the x64 one. It can be fixed by setting the x64 architecture manually in the test settings. - -It is also possible to execute the tests by simply debugging the test project once it's been built. It will underneath call the same command as `dotnet build /t:Test` does. diff --git a/docs/workflow/testing/visualstudio.md b/docs/workflow/testing/visualstudio.md new file mode 100644 index 0000000000000..c8c20b9cfc7fa --- /dev/null +++ b/docs/workflow/testing/visualstudio.md @@ -0,0 +1,16 @@ +# Visual Studio Test Explorer support +For Visual Studio Test Explorer to work in dotnet/runtime, the following test settings need to be enabled: +- Test parameters (like which `dotnet` host to use) are persisted in an auto-generated .runsettings file. For that to work, make sure that the "Auto detect runsettings Files" (`Options -> Test`) option is enabled. +- Make sure that the "Processor Architecture for AnyCPU project" (`Test Explore pane -> Test Explorer toolbar options --> Settings`) value is set to `auto`. + +# Visual Studio F5 Debugging support +dotnet/runtime uses `dotnet test` ([VSTest](https://github.com/Microsoft/vstest)) which spawns child processes during test execution. +Visual Studio by default doesn't automatically debug child processes, therefore preliminary steps need to be done to enable Debugging "F5" support. +Note that these steps aren't necessary for Visual Studio Test Explorer support. +1. Install the [Microsoft Child Process Debugging Power Tool](https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool) extension. +2. Go to the child process debug settings (`Debug -> Other Debug Targets -> Child Process Debugging Settings...`), enable the "Enable child process debugging" option and hit save. +3. Go to the project debug settings (`Debug -> $ProjectName Properties`) and enable the "Enable native code debugging" option. + +## References +- https://github.com/dotnet/project-system/issues/6176 tracks enabling the native code debugging functionality for multiple projects without user interaction. +- https://github.com/dotnet/sdk/issues/7419#issuecomment-298261617 explains the necessary steps to install and enable the mentioned extension in more detail. diff --git a/eng/Analyzers.props b/eng/Analyzers.props index 8d2cb20609f2b..4ed7e3cb9a96d 100644 --- a/eng/Analyzers.props +++ b/eng/Analyzers.props @@ -6,7 +6,7 @@ - + diff --git a/eng/Brewfile b/eng/Brewfile new file mode 100644 index 0000000000000..40252a15f3048 --- /dev/null +++ b/eng/Brewfile @@ -0,0 +1,8 @@ +brew "autoconf" +brew "automake" +brew "cmake" +brew "icu4c" +brew "libtool" +brew "openssl@1.1" +brew "pkg-config" +brew "python3" diff --git a/eng/CodeAnalysis.ruleset b/eng/CodeAnalysis.ruleset index cf97025667a2b..66a6af943a1ef 100644 --- a/eng/CodeAnalysis.ruleset +++ b/eng/CodeAnalysis.ruleset @@ -4,7 +4,7 @@ - + @@ -106,7 +106,7 @@ - + @@ -210,6 +210,7 @@ + diff --git a/eng/Configurations.props b/eng/Configurations.props index 764887c3ae5a6..06ee77bbe8d17 100644 --- a/eng/Configurations.props +++ b/eng/Configurations.props @@ -17,11 +17,20 @@ - 5.0 - .NETCoreApp,Version=v$(NETCoreAppCurrentVersion) - net$(NETCoreAppCurrentVersion) - net472 + + 5.0 + .NETCoreApp + $(NetCoreAppCurrentIdentifier),Version=v$(NetCoreAppCurrentVersion) + net$(NetCoreAppCurrentVersion) + + $(NetCoreAppCurrent) Microsoft.NETCore.App + .NET $(NetCoreAppCurrentVersion) + + net472 @@ -43,6 +52,7 @@ OSX FreeBSD NetBSD + SunOS Linux Windows_NT $(TargetOS) @@ -51,7 +61,7 @@ - true + true diff --git a/eng/DiaSymReaderNative.targets b/eng/DiaSymReaderNative.targets new file mode 100644 index 0000000000000..5836a781dfa8f --- /dev/null +++ b/eng/DiaSymReaderNative.targets @@ -0,0 +1,35 @@ + + + + + + AnyCPU + + + + + + PreserveNewest + false + false + + + PreserveNewest + false + false + + + + + \ No newline at end of file diff --git a/eng/SignCheckExclusionsFile.txt b/eng/SignCheckExclusionsFile.txt index a78ad401525dd..dc77ca3e4603c 100644 --- a/eng/SignCheckExclusionsFile.txt +++ b/eng/SignCheckExclusionsFile.txt @@ -11,3 +11,5 @@ *comhost.dll;;Template, https://github.com/dotnet/core-setup/pull/7549 *apphosttemplateapphostexe.exe;;Template, https://github.com/dotnet/core-setup/pull/7549 *comhosttemplatecomhostdll.dll;;Template, https://github.com/dotnet/core-setup/pull/7549 +*staticapphosttemplateapphostexe.exe;;Template, https://github.com/dotnet/core-setup/pull/7549 +*dotnet.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933 diff --git a/eng/Signing.props b/eng/Signing.props index 5ceb96ac54bf9..463c3602bb7f9 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -71,7 +71,6 @@ - diff --git a/eng/SubsetValidation.targets b/eng/SubsetValidation.targets index 53ea39ccd4959..3b0acd5c5e156 100644 --- a/eng/SubsetValidation.targets +++ b/eng/SubsetValidation.targets @@ -6,7 +6,7 @@ on a whole subset, and the dependency on the subset is disregarded automatically when Subset doesn't contain it. - %(InstallerProject.SignPhase): Indicates this project must be built before a certain signing + %(ProjectToBuild.SignPhase): Indicates this project must be built before a certain signing phase. Projects can depend on 'signing/stages/Sign.proj' to wait until all projects that are part of a stage are complete. This allows the build to perform complex container signing that isn't (can't be?) supported by Arcade's single pass, such as MSIs and bundles: diff --git a/eng/Subsets.props b/eng/Subsets.props index 801ddb9099483..f7c472357e68c 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -13,7 +13,7 @@ ./build.sh corehost installer.managed - This builds the CoreHost and also the Managed installer portion (e.g. Microsoft.DotNet.PlatformAbstractions) + This builds the CoreHost and also the Managed installer portion (e.g. Microsoft.NET.HostModel) projects. A space ' ' or '+' are the delimiters between multiple subsets to build. ./build.sh -test installer.tests @@ -38,7 +38,7 @@ clr+mono+libs+installer - mono+libs+installer + mono+libs+installer @@ -48,7 +48,7 @@ - Mono + Mono Mono CoreCLR @@ -104,7 +104,7 @@ - + @@ -115,78 +115,58 @@ - + false false false false - Configuration=$(CoreCLRConfiguration) - - - false - false - false - false - Configuration=$(MonoConfiguration) - - - false - false - false - false - Configuration=$(LibrariesConfiguration) - - - false - true - false - + - + - + - + - + - + - - - - - + + - + - + - + - + @@ -197,65 +177,65 @@ - + - + - + - + - + - + - + - + - - + + - - + + - + - + @@ -265,11 +245,20 @@ - + - + + + + + + + Configuration=$(CoreCLRConfiguration) + Configuration=$(MonoConfiguration) + Configuration=$(LibrariesConfiguration) + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2251bd9ac26bd..0e5212ef380e4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -6,61 +6,61 @@ - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d - + https://github.com/dotnet/arcade - 981e1a0b0149281a5994ecddfeb5cfcf002f9f1e + 898e51ed5fdcc4871087ac5754ca9056e58e575d https://dev.azure.com/dnceng/internal/_git/dotnet-optimization @@ -82,65 +82,65 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization d0bb63d2ec7060714e63ee4082fac48f2e57f3e2 - + https://github.com/microsoft/vstest - df61f73a1f4608df5ee0957350fbd3e81f924c6b + 8ee627ea54aba31b941e5d45a1a1614b50f7befb - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/runtime-assets - dca67e64ede5a701747e9a8e0117c18aaa4f7bca + 71b9284907ebc69e5f80b491a51084c75e0ef7d3 - + https://github.com/dotnet/llvm-project - e5fd1614a244e8441b2d79eb3ebb044d26ec63b2 + d179d1b519fb0b3e4a4b3f15ee55920e310c582f - + https://github.com/dotnet/llvm-project - e5fd1614a244e8441b2d79eb3ebb044d26ec63b2 + d179d1b519fb0b3e4a4b3f15ee55920e310c582f - + https://github.com/dotnet/llvm-project - e5fd1614a244e8441b2d79eb3ebb044d26ec63b2 + d179d1b519fb0b3e4a4b3f15ee55920e310c582f - + https://github.com/dotnet/llvm-project - e5fd1614a244e8441b2d79eb3ebb044d26ec63b2 + d179d1b519fb0b3e4a4b3f15ee55920e310c582f - + https://github.com/dotnet/llvm-project - e5fd1614a244e8441b2d79eb3ebb044d26ec63b2 + d179d1b519fb0b3e4a4b3f15ee55920e310c582f - + https://github.com/dotnet/llvm-project - e5fd1614a244e8441b2d79eb3ebb044d26ec63b2 + d179d1b519fb0b3e4a4b3f15ee55920e310c582f https://github.com/dotnet/runtime @@ -170,13 +170,13 @@ https://github.com/dotnet/runtime 0375524a91a47ca4db3ee1be548f74bab7e26e76 - + https://github.com/mono/linker - fe2d8f8c2007ecf3789df3d8169d9809111875bb + 3481158940a2b7f1114950cc7ba5bd56e0bfc761 - + https://github.com/dotnet/xharness - 669f7ff3cdcf7770e566c0bff795d38cd59ba961 + 8f6cc04f53cb6759758ffc97c9c8ca3ab4802f7f diff --git a/eng/Versions.props b/eng/Versions.props index 450f8a402ab25..586f105dc5466 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,7 +7,7 @@ 0 0 preview - 5 + 6 $(MajorVersion).$(MinorVersion).0.0 @@ -18,15 +18,9 @@ true true false - - 3.6.0-2.20166.2 dotnet $(ContainerName) - - $(MajorVersion).$(MinorVersion) - $(MajorVersion).$(MinorVersion) - net$(NETCoreAppFrameworkVersion) - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 - 2.5.1-beta.20255.6 - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 - 5.0.0-beta.20255.6 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 + 2.5.1-beta.20264.3 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 + 5.0.0-beta.20261.9 5.0.0-preview.4.20202.18 5.0.0-preview.4.20202.18 5.0.0-preview.4.20202.18 - 2.1.0 - 3.0.0 + 3.1.0 5.0.0-preview.4.20202.18 5.0.0-preview.4.20202.18 @@ -80,14 +73,14 @@ 5.0.0-preview.4.20202.18 5.0.0-alpha.1.19563.3 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 - 5.0.0-beta.20256.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 + 5.0.0-beta.20258.1 2.2.0-prerelease.19564.1 @@ -99,6 +92,7 @@ 1.0.5 1.7.0 + 2.0.0-beta1.20253.1 4.8.0 - 16.7.0-preview-20200429-01 - 1.0.0-prerelease.20255.4 + 16.7.0-preview-20200521-01 + 1.0.0-prerelease.20277.1 2.4.1 1.2.1 2.0.5 @@ -122,14 +116,14 @@ 3.1.0-preview-20200129.1 - 5.0.0-preview.3.20256.5 + 5.0.0-preview.3.20276.2 - 6.0.1-alpha.1.20254.1 - 6.0.1-alpha.1.20254.1 - 6.0.1-alpha.1.20254.1 - 6.0.1-alpha.1.20254.1 - 6.0.1-alpha.1.20254.1 - 6.0.1-alpha.1.20254.1 + 9.0.1-alpha.1.20268.2 + 9.0.1-alpha.1.20268.2 + 9.0.1-alpha.1.20268.2 + 9.0.1-alpha.1.20268.2 + 9.0.1-alpha.1.20268.2 + 9.0.1-alpha.1.20268.2 diff --git a/eng/build.ps1 b/eng/build.ps1 index 09d8164516acd..f8f1164bcafc8 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -2,15 +2,16 @@ Param( [switch][Alias('h')]$help, [switch][Alias('t')]$test, - [string[]][Alias('c')]$configuration = @("Debug"), + [ValidateSet("Debug","Release","Checked")][string[]][Alias('c')]$configuration = @("Debug"), [string][Alias('f')]$framework, [string]$vs, - [string]$os, + [string][Alias('v')]$verbosity = "minimal", + [ValidateSet("Windows_NT","Linux","OSX","Browser")][string]$os, [switch]$allconfigurations, [switch]$coverage, [string]$testscope, [switch]$testnobuild, - [string[]][Alias('a')]$arch = @([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant()), + [ValidateSet("x86","x64","arm","arm64","wasm")][string[]][Alias('a')]$arch = @([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant()), [Parameter(Position=0)][string][Alias('s')]$subset, [ValidateSet("Debug","Release","Checked")][string][Alias('rc')]$runtimeConfiguration, [ValidateSet("Debug","Release")][string][Alias('lc')]$librariesConfiguration, @@ -20,9 +21,9 @@ Param( function Get-Help() { Write-Host "Common settings:" Write-Host " -subset Build a subset, print available subsets with -subset help (short: -s)" - Write-Host " -vs Open the solution with VS for Test Explorer support. Path or solution name (ie -vs Microsoft.CSharp)" - Write-Host " -os Build operating system: Windows_NT or Unix" - Write-Host " -arch Build platform: x86, x64, arm or arm64 (short: -a). Pass a comma-separated list to build for multiple architectures." + Write-Host " -vs Open the solution with VS using the locally acquired SDK. Path or solution name (ie -vs Microsoft.CSharp)" + Write-Host " -os Build operating system: Windows_NT, Linux, OSX, or Browser" + Write-Host " -arch Build platform: x86, x64, arm, arm64, or wasm (short: -a). Pass a comma-separated list to build for multiple architectures." Write-Host " -configuration Build configuration: Debug, Release or [CoreCLR]Checked (short: -c). Pass a comma-separated list to build for multiple configurations" Write-Host " -runtimeConfiguration Runtime build configuration: Debug, Release or [CoreCLR]Checked (short: -rc)" Write-Host " -librariesConfiguration Libraries build configuration: Debug or Release (short: -lc)" @@ -59,37 +60,32 @@ if ($help -or (($null -ne $properties) -and ($properties.Contains('/help') -or $ exit 0 } -# VS Test Explorer support for libraries if ($vs) { . $PSScriptRoot\common\tools.ps1 - # Microsoft.DotNet.CoreSetup.sln is special - hosting tests are currently meant to run on the - # bootstrapped .NET Core, not on the live-built runtime. - if (([System.IO.Path]::GetFileName($vs) -ieq "Microsoft.DotNet.CoreSetup.sln") -or ($vs -ieq "Microsoft.DotNet.CoreSetup")) { + if (-Not (Test-Path $vs)) { + $solution = $vs + # Search for the solution in libraries + $vs = Split-Path $PSScriptRoot -Parent | Join-Path -ChildPath "src\libraries" | Join-Path -ChildPath $vs | Join-Path -ChildPath "$vs.sln" if (-Not (Test-Path $vs)) { - if (-Not ( $vs.endswith(".sln"))) { - $vs = "$vs.sln" + $vs = $solution + # Search for the solution in installer + if (-Not ($vs.endswith(".sln"))) { + $vs = "$vs.sln" + } + $vs = Split-Path $PSScriptRoot -Parent | Join-Path -ChildPath "src\installer" | Join-Path -ChildPath $vs + if (-Not (Test-Path $vs)) { + Write-Error "Passed in solution cannot be resolved." + exit 1 } - $vs = Join-Path "$PSScriptRoot\..\src\installer" $vs } - - # This tells .NET Core to use the bootstrapped runtime to run the tests - $env:DOTNET_ROOT=InitializeDotNetCli -install:$false } - else { - if (-Not (Test-Path $vs)) { - $vs = Join-Path "$PSScriptRoot\..\src\libraries" $vs | Join-Path -ChildPath "$vs.sln" - } - - $archTestHost = if ($arch) { $arch } else { "x64" } - # This tells .NET Core to use the same dotnet.exe that build scripts use - $env:DOTNET_ROOT="$PSScriptRoot\..\artifacts\bin\testhost\net5.0-Windows_NT-$configuration-$archTestHost"; - $env:DEVPATH="$PSScriptRoot\..\artifacts\bin\testhost\net472-Windows_NT-$configuration-$archTestHost"; - } + # This tells .NET Core to use the bootstrapped runtime + $env:DOTNET_ROOT=InitializeDotNetCli -install:$false # This tells MSBuild to load the SDK from the directory of the bootstrapped SDK - $env:DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=InitializeDotNetCli -install:$false + $env:DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$env:DOTNET_ROOT # This tells .NET Core not to go looking for .NET Core in other places $env:DOTNET_MULTILEVEL_LOOKUP=0; @@ -130,6 +126,7 @@ foreach ($argument in $PSBoundParameters.Keys) "os" { $arguments += " /p:TargetOS=$($PSBoundParameters[$argument])" } "allconfigurations" { $arguments += " /p:BuildAllConfigurations=true" } "properties" { $arguments += " " + $properties } + "verbosity" { $arguments += " -$argument " + $($PSBoundParameters[$argument]) } # configuration and arch can be specified multiple times, so they should be no-ops here "configuration" {} "arch" {} @@ -159,4 +156,4 @@ if ($failedBuilds.Count -ne 0) { exit 1 } -exit 0 \ No newline at end of file +exit 0 diff --git a/eng/build.sh b/eng/build.sh index 64496fd108050..02c5d278e259d 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -18,7 +18,7 @@ usage() { echo "Common settings:" echo " --subset Build a subset, print available subsets with -subset help (short: -s)" - echo " --os Build operating system: Windows_NT, Linux, FreeBSD, OSX, tvOS, iOS, Android or Browser" + echo " --os Build operating system: Windows_NT, Linux, FreeBSD, OSX, tvOS, iOS, Android, Browser, NetBSD or SunOS" echo " --arch Build platform: x86, x64, arm, armel, arm64 or wasm" echo " --configuration Build configuration: Debug, Release or [CoreCLR]Checked (short: -c)" echo " --runtimeConfiguration Runtime build configuration: Debug, Release or [CoreCLR]Checked (short: -rc)" @@ -107,34 +107,58 @@ while [[ $# > 0 ]]; do usage exit 0 ;; + -subset|-s) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then arguments="$arguments /p:Subset=help" shift 1 - else + else arguments="$arguments /p:Subset=$2" shift 2 fi ;; + -arch) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No architecture supplied. See help (--help) for supported architectures." 1>&2 exit 1 fi - arch=$2 + passedArch="$(echo "$2" | awk '{print tolower($0)}')" + case "$passedArch" in + x64|x86|arm|armel|arm64|wasm) + arch=$passedArch + ;; + *) + echo "Unsupported target architecture '$2'." + echo "The allowed values are x86, x64, arm, armel, arm64, and wasm." + exit 1 + ;; + esac shift 2 ;; + -configuration|-c) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No configuration supplied. See help (--help) for supported configurations." 1>&2 exit 1 fi - val="$(tr '[:lower:]' '[:upper:]' <<< ${2:0:1})${2:1}" + passedConfig="$(echo "$2" | awk '{print tolower($0)}')" + case "$passedConfig" in + debug|release|checked) + val="$(tr '[:lower:]' '[:upper:]' <<< ${passedConfig:0:1})${passedConfig:1}" + ;; + *) + echo "Unsupported target configuration '$2'." + echo "The allowed values are Debug, Release, and Checked." + exit 1 + ;; + esac arguments="$arguments -configuration $val" shift 2 ;; + -framework|-f) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No framework supplied. See help (--help) for supported frameworks." 1>&2 exit 1 fi @@ -142,73 +166,131 @@ while [[ $# > 0 ]]; do arguments="$arguments /p:BuildTargetFramework=$val" shift 2 ;; + -os) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No target operating system supplied. See help (--help) for supported target operating systems." 1>&2 exit 1 fi - os=$2 - arguments="$arguments /p:TargetOS=$2" + passedOS="$(echo "$2" | awk '{print tolower($0)}')" + case "$passedOS" in + windows_nt) + os="Windows_NT" ;; + linux) + os="Linux" ;; + freebsd) + os="FreeBSD" ;; + osx) + os="OSX" ;; + tvos) + os="tvOS" ;; + ios) + os="iOS" ;; + android) + os="Android" ;; + browser) + os="Browser" ;; + sunos) + os="SunOS" ;; + *) + echo "Unsupported target OS '$2'." + echo "The allowed values are Windows_NT, Linux, FreeBSD, OSX, tvOS, iOS, Android, Browser, and SunOS." + exit 1 + ;; + esac + arguments="$arguments /p:TargetOS=$os" shift 2 ;; + -allconfigurations) arguments="$arguments /p:BuildAllConfigurations=true" shift 1 ;; + -testscope) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No test scope supplied. See help (--help) for supported test scope values." 1>&2 exit 1 fi arguments="$arguments /p:TestScope=$2" shift 2 ;; + -testnobuild) arguments="$arguments /p:TestNoBuild=true" shift 1 ;; + -coverage) arguments="$arguments /p:Coverage=true" shift 1 ;; + -runtimeconfiguration|-rc) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No runtime configuration supplied. See help (--help) for supported runtime configurations." 1>&2 exit 1 fi - val="$(tr '[:lower:]' '[:upper:]' <<< ${2:0:1})${2:1}" + passedRuntimeConf="$(echo "$2" | awk '{print tolower($0)}')" + case "$passedRuntimeConf" in + debug|release|checked) + val="$(tr '[:lower:]' '[:upper:]' <<< ${passedRuntimeConf:0:1})${passedRuntimeConf:1}" + ;; + *) + echo "Unsupported runtime configuration '$2'." + echo "The allowed values are Debug, Release, and Checked." + exit 1 + ;; + esac arguments="$arguments /p:RuntimeConfiguration=$val" shift 2 ;; + -librariesconfiguration|-lc) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No libraries configuration supplied. See help (--help) for supported libraries configurations." 1>&2 exit 1 fi - arguments="$arguments /p:LibrariesConfiguration=$2" + passedLibConf="$(echo "$2" | awk '{print tolower($0)}')" + case "$passedLibConf" in + debug|release) + val="$(tr '[:lower:]' '[:upper:]' <<< ${passedLibConf:0:1})${passedLibConf:1}" + ;; + *) + echo "Unsupported libraries configuration '$2'." + echo "The allowed values are Debug and Release." + exit 1 + ;; + esac + arguments="$arguments /p:LibrariesConfiguration=$val" shift 2 ;; + -cross) crossBuild=1 arguments="$arguments /p:CrossBuild=True" shift 1 ;; + -clang*) arguments="$arguments /p:Compiler=$opt" shift 1 ;; + -cmakeargs) - if [ -z ${2+x} ]; then + if [ -z ${2+x} ]; then echo "No cmake args supplied." 1>&2 exit 1 fi cmakeargs="${cmakeargs} ${opt} $2" shift 2 ;; + -gcc*) arguments="$arguments /p:Compiler=$opt" shift 1 ;; + *) extraargs="$extraargs $1" shift 1 diff --git a/eng/codeOptimization.targets b/eng/codeOptimization.targets index 34f89c0807566..6ed7e997487bd 100644 --- a/eng/codeOptimization.targets +++ b/eng/codeOptimization.targets @@ -9,7 +9,7 @@ IBCMerge optimizations on Mac for now to unblock the offical build. See issue https://github.com/dotnet/runtime/issues/33303 --> - false + false Semi-colon delimited list of sln/proj's to build. Globbing is supported (*.sln)" Write-Host " -ci Set when running on CI server" + Write-Host " -excludeCIBinarylog Don't output binary log (short: -nobl)" Write-Host " -prepareMachine Prepare machine for CI run, clean up processes after build" Write-Host " -warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." @@ -134,7 +136,9 @@ try { } if ($ci) { - $binaryLog = $true + if (-not $excludeCIBinarylog) { + $binaryLog = $true + } $nodeReuse = $false } diff --git a/eng/common/build.sh b/eng/common/build.sh index 36f9aa0462ee1..6d7c5a1f69c20 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -32,6 +32,7 @@ usage() echo "Advanced settings:" echo " --projects Project or solution file(s) to build" echo " --ci Set when running on CI server" + echo " --excludeCIBinarylog Don't output binary log (short: -nobl)" echo " --prepareMachine Prepare machine for CI run, clean up processes after build" echo " --nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')" echo " --warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" @@ -68,6 +69,7 @@ clean=false warn_as_error=true node_reuse=true binary_log=false +exclude_ci_binary_log=false pipelines_log=false projects='' @@ -98,6 +100,9 @@ while [[ $# > 0 ]]; do -binarylog|-bl) binary_log=true ;; + -excludeCIBinarylog|-nobl) + exclude_ci_binary_log=true + ;; -pipelineslog|-pl) pipelines_log=true ;; @@ -156,8 +161,10 @@ done if [[ "$ci" == true ]]; then pipelines_log=true - binary_log=true node_reuse=false + if [[ "$exclude_ci_binary_log" == false ]]; then + binary_log=true + fi fi . "$scriptroot/tools.sh" diff --git a/eng/common/cibuild.sh b/eng/common/cibuild.sh index 66e3b0ac61c36..1a02c0dec8fd7 100755 --- a/eng/common/cibuild.sh +++ b/eng/common/cibuild.sh @@ -13,4 +13,4 @@ while [[ -h $source ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -. "$scriptroot/build.sh" --restore --build --test --pack --publish --ci $@ +. "$scriptroot/build.sh" --restore --build --test --pack --publish --ci $@ \ No newline at end of file diff --git a/eng/common/cross/arm/sources.list.trusty b/eng/common/cross/arm/sources.list.trusty index 8aa98a259ff0f..07d8f88d82e87 100644 --- a/eng/common/cross/arm/sources.list.trusty +++ b/eng/common/cross/arm/sources.list.trusty @@ -8,4 +8,4 @@ deb http://ports.ubuntu.com/ubuntu-ports/ trusty-backports main restricted deb-src http://ports.ubuntu.com/ubuntu-ports/ trusty-backports main restricted deb http://ports.ubuntu.com/ubuntu-ports/ trusty-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ trusty-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ trusty-security main restricted universe multiverse \ No newline at end of file diff --git a/eng/common/cross/arm/sources.list.xenial b/eng/common/cross/arm/sources.list.xenial index 56fbb36a59f62..eacd86b7df3c1 100644 --- a/eng/common/cross/arm/sources.list.xenial +++ b/eng/common/cross/arm/sources.list.xenial @@ -8,4 +8,4 @@ deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse \ No newline at end of file diff --git a/eng/common/cross/arm64/sources.list.trusty b/eng/common/cross/arm64/sources.list.trusty index 8aa98a259ff0f..07d8f88d82e87 100644 --- a/eng/common/cross/arm64/sources.list.trusty +++ b/eng/common/cross/arm64/sources.list.trusty @@ -8,4 +8,4 @@ deb http://ports.ubuntu.com/ubuntu-ports/ trusty-backports main restricted deb-src http://ports.ubuntu.com/ubuntu-ports/ trusty-backports main restricted deb http://ports.ubuntu.com/ubuntu-ports/ trusty-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ trusty-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ trusty-security main restricted universe multiverse \ No newline at end of file diff --git a/eng/common/cross/arm64/sources.list.xenial b/eng/common/cross/arm64/sources.list.xenial index 56fbb36a59f62..eacd86b7df3c1 100644 --- a/eng/common/cross/arm64/sources.list.xenial +++ b/eng/common/cross/arm64/sources.list.xenial @@ -8,4 +8,4 @@ deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse \ No newline at end of file diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1 index d1b9f5c20ba06..435e7641341b1 100644 --- a/eng/common/darc-init.ps1 +++ b/eng/common/darc-init.ps1 @@ -1,5 +1,5 @@ param ( - $darcVersion = "1.1.0-beta.20255.1", + $darcVersion = $null, $versionEndpoint = 'https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16', $verbosity = 'minimal', $toolpath = $null @@ -44,4 +44,4 @@ catch { Write-Host $_.ScriptStackTrace Write-PipelineTelemetryError -Category 'Darc' -Message $_ ExitWithExitCode 1 -} +} \ No newline at end of file diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh index 9e62d08cd3e0c..d981d7bbf38de 100755 --- a/eng/common/darc-init.sh +++ b/eng/common/darc-init.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash source="${BASH_SOURCE[0]}" -darcVersion='1.1.0-beta.20255.1' +darcVersion='' versionEndpoint='https://maestro-prod.westus2.cloudapp.azure.com/api/assets/darc-version?api-version=2019-01-16' verbosity='minimal' diff --git a/eng/common/dotnet-install.cmd b/eng/common/dotnet-install.cmd index f74c16cc8a892..b1c2642e76f72 100644 --- a/eng/common/dotnet-install.cmd +++ b/eng/common/dotnet-install.cmd @@ -1,2 +1,2 @@ @echo off -powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0dotnet-install.ps1""" %*" +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0dotnet-install.ps1""" %*" \ No newline at end of file diff --git a/eng/common/generate-graph-files.ps1 b/eng/common/generate-graph-files.ps1 index bc7ad852d56a5..0728b1a8b570d 100644 --- a/eng/common/generate-graph-files.ps1 +++ b/eng/common/generate-graph-files.ps1 @@ -83,4 +83,4 @@ catch { ExitWithExitCode 1 } finally { Pop-Location -} +} \ No newline at end of file diff --git a/eng/common/init-tools-native.cmd b/eng/common/init-tools-native.cmd index 10938a23c5287..438cd548c452c 100644 --- a/eng/common/init-tools-native.cmd +++ b/eng/common/init-tools-native.cmd @@ -1,3 +1,3 @@ @echo off powershell -NoProfile -NoLogo -ExecutionPolicy ByPass -command "& """%~dp0init-tools-native.ps1""" %*" -exit /b %ErrorLevel% +exit /b %ErrorLevel% \ No newline at end of file diff --git a/eng/common/msbuild.ps1 b/eng/common/msbuild.ps1 index b2dceff4ce87d..c6401230002fe 100644 --- a/eng/common/msbuild.ps1 +++ b/eng/common/msbuild.ps1 @@ -23,4 +23,4 @@ catch { ExitWithExitCode 1 } -ExitWithExitCode 0 +ExitWithExitCode 0 \ No newline at end of file diff --git a/eng/common/native/CommonLibrary.psm1 b/eng/common/native/CommonLibrary.psm1 index 41416862d9132..d7d1a6510949a 100644 --- a/eng/common/native/CommonLibrary.psm1 +++ b/eng/common/native/CommonLibrary.psm1 @@ -145,9 +145,12 @@ function Get-File { New-Item -path $DownloadDirectory -force -itemType "Directory" | Out-Null } + $TempPath = "$Path.tmp" if (Test-Path -IsValid -Path $Uri) { - Write-Verbose "'$Uri' is a file path, copying file to '$Path'" - Copy-Item -Path $Uri -Destination $Path + Write-Verbose "'$Uri' is a file path, copying temporarily to '$TempPath'" + Copy-Item -Path $Uri -Destination $TempPath + Write-Verbose "Moving temporary file to '$Path'" + Move-Item -Path $TempPath -Destination $Path return $? } else { @@ -157,8 +160,10 @@ function Get-File { while($Attempt -Lt $DownloadRetries) { try { - Invoke-WebRequest -UseBasicParsing -Uri $Uri -OutFile $Path - Write-Verbose "Downloaded to '$Path'" + Invoke-WebRequest -UseBasicParsing -Uri $Uri -OutFile $TempPath + Write-Verbose "Downloaded to temporary location '$TempPath'" + Move-Item -Path $TempPath -Destination $Path + Write-Verbose "Moved temporary file to '$Path'" return $True } catch { @@ -359,16 +364,21 @@ function Expand-Zip { return $False } } - if (-Not (Test-Path $OutputDirectory)) { - New-Item -path $OutputDirectory -Force -itemType "Directory" | Out-Null + + $TempOutputDirectory = Join-Path "$(Split-Path -Parent $OutputDirectory)" "$(Split-Path -Leaf $OutputDirectory).tmp" + if (Test-Path $TempOutputDirectory) { + Remove-Item $TempOutputDirectory -Force -Recurse } + New-Item -Path $TempOutputDirectory -Force -ItemType "Directory" | Out-Null Add-Type -assembly "system.io.compression.filesystem" - [io.compression.zipfile]::ExtractToDirectory("$ZipPath", "$OutputDirectory") + [io.compression.zipfile]::ExtractToDirectory("$ZipPath", "$TempOutputDirectory") if ($? -Eq $False) { Write-Error "Unable to extract '$ZipPath'" return $False } + + Move-Item -Path $TempOutputDirectory -Destination $OutputDirectory } catch { Write-Host $_ diff --git a/eng/common/native/install-cmake-test.sh b/eng/common/native/install-cmake-test.sh index 7d1b7136d8dee..12339a40761d4 100755 --- a/eng/common/native/install-cmake-test.sh +++ b/eng/common/native/install-cmake-test.sh @@ -114,4 +114,4 @@ if [[ $? != 0 ]]; then exit 1 fi -exit 0 +exit 0 \ No newline at end of file diff --git a/eng/common/native/install-cmake.sh b/eng/common/native/install-cmake.sh index aaa3e3818904b..18041be87633e 100755 --- a/eng/common/native/install-cmake.sh +++ b/eng/common/native/install-cmake.sh @@ -114,4 +114,4 @@ if [[ $? != 0 ]]; then exit 1 fi -exit 0 +exit 0 \ No newline at end of file diff --git a/eng/common/performance/perfhelixpublish.proj b/eng/common/performance/perfhelixpublish.proj index f86c3419efa03..1db5e8a84d758 100644 --- a/eng/common/performance/perfhelixpublish.proj +++ b/eng/common/performance/perfhelixpublish.proj @@ -6,6 +6,7 @@ py -3 %HELIX_CORRELATION_PAYLOAD%\Core_Root\CoreRun.exe %HELIX_CORRELATION_PAYLOAD%\Baseline_Core_Root\CoreRun.exe + $(HelixPreCommands);call %HELIX_CORRELATION_PAYLOAD%\performance\tools\machine-setup.cmd;set PYTHONPATH=%HELIX_WORKITEM_PAYLOAD%\scripts%3B%HELIX_WORKITEM_PAYLOAD% %HELIX_CORRELATION_PAYLOAD%\artifacts\BenchmarkDotNet.Artifacts %HELIX_CORRELATION_PAYLOAD%\artifacts\BenchmarkDotNet.Artifacts_Baseline @@ -40,6 +41,13 @@ $HELIX_WORKITEM_ROOT/testResults.xml + + --corerun %HELIX_CORRELATION_PAYLOAD%\dotnet-mono\shared\Microsoft.NETCore.App\5.0.0\corerun.exe + + + --corerun $(BaseDirectory)/dotnet-mono/shared/Microsoft.NETCore.App/5.0.0/corerun + + --corerun $(CoreRun) @@ -118,4 +126,4 @@ $(Python) %HELIX_CORRELATION_PAYLOAD%\performance\src\scenarios\crossgen\test.py crossgen --test-name Microsoft.CodeAnalysis.CSharp.dll --core-root %HELIX_CORRELATION_PAYLOAD%\Core_Root - + \ No newline at end of file diff --git a/eng/common/performance/performance-setup.ps1 b/eng/common/performance/performance-setup.ps1 index a0703852ee667..31a99e49015f4 100644 --- a/eng/common/performance/performance-setup.ps1 +++ b/eng/common/performance/performance-setup.ps1 @@ -12,8 +12,12 @@ Param( [string] $RunCategories="Libraries Runtime", [string] $Csproj="src\benchmarks\micro\MicroBenchmarks.csproj", [string] $Kind="micro", + [switch] $LLVM, + [switch] $MonoInterpreter, + [switch] $MonoAOT, [switch] $Internal, [switch] $Compare, + [string] $MonoDotnet="", [string] $Configurations="CompilationMode=$CompilationMode RunKind=$Kind" ) @@ -50,6 +54,21 @@ if ($Internal) { $HelixSourcePrefix = "official" } +if($MonoDotnet -ne "") +{ + $Configurations += " LLVM=$LLVM MonoInterpreter=$MonoInterpreter MonoAOT=$MonoAOT" + if($ExtraBenchmarkDotNetArguments -eq "") + { + #FIX ME: We need to block these tests as they don't run on mono for now + $ExtraBenchmarkDotNetArguments = "--exclusion-filter *Perf_Image* *Perf_NamedPipeStream*" + } + else + { + #FIX ME: We need to block these tests as they don't run on mono for now + $ExtraBenchmarkDotNetArguments += " --exclusion-filter *Perf_Image* *Perf_NamedPipeStream*" + } +} + # FIX ME: This is a workaround until we get this from the actual pipeline $CommonSetupArguments="--channel master --queue $Queue --build-number $BuildNumber --build-configs $Configurations --architecture $Architecture" $SetupArguments = "--repository https://github.com/$Repository --branch $Branch --get-perf-hash --commit-sha $CommitSha $CommonSetupArguments" @@ -70,6 +89,13 @@ else { git clone --branch master --depth 1 --quiet https://github.com/dotnet/performance $PerformanceDirectory } +if($MonoDotnet -ne "") +{ + $UsingMono = "true" + $MonoDotnetPath = (Join-Path $PayloadDirectory "dotnet-mono") + Move-Item -Path $MonoDotnet -Destination $MonoDotnetPath +} + if ($UseCoreRun) { $NewCoreRoot = (Join-Path $PayloadDirectory "Core_Root") Move-Item -Path $CoreRootDirectory -Destination $NewCoreRoot @@ -105,6 +131,7 @@ Write-PipelineSetVariable -Name 'UseCoreRun' -Value "$UseCoreRun" -IsMultiJobVar Write-PipelineSetVariable -Name 'UseBaselineCoreRun' -Value "$UseBaselineCoreRun" -IsMultiJobVariable $false Write-PipelineSetVariable -Name 'RunFromPerfRepo' -Value "$RunFromPerformanceRepo" -IsMultiJobVariable $false Write-PipelineSetVariable -Name 'Compare' -Value "$Compare" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'MonoDotnet' -Value "$UsingMono" -IsMultiJobVariable $false # Helix Arguments Write-PipelineSetVariable -Name 'Creator' -Value "$Creator" -IsMultiJobVariable $false @@ -112,4 +139,4 @@ Write-PipelineSetVariable -Name 'Queue' -Value "$Queue" -IsMultiJobVariable $fal Write-PipelineSetVariable -Name 'HelixSourcePrefix' -Value "$HelixSourcePrefix" -IsMultiJobVariable $false Write-PipelineSetVariable -Name '_BuildConfig' -Value "$Architecture.$Kind.$Framework" -IsMultiJobVariable $false -exit 0 +exit 0 \ No newline at end of file diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh index 34eed8b672f18..9409e4d85e92e 100755 --- a/eng/common/performance/performance-setup.sh +++ b/eng/common/performance/performance-setup.sh @@ -12,13 +12,18 @@ commit_sha=$BUILD_SOURCEVERSION build_number=$BUILD_BUILDNUMBER internal=false compare=false +mono_dotnet= kind="micro" +llvm=false +monointerpreter=false +monoaot=false run_categories="Libraries Runtime" csproj="src\benchmarks\micro\MicroBenchmarks.csproj" configurations="CompliationMode=$compilation_mode RunKind=$kind" run_from_perf_repo=false use_core_run=true use_baseline_core_run=true +using_mono=false while (($# > 0)); do lowerI="$(echo $1 | awk '{print tolower($0)}')" @@ -65,6 +70,7 @@ while (($# > 0)); do ;; --kind) kind=$2 + configurations="CompliationMode=$compilation_mode RunKind=$kind" shift 2 ;; --runcategories) @@ -79,6 +85,22 @@ while (($# > 0)); do internal=true shift 1 ;; + --llvm) + llvm=true + shift 1 + ;; + --monointerpreter) + monointerpreter=true + shift 1 + ;; + --monoaot) + monoaot=true + shift 1 + ;; + --monodotnet) + mono_dotnet=$2 + shift 2 + ;; --compare) compare=true shift 1 @@ -107,6 +129,7 @@ while (($# > 0)); do echo " --kind Related to csproj. The kind of benchmarks that should be run. Defaults to micro" echo " --runcategories Related to csproj. Categories of benchmarks to run. Defaults to \"coreclr corefx\"" echo " --internal If the benchmarks are running as an official job." + echo " --monodotnet Pass the path to the mono dotnet for mono performance testing." echo "" exit 0 ;; @@ -164,6 +187,10 @@ if [[ "$internal" == true ]]; then fi fi +if [[ "$mono_dotnet" != "" ]]; then + configurations="$configurations LLVM=$llvm MonoInterpreter=$monointerpreter MonoAOT=$monoaot" +fi + common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs $configurations --architecture $architecture" setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments" @@ -186,6 +213,12 @@ else mv $docs_directory $workitem_directory fi +if [[ "$mono_dotnet" != "" ]]; then + using_mono=true + mono_dotnet_path=$payload_directory/dotnet-mono + mv $mono_dotnet $mono_dotnet_path +fi + if [[ "$use_core_run" = true ]]; then new_core_root=$payload_directory/Core_Root mv $core_root_directory $new_core_root @@ -221,3 +254,4 @@ Write-PipelineSetVariable -name "HelixSourcePrefix" -value "$helix_source_prefix Write-PipelineSetVariable -name "Kind" -value "$kind" -is_multi_job_variable false Write-PipelineSetVariable -name "_BuildConfig" -value "$architecture.$kind.$framework" -is_multi_job_variable false Write-PipelineSetVariable -name "Compare" -value "$compare" -is_multi_job_variable false +Write-PipelineSetVariable -name "MonoDotnet" -value "$using_mono" -is_multi_job_variable false diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh index f87f195bb8ceb..33c3f0d8072a4 100755 --- a/eng/common/pipeline-logging-functions.sh +++ b/eng/common/pipeline-logging-functions.sh @@ -176,4 +176,4 @@ function Write-PipelinePrependPath { if [[ "$ci" == true ]]; then echo "##vso[task.prependpath]$prepend_path" fi -} +} \ No newline at end of file diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1 index 22eeb2656a2bf..8e9527113ca08 100644 --- a/eng/common/post-build/symbols-validation.ps1 +++ b/eng/common/post-build/symbols-validation.ps1 @@ -2,7 +2,8 @@ param( [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where NuGet packages to be checked are stored [Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation [Parameter(Mandatory=$true)][string] $DotnetSymbolVersion, # Version of dotnet symbol to use - [Parameter(Mandatory=$false)][switch] $ContinueOnError # If we should keep checking symbols after an error + [Parameter(Mandatory=$false)][switch] $ContinueOnError, # If we should keep checking symbols after an error + [Parameter(Mandatory=$false)][switch] $Clean # Clean extracted symbols directory after checking symbols ) function FirstMatchingSymbolDescriptionOrDefault { @@ -81,7 +82,14 @@ function CountMissingSymbols { $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath 'Symbols' - [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) + try { + [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) + } + catch { + Write-Host "Something went wrong extracting $PackagePath" + Write-Host $_ + return -1 + } Get-ChildItem -Recurse $ExtractPath | Where-Object {$RelevantExtensions -contains $_.Extension} | @@ -116,6 +124,10 @@ function CountMissingSymbols { } } + if ($Clean) { + Remove-Item $ExtractPath -Recurse -Force + } + Pop-Location return $MissingSymbols @@ -151,7 +163,7 @@ function CheckSymbolsAvailable { if ($Status -ne 0) { Write-PipelineTelemetryError -Category 'CheckSymbols' -Message "Missing symbols for $Status modules in the package $FileName" - + if ($ContinueOnError) { $TotalFailures++ } diff --git a/eng/common/sdl/NuGet.config b/eng/common/sdl/NuGet.config index a8213a55c4c0a..0c5451c11415f 100644 --- a/eng/common/sdl/NuGet.config +++ b/eng/common/sdl/NuGet.config @@ -1,4 +1,4 @@ - + diff --git a/eng/common/templates/job/performance.yml b/eng/common/templates/job/performance.yml index 53be464a30bcb..f877fd7a89800 100644 --- a/eng/common/templates/job/performance.yml +++ b/eng/common/templates/job/performance.yml @@ -92,4 +92,4 @@ jobs: Creator: $(Creator) WorkItemTimeout: 4:00 # 4 hours WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy - CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions + CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions \ No newline at end of file diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 47be0bedd71d4..b51bc5375ecf0 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -40,6 +40,8 @@ parameters: Net5Preview3ChannelId: 739 Net5Preview4ChannelId: 856 Net5Preview5ChannelId: 857 + NetCoreSDK313xxChannelId: 759 + NetCoreSDK313xxInternalChannelId: 760 NetCoreSDK314xxChannelId: 921 NetCoreSDK314xxInternalChannelId: 922 @@ -66,7 +68,7 @@ stages: inputs: filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1 arguments: -PromoteToChannels "$(TargetChannels)" - -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview3ChannelId}},${{parameters.Net5Preview4ChannelId}},${{parameters.Net5Preview5ChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}} + -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview3ChannelId}},${{parameters.Net5Preview4ChannelId}},${{parameters.Net5Preview5ChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}} - job: displayName: NuGet Validation @@ -408,3 +410,29 @@ stages: transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_313xx_Publishing' + channelName: '.NET Core SDK 3.1.3xx' + channelId: ${{ parameters.NetCoreSDK313xxChannelId }} + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' + +- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml + parameters: + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'NETCore_SDK_313xx_Internal_Publishing' + channelName: '.NET Core SDK 3.1.3xx Internal' + channelId: ${{ parameters.NetCoreSDK313xxInternalChannelId }} + transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' diff --git a/eng/common/templates/steps/run-script-ifequalelse.yml b/eng/common/templates/steps/run-script-ifequalelse.yml index 2dcd9d12aaf86..3d1242f5587c8 100644 --- a/eng/common/templates/steps/run-script-ifequalelse.yml +++ b/eng/common/templates/steps/run-script-ifequalelse.yml @@ -30,4 +30,4 @@ steps: name: ${{ parameters.name }} displayName: ${{ parameters.displayName }} env: ${{ parameters.env }} - condition: ${{ parameters.condition }} + condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index f31377a6be54c..d8dfc5e00498c 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -7,9 +7,11 @@ # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names. [string]$configuration = if (Test-Path variable:configuration) { $configuration } else { 'Debug' } +# Set to true to opt out of outputting binary log while running in CI +[bool]$excludeCIBinarylog = if (Test-Path variable:excludeCIBinarylog) { $excludeCIBinarylog } else { $false } + # Set to true to output binary log from msbuild. Note that emitting binary log slows down the build. -# Binary log must be enabled on CI. -[bool]$binaryLog = if (Test-Path variable:binaryLog) { $binaryLog } else { $ci } +[bool]$binaryLog = if (Test-Path variable:binaryLog) { $binaryLog } else { $ci -and !$excludeCIBinarylog } # Set to true to use the pipelines logger which will enable Azure logging output. # https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md @@ -55,10 +57,8 @@ set-strictmode -version 2.0 $ErrorActionPreference = 'Stop' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -function Create-Directory([string[]] $path) { - if (!(Test-Path $path)) { - New-Item -path $path -force -itemType 'Directory' | Out-Null - } +function Create-Directory ([string[]] $path) { + New-Item -Path $path -Force -ItemType 'Directory' | Out-Null } function Unzip([string]$zipfile, [string]$outpath) { @@ -605,8 +605,8 @@ function MSBuild() { # function MSBuild-Core() { if ($ci) { - if (!$binaryLog) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build.' + if (!$binaryLog -and !$excludeCIBinarylog) { + Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build, or explicitly opted-out from with the -excludeCIBinarylog switch.' ExitWithExitCode 1 } diff --git a/eng/common/tools.sh b/eng/common/tools.sh index a9dff4408c234..e94fce22ec37b 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -18,9 +18,17 @@ fi # Build configuration. Common values include 'Debug' and 'Release', but the repository may use other names. configuration=${configuration:-'Debug'} +# Set to true to opt out of outputting binary log while running in CI +exclude_ci_binary_log=${exclude_ci_binary_log:-false} + +if [[ "$ci" == true && "$exclude_ci_binary_log" == false ]]; then + binary_log_default=true +else + binary_log_default=false +fi + # Set to true to output binary log from msbuild. Note that emitting binary log slows down the build. -# Binary log must be enabled on CI. -binary_log=${binary_log:-$ci} +binary_log=${binary_log:-$binary_log_default} # Turns on machine preparation/clean up code that changes the machine state (e.g. kills build processes). prepare_machine=${prepare_machine:-false} @@ -404,8 +412,8 @@ function MSBuild { function MSBuild-Core { if [[ "$ci" == true ]]; then - if [[ "$binary_log" != true ]]; then - Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build." + if [[ "$binary_log" != true && "$exclude_ci_binary_log" != true ]]; then + Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build, or explicitly opted-out from with the -noBinaryLog switch." ExitWithExitCode 1 fi diff --git a/eng/install-native-dependencies.sh b/eng/install-native-dependencies.sh old mode 100644 new mode 100755 index be154811ea7f1..00be5a6287289 --- a/eng/install-native-dependencies.sh +++ b/eng/install-native-dependencies.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash if [ "$1" = "Linux" ]; then sudo apt update @@ -9,36 +9,9 @@ if [ "$1" = "Linux" ]; then if [ "$?" != "0" ]; then exit 1; fi -elif [ "$1" = "OSX" ]; then - brew update - brew upgrade - if [ "$?" != "0" ]; then - exit 1; - fi - brew install autoconf automake icu4c libtool openssl@1.1 pkg-config python3 - if [ "$?" != "0" ]; then - exit 1; - fi - if [ "$?" != "0" ]; then - exit 1; - fi -elif [ "$1" = "tvOS" ]; then - brew update - brew upgrade - if [ "$?" != "0" ]; then - exit 1; - fi - brew install autoconf automake libtool openssl@1.1 pkg-config python3 - if [ "$?" != "0" ]; then - exit 1; - fi -elif [ "$1" = "iOS" ]; then - brew update - brew upgrade - if [ "$?" != "0" ]; then - exit 1; - fi - brew install autoconf automake libtool openssl@1.1 pkg-config python3 +elif [ "$1" = "OSX" ] || [ "$1" = "tvOS" ] || [ "$1" = "iOS" ]; then + engdir=$(dirname "${BASH_SOURCE[0]}") + brew bundle --no-lock --file "${engdir}/Brewfile" if [ "$?" != "0" ]; then exit 1; fi diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index 920392bae3260..42cae8568797a 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -76,6 +76,7 @@ x64 x86 x64 + x64 @@ -133,9 +134,9 @@ true - - @@ -182,6 +183,18 @@ $(LibrariesNativeArtifactsPath)*.dwarf; $(LibrariesNativeArtifactsPath)*.pdb" IsNative="true" /> + + diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 27381c68d0e35..c231a01d42957 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -56,7 +56,7 @@ check_prereqs() local cmake_version="$(cmake --version | awk '/^cmake.* version [0-9]+\.[0-9]+\.[0-9]+$/ {print $3}')" if [[ "$(version "$cmake_version")" -lt "$(version 3.14.2)" ]]; then - echo "Please install CMake 3.14.2 or newer from http://www.cmake.org/download/ or https://apt.kitware.com and ensure it is on your path."; exit 1; + echo "Please install CMake 3.14.2 or newer from https://cmake.org/download/ or https://apt.kitware.com and ensure it is on your path."; exit 1; fi if [[ "$__HostOS" == "OSX" ]]; then @@ -409,7 +409,7 @@ done # Get the number of processors available to the scheduler # Other techniques such as `nproc` only get the number of # processors available to a single process. -platform=$(uname) +platform="$(uname)" if [[ "$platform" == "FreeBSD" ]]; then __NumProc=$(sysctl hw.ncpu | awk '{ print $2+1 }') elif [[ "$platform" == "NetBSD" || "$platform" == "SunOS" ]]; then diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 735f77b028217..a6e6ba45808d2 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -227,15 +227,13 @@ if (CLR_CMAKE_HOST_UNIX) if(CLR_CMAKE_HOST_OSX) message("Detected OSX x86_64") - endif(CLR_CMAKE_HOST_OSX) - - if(CLR_CMAKE_HOST_FREEBSD) + elseif(CLR_CMAKE_HOST_FREEBSD) message("Detected FreeBSD amd64") - endif(CLR_CMAKE_HOST_FREEBSD) - - if(CLR_CMAKE_HOST_NETBSD) + elseif(CLR_CMAKE_HOST_NETBSD) message("Detected NetBSD amd64") - endif(CLR_CMAKE_HOST_NETBSD) + elseif(CLR_CMAKE_HOST_SUNOS) + message("Detected SunOS amd64") + endif(CLR_CMAKE_HOST_OSX) endif(CLR_CMAKE_HOST_UNIX) if (CLR_CMAKE_HOST_WIN32) @@ -373,6 +371,8 @@ if(CLR_CMAKE_TARGET_UNIX) add_definitions(-DTARGET_LINUX) elseif(CLR_CMAKE_TARGET_NETBSD) add_definitions(-DTARGET_NETBSD) + elseif(CLR_CMAKE_TARGET_SUNOS) + add_definitions(-DTARGET_SUNOS) elseif(CLR_CMAKE_TARGET_ANDROID) add_definitions(-DTARGET_ANDROID) endif() diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index 1c5254d84965a..04fdfaed45a99 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -88,6 +88,8 @@ if(CLR_CMAKE_HOST_OS STREQUAL iOS) set(CLR_CMAKE_HOST_IOS 1) if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") set(CLR_CMAKE_HOST_UNIX_AMD64 1) + elseif(CMAKE_OSX_ARCHITECTURES MATCHES "i386") + set(CLR_CMAKE_HOST_UNIX_X86 1) elseif(CMAKE_OSX_ARCHITECTURES MATCHES "armv7") set(CLR_CMAKE_HOST_UNIX_ARM 1) elseif(CMAKE_OSX_ARCHITECTURES MATCHES "arm64") @@ -168,6 +170,7 @@ endif(CLR_CMAKE_HOST_OS STREQUAL Windows) if(CLR_CMAKE_HOST_OS STREQUAL Emscripten) #set(CLR_CMAKE_HOST_UNIX 1) # TODO: this should be reenabled but it activates a bunch of additional compiler flags in configurecompiler.cmake set(CLR_CMAKE_HOST_UNIX_WASM 1) + set(CLR_CMAKE_HOST_BROWSER 1) endif(CLR_CMAKE_HOST_OS STREQUAL Emscripten) #-------------------------------------------- @@ -315,7 +318,7 @@ endif(CLR_CMAKE_TARGET_OS STREQUAL SunOS) if(CLR_CMAKE_TARGET_OS STREQUAL Emscripten) set(CLR_CMAKE_TARGET_UNIX 1) set(CLR_CMAKE_TARGET_LINUX 1) - set(CLR_CMAKE_TARGET_EMSCRIPTEN 1) + set(CLR_CMAKE_TARGET_BROWSER 1) endif(CLR_CMAKE_TARGET_OS STREQUAL Emscripten) if(CLR_CMAKE_TARGET_UNIX) @@ -357,7 +360,7 @@ else() endif() endif() -if(NOT CLR_CMAKE_TARGET_EMSCRIPTEN) +if(NOT CLR_CMAKE_TARGET_BROWSER) # Skip check_pie_supported call on Android as ld from llvm toolchain with NDK API level 21 # complains about missing linker flag `-no-pie` (while level 28's ld does support this flag, # but since we know that PIE is supported, we can safely skip this redundant check). diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake index b63ab0f1a66d5..4fb94531d7698 100644 --- a/eng/native/configuretools.cmake +++ b/eng/native/configuretools.cmake @@ -6,7 +6,7 @@ if (CMAKE_C_COMPILER MATCHES "-?[0-9]+(\.[0-9]+)?$") set(CLR_CMAKE_COMPILER_FILE_NAME_VERSION "${CMAKE_MATCH_0}") endif() -if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_ARCH_WASM) +if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(APPLE) set(TOOLSET_PREFIX "") diff --git a/eng/notSupported.SourceBuild.targets b/eng/notSupported.SourceBuild.targets index afbbdd32de404..743c4a3ace00b 100644 --- a/eng/notSupported.SourceBuild.targets +++ b/eng/notSupported.SourceBuild.targets @@ -3,7 +3,11 @@ BeforeTargets="BeforeCompile" Condition="'$(DotNetBuildFromSource)' == 'true' and ('$(GeneratePlatformNotSupportedAssembly)' == 'true' or '$(GeneratePlatformNotSupportedAssemblyMessage)' != '')"> - + + + $(IntermediateOutputPath) + + diff --git a/eng/outerBuild.targets b/eng/outerBuild.targets index dd546d6bd6f6b..2c529a56aa2f9 100644 --- a/eng/outerBuild.targets +++ b/eng/outerBuild.targets @@ -1,7 +1,7 @@ - + diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index e0f71a3f128a9..29071209e79dc 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -28,7 +28,7 @@ jobs: - template: /eng/pipelines/common/clone-checkout-bundle-step.yml - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: - - script: sh $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} displayName: Install Build Dependencies - script: | diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 39866387e12b9..1e0e7316d17a5 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -332,6 +332,26 @@ jobs: helixQueueGroup: ${{ parameters.helixQueueGroup }} ${{ insert }}: ${{ parameters.jobParameters }} +# iOS x86 + +- ${{ if containsValue(parameters.platforms, 'iOS_x86') }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + osGroup: iOS + archType: x86 + platform: iOS_x86 + jobParameters: + runtimeFlavor: mono + stagedBuild: ${{ parameters.stagedBuild }} + buildConfig: ${{ parameters.buildConfig }} + ${{ if eq(parameters.passPlatforms, true) }}: + platforms: ${{ parameters.platforms }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + managedTestBuildOsGroup: OSX + ${{ insert }}: ${{ parameters.jobParameters }} + # iOS arm - ${{ if containsValue(parameters.platforms, 'iOS_arm') }}: diff --git a/eng/pipelines/common/templates/runtimes/build-test-job.yml b/eng/pipelines/common/templates/runtimes/build-test-job.yml index 4d55b818ef6fb..36f5cb686b3f5 100644 --- a/eng/pipelines/common/templates/runtimes/build-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/build-test-job.yml @@ -21,6 +21,7 @@ parameters: pool: '' runtimeFlavor: 'coreclr' runtimeFlavorDisplayName: 'CoreCLR' + runtimeVariant: '' ### Build managed test components (native components are getting built as part ### of the the product build job). @@ -39,6 +40,7 @@ jobs: osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} container: ${{ parameters.container }} + runtimeVariant: ${{ parameters.runtimeVariant }} testGroup: ${{ parameters.testGroup }} stagedBuild: ${{ parameters.stagedBuild }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} @@ -66,7 +68,7 @@ jobs: # by switching over to using reference assembly. ${{ if ne(parameters.stagedBuild, true) }}: dependsOn: - - ${{ format('coreclr_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, coalesce(parameters.liveRuntimeBuildConfig, parameters.buildConfig)) }} + - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, coalesce(parameters.liveRuntimeBuildConfig, parameters.buildConfig)) }} - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} @@ -81,7 +83,7 @@ jobs: # Install test build dependencies - ${{ if eq(parameters.osGroup, 'OSX') }}: - - script: sh $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) displayName: Install native dependencies - ${{ if eq(parameters.osGroup, 'Windows_NT') }}: # Necessary to install correct cmake version diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index 028188f1e0344..a4fe9f78544dc 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -17,12 +17,11 @@ parameters: stagedBuild: false displayNameArgs: '' runInUnloadableContext: false + runtimeVariant: '' variables: {} pool: '' runtimeFlavor: 'coreclr' runtimeFlavorDisplayName: 'CoreCLR' - runtimeMode: '' - runtimeModeDisplayName: '' ### Test run job @@ -43,6 +42,7 @@ jobs: stagedBuild: ${{ parameters.stagedBuild }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} helixType: 'build/tests/' + runtimeVariant: ${{ parameters.runtimeVariant }} pool: ${{ parameters.pool }} condition: ${{ parameters.condition }} @@ -57,18 +57,18 @@ jobs: - ${{ if ne(parameters.testGroup, 'innerloop') }}: - '${{ parameters.runtimeFlavor }}_common_test_build_p1_AnyOS_AnyCPU_${{parameters.buildConfig }}' - ${{ if ne(parameters.stagedBuild, true) }}: - - ${{ format('{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + - ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} # Compute job name from template parameters ${{ if eq(parameters.testGroup, 'innerloop') }}: - name: 'run_test_p0_${{ parameters.runtimeFlavor }}${{ parameters.runtimeMode }}_${{ parameters.displayNameArgs }}_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_${{ parameters.buildConfig }}' - displayName: '${{ parameters.runtimeFlavorDisplayName }} ${{ parameters.runtimeModeDisplayName}} Pri0 Runtime Tests Run ${{ parameters.displayNameArgs }} ${{ parameters.osGroup }}${{ parameters.osSubgroup }} ${{ parameters.archType }} ${{ parameters.buildConfig }}' + name: 'run_test_p0_${{ parameters.runtimeFlavor }}${{ parameters.runtimeVariant }}_${{ parameters.displayNameArgs }}_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_${{ parameters.buildConfig }}' + displayName: '${{ parameters.runtimeFlavorDisplayName }} ${{ parameters.runtimeVariant}} Pri0 Runtime Tests Run ${{ parameters.displayNameArgs }} ${{ parameters.osGroup }}${{ parameters.osSubgroup }} ${{ parameters.archType }} ${{ parameters.buildConfig }}' ${{ if ne(parameters.testGroup, 'innerloop') }}: name: 'run_test_p1_${{ parameters.displayNameArgs }}_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_${{ parameters.buildConfig }}' - displayName: '${{ parameters.runtimeFlavorDisplayName }} ${{ parameters.runtimeModeDisplayName }} Pri1 Runtime Tests Run ${{ parameters.displayNameArgs }} ${{ parameters.osGroup }}${{ parameters.osSubgroup }} ${{ parameters.archType }} ${{ parameters.buildConfig }}' + displayName: '${{ parameters.runtimeFlavorDisplayName }} ${{ parameters.runtimeVariant }} Pri1 Runtime Tests Run ${{ parameters.displayNameArgs }} ${{ parameters.osGroup }}${{ parameters.osSubgroup }} ${{ parameters.archType }} ${{ parameters.buildConfig }}' variables: - name: testhostArg @@ -103,10 +103,6 @@ jobs: - name: crossgenArg value: 'composite' - - ${{ if eq(parameters.runtimeMode, 'interpreter') }}: - - name: RuntimeModeDisplayName - value: 'Interpreter' - # Set job timeouts # # "timeoutPerTestCollectionInMinutes" is the time needed for the "biggest" xUnit test collection to complete. @@ -277,7 +273,7 @@ jobs: - script: $(_msbuildCommand) $(Build.SourcesDirectory)/src/mono/mono.proj /t:PatchCoreClrCoreRoot - /p:Configuration=$(buildConfig) + /p:Configuration=$(buildConfigUpper) /p:TargetArchitecture=$(archType) displayName: "Patch dotnet with mono" @@ -288,6 +284,7 @@ jobs: buildConfig: $(buildConfigUpper) archType: ${{ parameters.archType }} osGroup: ${{ parameters.osGroup }} + osSubgroup: ${{ parameters.osSubgroup}} coreClrRepoRoot: $(coreClrRepoRoot) runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} @@ -338,7 +335,10 @@ jobs: ${{ if in(parameters.testGroup, 'innerloop', 'outerloop') }}: scenarios: - normal - - no_tiered_compilation + - ${{ if eq(parameters.runtimeFlavor, 'coreclr') }}: + - no_tiered_compilation + - ${{ if eq(parameters.runtimeFlavor, 'mono') }}: + - interpreter ${{ if in(parameters.testGroup, 'jitstress') }}: scenarios: - jitminopts @@ -456,12 +456,13 @@ jobs: - jitguardeddevirtualization - jitehwritethru - jitobjectstackallocation + - jitpgo # Publish Logs - task: PublishPipelineArtifact@1 displayName: Publish Logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - artifactName: '${{ parameters.runtimeFlavor }}_${{ parameters.runtimeMode }}_$(LogNamePrefix)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.testGroup }}' + artifactName: '${{ parameters.runtimeFlavor }}_${{ parameters.runtimeVariant }}_$(LogNamePrefix)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.testGroup }}' continueOnError: true condition: always() diff --git a/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml b/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml index 2fc09a15ecd6b..3602929653dc3 100644 --- a/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml +++ b/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml @@ -3,6 +3,7 @@ parameters: condition: '' archType: '' osGroup: '' + osSubgroup: '' buildConfig: '' creator: '' publishTestResults: '' @@ -23,7 +24,7 @@ parameters: gcSimulatorTests: '' coreClrRepoRoot: '' runtimeFlavorDisplayName: 'CoreCLR' - runtimeMode: '' + runtimeVariant: '' steps: - ${{ if eq(parameters.osGroup, 'Windows_NT') }}: @@ -39,7 +40,7 @@ steps: condition: ${{ parameters.condition }} env: __BuildArch: ${{ parameters.archType }} - __TargetOS: ${{ parameters.osGroup }} + __TargetOS: ${{ parameters.osGroup }}${{ parameters.osSubgroup }} __BuildType: ${{ parameters.buildConfig }} _Creator: ${{ parameters.creator }} _PublishTestResults: ${{ parameters.publishTestResults }} @@ -58,7 +59,7 @@ steps: _TimeoutPerTestCollectionInMinutes: ${{ parameters.timeoutPerTestCollectionInMinutes }} _TimeoutPerTestInMinutes: ${{ parameters.timeoutPerTestInMinutes }} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} - _RuntimeMode: ${{ parameters.runtimeMode }} + _RuntimeVariant: ${{ parameters.runtimeVariant }} ${{ if eq(parameters.publishTestResults, 'true') }}: SYSTEM_ACCESSTOKEN: $(System.AccessToken) # TODO: remove NUGET_PACKAGES once https://github.com/dotnet/arcade/issues/1578 is fixed @@ -81,7 +82,7 @@ steps: condition: ${{ parameters.condition }} env: __BuildArch: ${{ parameters.archType }} - __TargetOS: ${{ parameters.osGroup }} + __TargetOS: ${{ parameters.osGroup }}${{ parameters.osSubgroup }} __BuildType: ${{ parameters.buildConfig }} _Creator: ${{ parameters.creator }} _PublishTestResults: ${{ parameters.publishTestResults }} @@ -100,7 +101,7 @@ steps: _TimeoutPerTestCollectionInMinutes: ${{ parameters.timeoutPerTestCollectionInMinutes }} _TimeoutPerTestInMinutes: ${{ parameters.timeoutPerTestInMinutes }} runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }} - _RuntimeMode: ${{ parameters.runtimeMode }} + _RuntimeVariant: ${{ parameters.runtimeVariant }} ${{ if eq(parameters.publishTestResults, 'true') }}: SYSTEM_ACCESSTOKEN: $(System.AccessToken) # TODO: remove NUGET_PACKAGES once https://github.com/dotnet/arcade/issues/1578 is fixed diff --git a/eng/pipelines/coreclr/ci.yml b/eng/pipelines/coreclr/ci.yml index 51bb6e746eb64..7e72c87e16b86 100644 --- a/eng/pipelines/coreclr/ci.yml +++ b/eng/pipelines/coreclr/ci.yml @@ -8,6 +8,7 @@ trigger: - '*' - src/libraries/System.Private.CoreLib/* exclude: + - .github/* - docs/* - CODE-OF-CONDUCT.md - CONTRIBUTING.md diff --git a/eng/pipelines/coreclr/perf.yml b/eng/pipelines/coreclr/perf.yml index ffa22b8afc751..d2ed639d434bd 100644 --- a/eng/pipelines/coreclr/perf.yml +++ b/eng/pipelines/coreclr/perf.yml @@ -8,6 +8,7 @@ trigger: - '*' - src/libraries/System.Private.CoreLib/* exclude: + - .github/* - docs/* - CODE-OF-CONDUCT.md - CONTRIBUTING.md @@ -60,11 +61,32 @@ jobs: - Windows_NT_x86 jobParameters: testGroup: perf - + +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/mono/templates/build-job.yml + runtimeFlavor: mono + buildConfig: release + platforms: + - Linux_x64 + +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - Linux_x64 + jobParameters: + testGroup: perf + liveLibrariesBuildConfig: Release + runtimeType: mono + - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml buildConfig: release + runtimeFlavor: coreclr platforms: - Linux_x64 - Windows_NT_x64 diff --git a/eng/pipelines/coreclr/r2r.yml b/eng/pipelines/coreclr/r2r.yml index b8e5d6e59f3b0..0a645418f02e9 100644 --- a/eng/pipelines/coreclr/r2r.yml +++ b/eng/pipelines/coreclr/r2r.yml @@ -24,6 +24,8 @@ jobs: - Linux_arm - Linux_arm64 - Linux_x64 + - Windows_NT_arm + - Windows_NT_arm64 - Windows_NT_x64 - Windows_NT_x86 - CoreClrTestBuildHost # Either OSX_x64 or Linux_x64 @@ -47,6 +49,8 @@ jobs: - Linux_arm - Linux_arm64 - Linux_x64 + - Windows_NT_arm + - Windows_NT_arm64 - Windows_NT_x64 - Windows_NT_x86 helixQueueGroup: ci diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index d0ed04b5b0c6a..91201c3b74dfb 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -10,6 +10,7 @@ parameters: osSubgroup: '' platform: '' pool: '' + runtimeVariant: '' signBinaries: false stagedBuild: false testGroup: '' @@ -25,6 +26,7 @@ jobs: archType: ${{ parameters.archType }} osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} + runtimeVariant: ${{ parameters.runtimeVariant }} testGroup: ${{ parameters.testGroup }} helixType: 'build/product/' enableMicrobuild: true @@ -37,8 +39,8 @@ jobs: name: ${{ format('coreclr_{0}_product_build_{1}{1}_{3}_{4}', parameters.compilerName, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} displayName: ${{ format('CoreCLR GCC Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} ${{ if eq(parameters.compilerName, 'clang') }}: - name: ${{ format('coreclr_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - displayName: ${{ format('CoreCLR Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + name: ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + displayName: ${{ format('CoreCLR {0} Product Build {1}{2} {3} {4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} # Run all steps in the container. # Note that the containers are defined in platform-matrix.yml @@ -104,7 +106,7 @@ jobs: # and FreeBSD builds use a build agent with dependencies # preinstalled, so we only need this step for OSX and Windows. - ${{ if eq(parameters.osGroup, 'OSX') }}: - - script: sh $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) displayName: Install native dependencies - ${{ if eq(parameters.osGroup, 'Windows_NT') }}: # Necessary to install python diff --git a/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml b/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml index cfecf9bbd5c06..0e537cb6c7e17 100644 --- a/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml +++ b/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml @@ -5,6 +5,7 @@ parameters: osSubgroup: '' container: '' helixQueues: '' + runtimeVariant: '' crossrootfsDir: '' stagedBuild: false variables: {} @@ -30,6 +31,7 @@ jobs: osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} stagedBuild: ${{ parameters.stagedBuild }} + runtimeVariant: ${{ parameters.runtimeVariant }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} helixType: 'test/crossgen-comparison/' pool: ${{ parameters.pool }} @@ -72,7 +74,7 @@ jobs: # Test job depends on the corresponding build job dependsOn: - - ${{ format('coreclr_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index 1e532b52ead0e..003e58f276146 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -4,9 +4,11 @@ parameters: osGroup: '' osSubgroup: '' container: '' + runtimeVariant: '' framework: net5.0 # Specify the appropriate framework when running release branches (ie netcoreapp3.0 for release/3.0) liveLibrariesBuildConfig: '' variables: {} + runtimeType: 'coreclr' pool: '' ### Perf job @@ -18,24 +20,34 @@ jobs: - template: run-performance-job.yml parameters: # Compute job name from template parameters - jobName: ${{ format('perfbuild_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - displayName: ${{ format('Performance {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + jobName: ${{ format('perfbuild_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType) }} + displayName: ${{ format('Performance {0}{1} {2} {3} {4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType) }} pool: ${{ parameters.pool }} buildConfig: ${{ parameters.buildConfig }} archType: ${{ parameters.archType }} osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} + runtimeVariant: ${{ parameters.runtimeVariant }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} + runtimeType: ${{ parameters.runtimeType }} # Test job depends on the corresponding build job dependsOn: - - ${{ format('coreclr_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} + - ${{ if eq(parameters.runtimeType, 'mono') }}: + - ${{ format('mono_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} ${{ if eq(parameters.osGroup, 'Windows_NT') }}: - extraSetupParameters: -CoreRootDirectory $(Build.SourcesDirectory)\artifacts\tests\coreclr\${{ parameters.osGroup }}.${{ parameters.archType }}.Release\Tests\Core_Root -Architecture ${{ parameters.archType }} + ${{ if eq(parameters.runtimeType, 'mono') }}: + extraSetupParameters: -Architecture ${{ parameters.archType }} -MonoDotnet $(Build.SourcesDirectory)\.dotnet-mono -Kind micro_mono + ${{ if ne(parameters.runtimeType, 'mono') }}: + extraSetupParameters: -CoreRootDirectory $(Build.SourcesDirectory)\artifacts\tests\coreclr\${{ parameters.osGroup }}.${{ parameters.archType }}.Release\Tests\Core_Root -Architecture ${{ parameters.archType }} ${{ if ne(parameters.osGroup, 'Windows_NT') }}: - extraSetupParameters: --corerootdirectory $(Build.SourcesDirectory)/artifacts/tests/coreclr/${{ parameters.osGroup }}.${{ parameters.archType }}.Release/Tests/Core_Root --architecture ${{ parameters.archType }} + ${{ if eq(parameters.runtimeType, 'mono') }}: + extraSetupParameters: --architecture ${{ parameters.archType }} --monodotnet $(Build.SourcesDirectory)/.dotnet-mono --kind micro_mono + ${{ if ne(parameters.runtimeType, 'mono') }}: + extraSetupParameters: --corerootdirectory $(Build.SourcesDirectory)/artifacts/tests/coreclr/${{ parameters.osGroup }}.${{ parameters.archType }}.Release/Tests/Core_Root --architecture ${{ parameters.archType }} variables: ${{ parameters.variables }} @@ -44,7 +56,6 @@ jobs: steps: # Extra steps that will be passed to the performance template and run before sending the job to helix (all of which is done in the template) - # Optionally download live-built libraries - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - template: /eng/pipelines/common/download-artifact-step.yml @@ -64,7 +75,24 @@ jobs: artifactName: '$(buildProductArtifactName)' displayName: 'product build' + - ${{ if eq(parameters.runtimeType, 'mono') }}: + - template: /eng/pipelines/common/download-artifact-step.yml + parameters: + unpackFolder: $(librariesDownloadDir)/bin/mono/$(osGroup).$(archType).$(buildConfigUpper) + cleanUnpackFolder: false + artifactFileName: 'MonoProduct_${{ parameters.runtimeVariant }}_$(osGroup)_$(archType)_$(buildConfig)$(archiveExtension)' + artifactName: 'MonoProduct_${{ parameters.runtimeVariant }}_$(osGroup)_$(archType)_$(buildConfig)' + displayName: 'Mono runtime' # Create Core_Root - script: $(coreClrRepoRootDir)build-test$(scriptExt) $(buildConfig) $(archType) generatelayoutonly $(librariesOverrideArg) displayName: Create Core_Root + condition: and(succeeded(), ne(variables.runtimeFlavorName, 'Mono')) + + - script: "build.cmd -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)\\bin\\mono\\$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\.dotnet-mono /E /I /Y;copy $(Build.SourcesDirectory)\\artifacts\\bin\\coreclr\\$(osGroup).$(archType).$(buildConfigUpper)\\corerun.exe $(Build.SourcesDirectory)\\.dotnet-mono\\shared\\Microsoft.NETCore.App\\5.0.0\\corerun.exe" + displayName: "Create mono dotnet (Windows)" + condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), eq(variables.osGroup, 'Windows_NT')) + + - script: "mkdir $(Build.SourcesDirectory)/.dotnet-mono;./build.sh -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)/bin/mono/$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;cp $(Build.SourcesDirectory)/artifacts/bin/testhost/$(_Framework)-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/.dotnet-mono -r;cp $(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)/corerun $(Build.SourcesDirectory)/.dotnet-mono/shared/Microsoft.NETCore.App/5.0.0/corerun" + displayName: "Create mono dotnet (Linux)" + condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), ne(variables.osGroup, 'Windows_NT')) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 1e37e86c8a645..881a498fbd20d 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -16,6 +16,7 @@ parameters: timeoutInMinutes: 320 # optional -- timeout for the job enableTelemetry: false # optional -- enable for telemetry liveLibrariesBuildConfig: '' # optional -- live-live libraries configuration to use for the run + runtimeType: 'coreclr' jobs: - template: xplat-pipeline-job.yml @@ -103,3 +104,10 @@ jobs: WorkItemTimeout: 4:00 # 4 hours WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions + - task: PublishPipelineArtifact@1 + displayName: Publish Logs + inputs: + targetPath: $(Build.SourcesDirectory)/artifacts/log + artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}' + continueOnError: true + condition: always() diff --git a/eng/pipelines/coreclr/templates/xplat-pipeline-job.yml b/eng/pipelines/coreclr/templates/xplat-pipeline-job.yml index acbd675617748..191b05d26f0f1 100644 --- a/eng/pipelines/coreclr/templates/xplat-pipeline-job.yml +++ b/eng/pipelines/coreclr/templates/xplat-pipeline-job.yml @@ -69,14 +69,14 @@ jobs: # Build product defines what we are trying to build, either coreclr or mono - name: buildProductArtifactName - value: 'CoreCLRProduct_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' + value: 'CoreCLRProduct_${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' - name: buildProductRootFolderPath value: '$(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)' # We need this because both mono and coreclr build currently depends on CoreClr - name: coreClrProductArtifactName - value: 'CoreCLRProduct_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' + value: 'CoreCLRProduct_${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' - name: coreClrProductRootFolderPath value: '$(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)' diff --git a/eng/pipelines/evaluate-changed-paths.sh b/eng/pipelines/evaluate-changed-paths.sh index 0df618957245b..bfc5c857b64fe 100755 --- a/eng/pipelines/evaluate-changed-paths.sh +++ b/eng/pipelines/evaluate-changed-paths.sh @@ -162,7 +162,7 @@ probePaths() { if [[ "$include_path_string" == "" ]]; then include_path_string=":$_path" else - include_path_string="$exclude_path_string :$_path" + include_path_string="$include_path_string :$_path" fi done diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml index 8006c888ee00c..ff9600d83fea6 100644 --- a/eng/pipelines/global-build.yml +++ b/eng/pipelines/global-build.yml @@ -15,6 +15,7 @@ pr: - docs/manpages/* - eng/pipelines/global-build.yml exclude: + - .github/* - docs/* - eng/pipelines/coreclr/*.* - eng/pipelines/libraries/*.* @@ -91,4 +92,17 @@ jobs: jobParameters: testGroup: innerloop nameSuffix: Mono_Libraries - buildArgs: -subset mono+libs /p:RuntimeFlavor=Mono \ No newline at end of file + buildArgs: -subset mono+libs /p:RuntimeFlavor=Mono + +# +# SourceBuild Build +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: release + platforms: + - Linux_x64 + jobParameters: + nameSuffix: SourceBuild + buildArgs: /p:DotNetBuildFromSource=true \ No newline at end of file diff --git a/eng/pipelines/installer/installer-matrix.yml b/eng/pipelines/installer/installer-matrix.yml index bb5e6e46f96c4..e9ae06bf26769 100644 --- a/eng/pipelines/installer/installer-matrix.yml +++ b/eng/pipelines/installer/installer-matrix.yml @@ -3,6 +3,7 @@ parameters: platforms: [] jobParameters: [] buildConfig: Release + runtimeVariant: '' jobs: @@ -16,5 +17,6 @@ jobs: platforms: ${{ parameters.platforms }} passPlatforms: true runtimeFlavor: ${{ parameters.runtimeFlavor }} + runtimeVariant: ${{ parameters.runtimeVariant }} jobParameters: ${{ insert }}: ${{ parameters.jobParameters }} diff --git a/eng/pipelines/installer/jobs/base-job.yml b/eng/pipelines/installer/jobs/base-job.yml index 413f9c7c70807..8e9c3f1824bb2 100644 --- a/eng/pipelines/installer/jobs/base-job.yml +++ b/eng/pipelines/installer/jobs/base-job.yml @@ -13,6 +13,7 @@ parameters: variables: [] name: '' displayName: '' + runtimeVariant: '' pool: '' packageDistroList: @@ -38,8 +39,8 @@ parameters: platforms: [] jobs: -- job: ${{ format('installer_{0}_{1}_{2}', parameters.runtimeFlavor, coalesce(parameters.name, parameters.platform), parameters.buildConfig) }} - displayName: ${{ format('Installer Build and Test {0} {1} {2}', parameters.runtimeFlavor, coalesce(parameters.name, parameters.platform), parameters.buildConfig) }} +- job: ${{ format('installer_{0}_{1}_{2}_{3}', parameters.runtimeFlavor, parameters.runtimeVariant, coalesce(parameters.name, parameters.platform), parameters.buildConfig) }} + displayName: ${{ format('Installer Build and Test {0} {1} {2} {3}', parameters.runtimeFlavor, parameters.runtimeVariant, coalesce(parameters.name, parameters.platform), parameters.buildConfig) }} condition: and(succeeded(), ${{ parameters.condition }}) pool: ${{ parameters.pool }} @@ -79,6 +80,14 @@ jobs: - name: SignType value: test + - ${{ if eq(parameters.runtimeVariant, 'llvmjit') }}: + - name: llvmParameter + value: /p:MonoEnableLLVM=true + + - ${{ if eq(parameters.runtimeVariant, 'llvmaot') }}: + - name: llvmParameter + value: /p:MonoEnableLLVM=true /p:MonoBundleLLVMOptimizer=true + # Set up non-PR build from internal project - ${{ if eq(parameters.isOfficialBuild, true) }}: - name: SignType @@ -105,6 +114,7 @@ jobs: /p:PortableBuild=true /p:SkipTests=$(SkipTests) /p:RuntimeFlavor=${{ parameters.runtimeFlavor }} + $(llvmParameter) $(OfficialBuildArg) - name: MsbuildSigningArguments value: >- @@ -129,6 +139,7 @@ jobs: /p:PortableBuild=true /p:SkipTests=$(SkipTests) /p:RuntimeFlavor=${{ parameters.runtimeFlavor }} + $(llvmParameter) - name: BaseJobBuildCommand value: >- @@ -145,6 +156,7 @@ jobs: value: >- /p:PortableBuild=true /p:SkipTests=$(SkipTests) + $(llvmParameter) - name: BaseJobBuildCommand value: >- @@ -195,6 +207,7 @@ jobs: /p:TargetArchitecture=${{ parameters.archType }} /p:RuntimeFlavor=${{ parameters.runtimeFlavor }} $(OfficialBuildArg) + $(llvmParameter) - name: _PortableBuild value: ${{ eq(parameters.osSubgroup, '') }} @@ -292,7 +305,7 @@ jobs: /p:RuntimeArtifactsPath=$(buildCommandSourcesDirectory)$(RuntimeDownloadPath) /p:RuntimeConfiguration=${{ parameters.liveRuntimeBuildConfig }} - name: RuntimeArtifactName - value: $(runtimeFlavorName)Product_$(liveRuntimeLegName) + value: $(runtimeFlavorName)Product_${{ parameters.runtimeVariant }}_$(liveRuntimeLegName) - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - name: liveLibrariesLegName @@ -331,8 +344,9 @@ jobs: - checkout - ${{ parameters.dependsOn }} - ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}: - - ${{ format('{0}_product_build_{1}{2}_{3}_{4}', + - ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, + parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, @@ -347,7 +361,7 @@ jobs: - libraries_build_allconfigurations_Windows_NT_x64_Release - ${{ if eq(parameters.buildFullPlatformManifest, true) }}: - ${{ each platform in parameters.platforms }}: - - ${{ parameters.runtimeFlavor }}_product_build_${{ platform }}_${{ parameters.liveRuntimeBuildConfig }} + - ${{ parameters.runtimeFlavor }}_${{ parameters.runtimeVariant }}_product_build_${{ platform }}_${{ parameters.liveRuntimeBuildConfig }} - libraries_build_${{ platform }}_${{ parameters.liveLibrariesBuildConfig }} steps: @@ -443,7 +457,7 @@ jobs: cleanUnpackFolder: false - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: - - script: sh $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} displayName: Install Build Dependencies - script: | @@ -522,6 +536,7 @@ jobs: parameters: name: ${{ coalesce(parameters.name, parameters.platform) }} runtimeFlavor: ${{ parameters.runtimeFlavor }} + runtimeVariant: ${{ parameters.runtimeVariant }} skipTests: $(SkipTests) isOfficialBuild: ${{ eq(parameters.isOfficialBuild, true) }} diff --git a/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml b/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml index 672a12aa61be7..884ca0177e7f8 100644 --- a/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml +++ b/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml @@ -1,7 +1,7 @@ parameters: name: '' runtimeFlavor: 'coreclr' - + runtimeVariant: '' isOfficialBuild: false steps: @@ -38,6 +38,6 @@ steps: displayName: Publish BuildLogs inputs: targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: Installer-Logs-${{ parameters.runtimeFlavor }}-${{ parameters.name }}-$(_BuildConfig) + artifactName: Installer-Logs-${{ parameters.runtimeFlavor }}-${{ parameters.runtimeVariant }}-${{ parameters.name }}-$(_BuildConfig) continueOnError: true condition: succeededOrFailed() diff --git a/eng/pipelines/libraries/base-job.yml b/eng/pipelines/libraries/base-job.yml index 2793183d99ae6..b1a801f965789 100644 --- a/eng/pipelines/libraries/base-job.yml +++ b/eng/pipelines/libraries/base-job.yml @@ -5,8 +5,8 @@ parameters: osSubgroup: '' crossrootfsDir: '' framework: '' - isOfficialBuild: false isOfficialAllConfigurations: false + isSourceBuild: false liveRuntimeBuildConfig: '' runtimeFlavor: 'coreclr' timeoutInMinutes: 150 @@ -91,7 +91,7 @@ jobs: - _runtimeConfigurationArg: -rc ${{ parameters.liveRuntimeBuildConfig }} # Download full product dependencies for mono or test - ${{ if or(ne(parameters.runtimeFlavor, 'coreclr'), ne(parameters.testScope, '')) }}: - - _runtimeArtifactName: '$(runtimeFlavorName)Product_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_${{ parameters.liveRuntimeBuildConfig }}' + - _runtimeArtifactName: '$(runtimeFlavorName)Product_${{ parameters.runtimeVariant}}_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_${{ parameters.liveRuntimeBuildConfig }}' - _runtimeArtifactsPathArg: ' /p:RuntimeArtifactsPath=$(_runtimeDownloadPath)' - _testRunNamePrefixSuffix: $(runtimeFlavorName)_${{ parameters.liveRuntimeBuildConfig }} diff --git a/eng/pipelines/libraries/build-job.yml b/eng/pipelines/libraries/build-job.yml index f3de87e46401f..f33f413f457ee 100644 --- a/eng/pipelines/libraries/build-job.yml +++ b/eng/pipelines/libraries/build-job.yml @@ -7,6 +7,7 @@ parameters: framework: '' isOfficialBuild: false isOfficialAllConfigurations: false + runtimeVariant: '' # When set to a non-empty value (Debug / Release), it determines the runtime's # build configuration to use for building libraries and tests. Setting this @@ -43,6 +44,7 @@ jobs: container: ${{ parameters.container }} condition: ${{ parameters.condition }} pool: ${{ parameters.pool }} + runtimeVariant: ${{ parameters.runtimeVariant }} testScope: ${{ parameters.testScope }} name: build displayName: 'Build' @@ -51,7 +53,7 @@ jobs: dependsOn: # Use full product dependency for non-coreclr and test builds - ${{ if or(ne(parameters.runtimeFlavor, 'coreclr'), ne(parameters.testScope, '')) }}: - - ${{ format('{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }} + - ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }} variables: - _subset: libs @@ -74,7 +76,7 @@ jobs: - template: /eng/pipelines/common/restore-internal-tools.yml - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: - - script: sh $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} displayName: Install Build Dependencies - script: | diff --git a/eng/pipelines/libraries/build-test-job.yml b/eng/pipelines/libraries/build-test-job.yml index c58de839dbdaf..0ce715add47c9 100644 --- a/eng/pipelines/libraries/build-test-job.yml +++ b/eng/pipelines/libraries/build-test-job.yml @@ -7,6 +7,7 @@ parameters: isOfficialBuild: false liveRuntimeBuildConfig: '' runtimeFlavor: 'coreclr' + runtimeVariant: '' timeoutInMinutes: 150 container: '' publishTestArtifacs: true @@ -29,6 +30,7 @@ jobs: liveRuntimeBuildConfig: ${{ parameters.liveRuntimeBuildConfig }} timeoutInMinutes: ${{ parameters.timeoutInMinutes }} container: ${{ parameters.container }} + runtimeVariant: ${{ parameters.runtimeVariant }} pool: ${{ parameters.pool }} testScope: ${{ parameters.testScope }} name: test_build @@ -38,7 +40,7 @@ jobs: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} # Libraries Test also depends on Product, now that the libraries build only depends on corelib - ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}: - - ${{ format('{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }} + - ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }} variables: - librariesTestsArtifactName: ${{ format('libraries_test_assets_{0}_{1}_{2}', parameters.osGroup, parameters.archType, parameters.buildConfig) }} diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index c221d8b780c7f..7e450f8f4c0d0 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -58,8 +58,8 @@ jobs: - Ubuntu.1804.Amd64.Open - SLES.12.Amd64.Open - SLES.15.Amd64.Open - - (Fedora.29.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-29-helix-a12566d-20191210224553 - (Fedora.30.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-30-helix-4f8cef7-20200121150022 + - (Fedora.32.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-32-helix-20200512010618-efb9f14 - (Ubuntu.1910.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-19.10-helix-amd64-cfcfd50-20191030180623 - (Debian.10.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-bfcd90a-20200121150006 - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: @@ -69,7 +69,7 @@ jobs: - Ubuntu.1604.Amd64.Open - Ubuntu.1804.Amd64.Open - SLES.15.Amd64.Open - - (Fedora.29.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-29-helix-a12566d-20191210224553 + - (Fedora.30.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-30-helix-4f8cef7-20200121150022 # OSX x64 - ${{ if eq(parameters.platform, 'OSX_x64') }}: @@ -98,7 +98,7 @@ jobs: - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: # Bring back once: https://github.com/dotnet/runtime/issues/35689 is fixed # - Windows.7.Amd64.Open - # - Windows.81.Amd64.Open + - Windows.81.Amd64.Open - Windows.10.Amd64.Server19H1.ES.Open - ${{ if ne(parameters.jobParameters.runtimeFlavor, 'mono') }}: - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 @@ -125,8 +125,8 @@ jobs: - ${{ if eq(parameters.jobParameters.buildConfig, 'Release') }}: - Windows.10.Amd64.Server19H1.ES.Open - ${{ if eq(parameters.jobParameters.buildConfig, 'Debug') }}: + - Windows.7.Amd64.Open # Bring back once: https://github.com/dotnet/runtime/issues/35689 is fixed - # - Windows.7.Amd64.Open # - Windows.81.Amd64.Open - Windows.10.Amd64.Server19H1.Open diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index 7d982c09e7202..053d7f90044ae 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -9,6 +9,7 @@ parameters: runtimeFlavor: 'coreclr' timeoutInMinutes: 150 pool: '' + runtimeVariant: '' testScope: '' helixQueues: [] dependsOnTestBuildConfiguration: Debug @@ -27,6 +28,7 @@ jobs: isOfficialBuild: ${{ parameters.isOfficialBuild }} liveRuntimeBuildConfig: ${{ parameters.liveRuntimeBuildConfig }} runtimeFlavor: ${{ parameters.runtimeFlavor }} + runtimeVariant: ${{ parameters.runtimeVariant }} timeoutInMinutes: ${{ parameters.timeoutInMinutes }} container: '' # we just send to helix, no need to use a container. condition: ${{ parameters.condition }} @@ -47,7 +49,7 @@ jobs: - ${{ format('libraries_build_{0}_{1}{2}_{3}_{4}', parameters.framework, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ format('libraries_test_build_{0}_{1}_{2}_{3}', parameters.framework, parameters.osGroup, parameters.dependsOnTestArchitecture, parameters.dependsOnTestBuildConfiguration) }} - ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}: - - ${{ format('{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }} + - ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveRuntimeBuildConfig) }} variables: - librariesTestsArtifactName: ${{ format('libraries_test_assets_{0}_{1}_{2}', parameters.osGroup, parameters.dependsOnTestArchitecture, parameters.dependsOnTestBuildConfiguration) }} diff --git a/eng/pipelines/mono/templates/build-job.yml b/eng/pipelines/mono/templates/build-job.yml index 136c83cf522d2..901bab9a0f660 100644 --- a/eng/pipelines/mono/templates/build-job.yml +++ b/eng/pipelines/mono/templates/build-job.yml @@ -9,7 +9,7 @@ parameters: variables: {} pool: '' condition: true - llvm: false + runtimeVariant: '' isOfficialBuild: false crossrootfsDir: '' @@ -24,20 +24,13 @@ jobs: helixType: 'build/product/' enableMicrobuild: true pool: ${{ parameters.pool }} - llvm: ${{ parameters.llvm }} + runtimeVariant: ${{ parameters.runtimeVariant }} crossrootfsDir: ${{ parameters.crossroofsDir }} condition: ${{ parameters.condition }} # Compute job name from template parameters - ${{ if ne(parameters.llvm, true) }}: - name: ${{ format('mono_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - displayName: ${{ format('Mono Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - - # if LLVM enabled, set a variable we can consume - ${{ if eq(parameters.llvm, true) }}: - name: ${{ format('mono_llvm_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - displayName: ${{ format('Mono LLVM Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - + name: ${{ format('mono_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + displayName: ${{ format('Mono {0} Product Build {1}{2} {3} {4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} # Run all steps in the container. # Note that the containers are defined in platform-matrix.yml @@ -81,6 +74,12 @@ jobs: value: wasm - name: osOverride value: '-os Browser' + - ${{ if eq(parameters.runtimeVariant, 'llvmjit') }}: + - name: llvmParameter + value: /p:MonoEnableLLVM=true /p:MonoBundleLLVMOptimizer=false + - ${{ if eq(parameters.runtimeVariant, 'llvmaot') }}: + - name: llvmParameter + value: /p:MonoEnableLLVM=true /p:MonoBundleLLVMOptimizer=true - ${{ parameters.variables }} steps: @@ -90,7 +89,7 @@ jobs: # and FreeBSD builds use a build agent with dependencies # preinstalled, so we only need this step for OSX and Windows. - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS') }}: - - script: sh $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) + - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) displayName: Install native dependencies - ${{ if eq(parameters.osGroup, 'Windows_NT') }}: # Necessary to install python @@ -105,10 +104,10 @@ jobs: # Build - ${{ if ne(parameters.osGroup, 'Windows_NT') }}: - - script: ./build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) /p:MonoEnableLLVM=${{ parameters.llvm }} + - script: ./build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) $(llvmParameter) displayName: Build product - ${{ if eq(parameters.osGroup, 'Windows_NT') }}: - - script: build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) /p:MonoEnableLLVM=${{ parameters.llvm }} + - script: build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) $(llvmParameter) displayName: Build product - ${{ if in(parameters.osGroup, 'OSX', 'iOS','tvOS') }}: @@ -129,15 +128,15 @@ jobs: displayName: 'product build' # Build packages - - ${{ if and(ne(parameters.llvm, true), ne(parameters.osGroup, 'Windows_NT')) }}: - - script: ./build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) /p:MonoEnableLLVM=${{ parameters.llvm }} -pack $(OutputRidArg) + - ${{ if ne(parameters.osGroup, 'Windows_NT') }}: + - script: ./build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) $(llvmParameter) -pack $(OutputRidArg) displayName: Build nupkg - - ${{ if and(ne(parameters.llvm, true), eq(parameters.osGroup, 'Windows_NT')) }}: - - script: build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) /p:MonoEnableLLVM=${{ parameters.llvm }} -pack $(OutputRidArg) + - ${{ if eq(parameters.osGroup, 'Windows_NT') }}: + - script: build$(scriptExt) -subset mono -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) $(llvmParameter) -pack $(OutputRidArg) displayName: Build nupkg # Publish official build - - ${{ if and(ne(parameters.llvm, true), eq(parameters.publishToBlobFeed, 'true')) }}: + - ${{ if eq(parameters.publishToBlobFeed, 'true') }}: - ${{ if ne(parameters.osGroup, 'Windows_NT') }}: - script: $(Build.SourcesDirectory)/eng/common/build.sh --ci --restore --publish --configuration $(_BuildConfig) /p:DotNetPublishUsingPipelines=true /p:DotNetPublishToBlobFeed=true /p:DotNetPublishBlobFeedUrl=$(dotnetfeedUrl) /p:DotNetPublishBlobFeedKey=$(dotnetfeedPAT) /p:Configuration=$(_BuildConfig) /p:TargetArchitecture=$(archType) /p:TargetOS=$(osGroup) /p:OSIdentifier=$(osGroup)$(osSubgroup) /bl:"$(Build.SourcesDirectory)/artifacts/log/publish-pkgs.binlog" --projects $(Build.SourcesDirectory)/eng/empty.csproj displayName: Publish packages to blob feed @@ -160,9 +159,6 @@ jobs: displayName: Publish Logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - ${{ if ne(parameters.llvm, true) }}: - artifactName: 'BuildLogs_Mono_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' - ${{ if eq(parameters.llvm, true) }}: - artifactName: 'BuildLogs_Mono_LLVM_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' + artifactName: 'BuildLogs_Mono_${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' continueOnError: true condition: always() diff --git a/eng/pipelines/mono/templates/xplat-pipeline-job.yml b/eng/pipelines/mono/templates/xplat-pipeline-job.yml index 02ffcc202d3c4..364616643e86f 100644 --- a/eng/pipelines/mono/templates/xplat-pipeline-job.yml +++ b/eng/pipelines/mono/templates/xplat-pipeline-job.yml @@ -9,7 +9,7 @@ parameters: liveLibrariesBuildConfig: '' strategy: '' pool: '' - llvm: false + runtimeVariant: '' liveRuntimeBuildConfig: 'release' # arcade-specific parameters @@ -35,7 +35,7 @@ jobs: container: ${{ parameters.container }} strategy: ${{ parameters.strategy }} pool: ${{ parameters.pool }} - llvm: ${{ parameters.llvm }} + runtimeVariant: ${{ parameters.runtimeVariant }} # arcade-specific parameters condition: and(succeeded(), ${{ parameters.condition }}) @@ -47,18 +47,14 @@ jobs: gatherAssetManifests: ${{ parameters.gatherAssetManifests }} variables: - - name: coreClrProductArtifactName - value: 'CoreCLRProduct_$(osGroup)$(osSubgroup)_$(archType)_${{ parameters.liveRuntimeBuildConfig }}' + value: 'CoreCLRProduct_${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_$(archType)_${{ parameters.liveRuntimeBuildConfig }}' - name: coreClrProductRootFolderPath - value: '$(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).${{ parameters.liveRuntimeBuildConfig }}' + value: '$(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(liveRuntimeBuildConfigUpper)' - name: buildProductArtifactName - ${{ if ne(parameters.llvm, true) }}: - value: 'MonoProduct_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' - ${{ if eq(parameters.llvm, true) }}: - value: 'MonoProduct_LLVM_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' + value: 'MonoProduct_${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' - name: binTestsPath value: '$(Build.SourcesDirectory)/artifacts/tests/coreclr' @@ -87,8 +83,13 @@ jobs: - name: nativeTestArtifactRootFolderPath value: '$(binTestsPath)/obj/$(osGroup).$(archType).$(buildConfigUpper)' - - + - name: liveRuntimeBuildConfigUpper + ${{ if eq(parameters.liveRuntimeBuildConfig, 'release') }}: + value: 'Release' + ${{ if eq(parameters.liveRuntimeBuildConfig, 'checked') }}: + value: 'Checked' + ${{ if eq(parameters.liveRuntimeBuildConfig, 'debug') }}: + value: 'Debug' - librariesBuildArtifactName: '' - librariesOverrideArg: '' diff --git a/eng/pipelines/official/stages/publish.yml b/eng/pipelines/official/stages/publish.yml index 260931d01cb43..48171955c3709 100644 --- a/eng/pipelines/official/stages/publish.yml +++ b/eng/pipelines/official/stages/publish.yml @@ -18,8 +18,7 @@ stages: publishUsingPipelines: true dependsOn: PrepareSignedArtifacts pool: - name: NetCoreInternal-Pool - queue: buildpool.windows.10.amd64.vs2017 + vmImage: vs2017-win2016 # Stages-based publishing entry point - template: /eng/common/templates/post-build/post-build.yml diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index bc010a5ce1a18..45715a7bf1183 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -9,6 +9,7 @@ trigger: - '*' - docs/manpages/* exclude: + - .github/* - docs/* - CODE-OF-CONDUCT.md - CONTRIBUTING.md @@ -76,7 +77,8 @@ stages: - tvOS_x64 - tvOS_arm64 - iOS_x64 - # - iOS_arm # https://github.com/dotnet/runtime/issues/34465 + - iOS_x86 + - iOS_arm - iOS_arm64 - OSX_x64 - Linux_x64 @@ -92,6 +94,49 @@ stages: jobParameters: isOfficialBuild: ${{ variables.isOfficialBuild }} + # + # Build Mono LLVM release + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/mono/templates/build-job.yml + runtimeFlavor: mono + buildConfig: release + platforms: + - OSX_x64 + - Linux_x64 + # - Linux_arm + # - Linux_arm64 + # - Linux_musl_x64 + # - Linux_musl_arm64 + # - Windows_NT_x64 + # - Windows_NT_x86 + # - Windows_NT_arm + # - Windows_NT_arm64 + jobParameters: + runtimeVariant: LLVMJIT + isOfficialBuild: ${{ variables.isOfficialBuild }} + + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/mono/templates/build-job.yml + runtimeFlavor: mono + buildConfig: release + platforms: + - OSX_x64 + - Linux_x64 + # - Linux_arm + # - Linux_arm64 + # - Linux_musl_x64 + # - Linux_musl_arm64 + # - Windows_NT_x64 + # - Windows_NT_x86 + # - Windows_NT_arm + # - Windows_NT_arm64 + jobParameters: + runtimeVariant: LLVMAOT + isOfficialBuild: ${{ variables.isOfficialBuild }} + # # Build libraries using live CoreLib from CoreCLR # @@ -130,7 +175,8 @@ stages: - tvOS_x64 - tvOS_arm64 - iOS_x64 - # - iOS_arm # https://github.com/dotnet/runtime/issues/34465 + - iOS_x86 + - iOS_arm - iOS_arm64 - Browser_wasm jobParameters: @@ -192,15 +238,47 @@ stages: - Linux_x64 - tvOS_x64 - tvOS_arm64 - # - iOS_arm # https://github.com/dotnet/runtime/issues/34465 + - iOS_arm - iOS_arm64 - iOS_x64 + - iOS_x86 - Android_arm - Android_arm64 - Android_x64 - Android_x86 - Browser_wasm + # + # Installer Build for platforms using Mono + # + - template: /eng/pipelines/installer/installer-matrix.yml + parameters: + jobParameters: + liveRuntimeBuildConfig: release + liveLibrariesBuildConfig: Release + isOfficialBuild: ${{ variables.isOfficialBuild }} + useOfficialAllConfigurations: false + buildFullPlatformManifest: false + runtimeVariant: LLVMJIT + runtimeFlavor: mono + platforms: + - OSX_x64 + - Linux_x64 + + - template: /eng/pipelines/installer/installer-matrix.yml + parameters: + jobParameters: + liveRuntimeBuildConfig: release + liveLibrariesBuildConfig: Release + isOfficialBuild: ${{ variables.isOfficialBuild }} + useOfficialAllConfigurations: false + buildFullPlatformManifest: false + runtimeVariant: LLVMAOT + runtimeFlavor: mono + platforms: + - OSX_x64 + - Linux_x64 + - ${{ if eq(variables.isOfficialBuild, true) }}: - template: /eng/pipelines/official/stages/publish.yml parameters: diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 307cc24bbca69..0406560c6c22f 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -15,6 +15,7 @@ trigger: - docs/manpages/* exclude: - eng/Version.Details.xml + - .github/* - docs/* - CODE-OF-CONDUCT.md - CONTRIBUTING.md @@ -36,6 +37,7 @@ pr: - docs/manpages/* exclude: - eng/Version.Details.xml + - .github/* - docs/* - CODE-OF-CONDUCT.md - CONTRIBUTING.md @@ -76,6 +78,8 @@ jobs: - subset: mono include: - src/libraries/System.Private.CoreLib/* + - src/libraries/Native/Unix/System.Globalization.Native/* + - src/libraries/Native/Unix/Common/* exclude: - eng/Version.Details.xml - '*.md' @@ -105,8 +109,8 @@ jobs: - eng/pipelines/installer/* - subset: runtimetests include: - - /src/coreclr/tests/* - - /src/coreclr/build-test.sh + - src/coreclr/tests/* + - src/coreclr/build-test.sh - subset: installer include: - docs/manpages/* @@ -245,6 +249,7 @@ jobs: - tvOS_x64 - tvOS_arm64 - iOS_x64 + - iOS_x86 - iOS_arm - iOS_arm64 - OSX_x64 @@ -282,6 +287,7 @@ jobs: - tvOS_x64 - tvOS_arm64 - iOS_x64 + - iOS_x86 - iOS_arm - iOS_arm64 - Linux_x64 @@ -343,7 +349,31 @@ jobs: # - Windows_NT_arm # - Windows_NT_arm64 jobParameters: - llvm: true + runtimeVariant: LLVMJIT + condition: >- + or( + eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isFullMatrix'], true)) + +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/mono/templates/build-job.yml + runtimeFlavor: mono + buildConfig: debug + platforms: + - OSX_x64 + - Linux_x64 + # - Linux_arm + # - Linux_arm64 + # - Linux_musl_x64 + # - Linux_musl_arm64 + # - Windows_NT_x64 + # - Windows_NT_x86 + # - Windows_NT_arm + # - Windows_NT_arm64 + jobParameters: + runtimeVariant: LLVMAOT condition: >- or( eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true), @@ -371,7 +401,31 @@ jobs: # - Windows_NT_arm # - Windows_NT_arm64 jobParameters: - llvm: true + runtimeVariant: LLVMJIT + condition: >- + or( + eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true), + eq(variables['isFullMatrix'], true)) + +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/mono/templates/build-job.yml + runtimeFlavor: mono + buildConfig: release + platforms: + - OSX_x64 + - Linux_x64 + # - Linux_arm + # - Linux_arm64 + # - Linux_musl_x64 + # - Linux_musl_arm64 + # - Windows_NT_x64 + # - Windows_NT_x86 + # - Windows_NT_arm + # - Windows_NT_arm64 + jobParameters: + runtimeVariant: LLVMAOT condition: >- or( eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true), @@ -423,7 +477,7 @@ jobs: - Android_x64 - Android_arm - tvOS_arm64 - # - iOS_arm # https://github.com/dotnet/runtime/issues/34465 + - iOS_arm - iOS_x64 jobParameters: liveRuntimeBuildConfig: release @@ -438,6 +492,7 @@ jobs: - Android_arm64 - tvOS_x64 - iOS_arm64 + - iOS_x86 - Browser_wasm jobParameters: liveRuntimeBuildConfig: debug @@ -515,7 +570,7 @@ jobs: - template: /eng/pipelines/installer/installer-matrix.yml parameters: - buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + buildConfig: Release platforms: - OSX_x64 - Linux_x64 @@ -529,13 +584,13 @@ jobs: - template: /eng/pipelines/installer/installer-matrix.yml parameters: - buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + buildConfig: Release runtimeFlavor: mono platforms: - Android_x64 - Android_arm - tvOS_arm64 - # - iOS_arm # https://github.com/dotnet/runtime/issues/34465 + - iOS_arm - iOS_x64 jobParameters: liveRuntimeBuildConfig: release @@ -550,6 +605,7 @@ jobs: - Android_arm64 - tvOS_x64 - iOS_arm64 + - iOS_x86 - OSX_x64 - Linux_x64 - Browser_wasm @@ -557,6 +613,30 @@ jobs: liveRuntimeBuildConfig: release liveLibrariesBuildConfig: ${{ variables.debugOnPrReleaseOnRolling }} +- template: /eng/pipelines/installer/installer-matrix.yml + parameters: + buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + runtimeFlavor: mono + platforms: + - OSX_x64 + - Linux_x64 + jobParameters: + runtimeVariant: LLVMJIT + liveRuntimeBuildConfig: release + liveLibrariesBuildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + +- template: /eng/pipelines/installer/installer-matrix.yml + parameters: + buildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + runtimeFlavor: mono + platforms: + - OSX_x64 + - Linux_x64 + jobParameters: + runtimeVariant: LLVMAOT + liveRuntimeBuildConfig: release + liveLibrariesBuildConfig: ${{ variables.debugOnPrReleaseOnRolling }} + # # Libraries Test Build # Only when CoreCLR, Mono or Libraries is changed @@ -689,6 +769,7 @@ jobs: runtimeFlavor: mono platforms: - OSX_x64 + - Linux_arm64 helixQueueGroup: pr helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml jobParameters: @@ -701,29 +782,6 @@ jobs: eq(dependencies.checkout.outputs['SetPathVars_runtimetests.containsChange'], true), eq(variables['isFullMatrix'], true)) -# -# Mono CoreCLR runtime Test executions using live libraries -# Only when Mono is changed -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/templates/runtimes/run-test-job.yml - buildConfig: release - runtimeFlavor: mono - platforms: - - OSX_x64 - helixQueueGroup: pr - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - jobParameters: - testGroup: innerloop - liveLibrariesBuildConfig: ${{ variables.debugOnPrReleaseOnRolling }} - liveRuntimeBuildConfig: release - runtimeMode: 'interpreter' - runtimeModeDisplayName: 'Interpreter' - condition: >- - or( - eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true), - eq(variables['isFullMatrix'], true)) - # # Libraries Release Test Execution against a release mono runtime. # Only when libraries or mono changed diff --git a/eng/referenceFromRuntime.targets b/eng/referenceFromRuntime.targets index 00d7d54abb80b..34d0eb49199c8 100644 --- a/eng/referenceFromRuntime.targets +++ b/eng/referenceFromRuntime.targets @@ -111,7 +111,7 @@ - + diff --git a/eng/run-test.sh b/eng/run-test.sh index abd1d920b1615..5f14e6f6121be 100644 --- a/eng/run-test.sh +++ b/eng/run-test.sh @@ -15,12 +15,12 @@ wait_on_pids() usage() { - echo "Runs .NET CoreFX tests on FreeBSD, NetBSD or Linux" + echo "Runs .NET CoreFX tests on FreeBSD, Linux, NetBSD or SunOS" echo "usage: run-test [options]" echo echo "Input sources:" echo " --runtime Location of root of the binaries directory" - echo " containing the FreeBSD, NetBSD or Linux runtime" + echo " containing the FreeBSD, Linux, NetBSD or SunOS runtime" echo " default: /bin/testhost/netcoreapp---" echo " --corefx-tests Location of the root binaries location containing" echo " the tests to run" @@ -29,7 +29,7 @@ usage() echo "Flavor/OS/Architecture options:" echo " --configuration Configuration to run (Debug/Release)" echo " default: Debug" - echo " --os OS to run (FreeBSD, NetBSD or Linux)" + echo " --os OS to run (FreeBSD, Linux, NetBSD or SunOS)" echo " default: detect current OS" echo " --arch Architecture to run (x64, arm, armel, x86, arm64)" echo " default: detect current architecture" @@ -236,34 +236,34 @@ done # Compute paths to the binaries if they haven't already been computed -if [ "$Runtime" == "" ] +if [ -z "$Runtime" ] then Runtime="$ProjectRoot/artifacts/bin/testhost/netcoreapp-$OS-$Configuration-$__Arch" fi -if [ "$CoreFxTests" == "" ] +if [ -z "$CoreFxTests" ] then CoreFxTests="$ProjectRoot/artifacts/bin" fi # Check parameters up front for valid values: -if [ ! "$Configuration" == "Debug" ] && [ ! "$Configuration" == "Release" ] +if [ "$Configuration" != "Debug" ] && [ "$Configuration" != "Release" ] then echo "error: Configuration should be Debug or Release" exit 1 fi -if [ ! "$OS" == "FreeBSD" ] && [ ! "$OS" == "NetBSD" ] && [ ! "$OS" == "Linux" ] +if [ "$OS" != "FreeBSD" ] && [ "$OS" != "Linux" ] && [ "$OS" != "NetBSD" ] && [ "$OS" != "SunOS" ] then - echo "error: OS should be FreeBSD, NetBSD or Linux" + echo "error: OS should be FreeBSD, Linux, NetBSD or Linux" exit 1 fi export CORECLR_SERVER_GC="$serverGC" export PAL_OUTPUTDEBUGSTRING="1" -if [ "$LANG" == "" ] +if [ -z "$LANG" ] then export LANG="en_US.UTF-8" fi @@ -285,7 +285,10 @@ if [ $RunTestSequential -eq 1 ] then maxProcesses=1; else - if [ `uname` = "NetBSD" ] || [ `uname` = "FreeBSD" ]; then + platform="$(uname)" + if [ "$platform" = "FreeBSD" ]; then + maxProcesses=$(sysctl hw.ncpu | awk '{ print $2+1 }') + if [ "$platform" = "NetBSD" ] || [ "$platform" = "SunOS" ] ; then maxProcesses=$(($(getconf NPROCESSORS_ONLN)+1)) else maxProcesses=$(($(getconf _NPROCESSORS_ONLN)+1)) diff --git a/eng/sdl-tsa-vars.config b/eng/sdl-tsa-vars.config new file mode 100644 index 0000000000000..0b4659a0fe4f7 --- /dev/null +++ b/eng/sdl-tsa-vars.config @@ -0,0 +1,11 @@ +-SourceToolsList @("policheck","credscan") +-TsaInstanceURL https://devdiv.visualstudio.com/ +-TsaProjectName DEVDIV +-TsaNotificationEmail runtimerepo-infra@microsoft.com +-TsaCodebaseAdmin REDMOND\danmose +-TsaBugAreaPath "DevDiv\NET Runtime\Reliability\Docs" +-TsaIterationPath DevDiv +-TsaRepositoryName Runtime +-TsaCodebaseName Runtime +-TsaOnboard $True +-TsaPublish $True \ No newline at end of file diff --git a/src/libraries/targetframeworksuffix.props b/eng/targetframeworksuffix.props similarity index 91% rename from src/libraries/targetframeworksuffix.props rename to eng/targetframeworksuffix.props index 2f427328fd5fd..f89923d3ab86c 100644 --- a/src/libraries/targetframeworksuffix.props +++ b/eng/targetframeworksuffix.props @@ -62,6 +62,13 @@ netbsd + + + true + true + sunos + + true diff --git a/eng/testing/AndroidRunnerTemplate.sh b/eng/testing/AndroidRunnerTemplate.sh index dfb90ecaa156b..1a683aa348986 100644 --- a/eng/testing/AndroidRunnerTemplate.sh +++ b/eng/testing/AndroidRunnerTemplate.sh @@ -4,7 +4,7 @@ EXECUTION_DIR=$(dirname $0) TEST_NAME=$1 TARGET_ARCH=$2 -APK=$EXECUTION_DIR/Bundle/bin/$TEST_NAME.apk +APK=$EXECUTION_DIR/bin/$TEST_NAME.apk # it doesn't support parallel execution yet, so, here is a hand-made semaphore: LOCKDIR=/tmp/androidtests.lock @@ -20,4 +20,4 @@ done dotnet xharness android test -i="net.dot.MonoRunner" \ --package-name="net.dot.$TEST_NAME" \ - --app=$APK -o=$EXECUTION_DIR/Bundle/TestResults -v + --app=$APK -o=$EXECUTION_DIR/TestResults -v diff --git a/eng/testing/AppleRunnerTemplate.sh b/eng/testing/AppleRunnerTemplate.sh index 11b5675fab77f..c146f7e0364b1 100644 --- a/eng/testing/AppleRunnerTemplate.sh +++ b/eng/testing/AppleRunnerTemplate.sh @@ -25,7 +25,7 @@ fi # "Release" in SCHEME_SDK is what xcode produces (see "bool Optimized" property in AppleAppBuilderTask) -APP_BUNDLE=$EXECUTION_DIR/Bundle/$TEST_NAME/$SCHEME_SDK/$TEST_NAME.app +APP_BUNDLE=$EXECUTION_DIR/$TEST_NAME/$SCHEME_SDK/$TEST_NAME.app # it doesn't support parallel execution yet, so, here is a hand-made semaphore: LOCKDIR=/tmp/runonsim.lock @@ -39,10 +39,14 @@ while true; do fi done -XHARNESS_OUT="$EXECUTION_DIR/Bundle/xharness-output" +XHARNESS_OUT="$EXECUTION_DIR/xharness-output" dotnet xharness ios test --app="$APP_BUNDLE" \ --targets=$TARGET \ --output-directory=$XHARNESS_OUT +_exitCode=$? + echo "Xharness artifacts: $XHARNESS_OUT" + +exit $_exitCode diff --git a/eng/testing/WasmRunnerTemplate.sh b/eng/testing/WasmRunnerTemplate.sh new file mode 100644 index 0000000000000..2d4b8f95d4f49 --- /dev/null +++ b/eng/testing/WasmRunnerTemplate.sh @@ -0,0 +1,12 @@ +set -ev + +EXECUTION_DIR=$(dirname $0) +TEST_NAME=$1 +TARGET_ARCH=$2 + +echo "Test: $1 Arch: $2" + +cd $EXECUTION_DIR +v8 --expose_wasm runtime.js -- --enable-gc --run WasmTestRunner.dll $TEST_NAME + +exit 0 diff --git a/eng/testing/coverage.targets b/eng/testing/coverage.targets index fd53a86bda515..6f8ac2648f06e 100644 --- a/eng/testing/coverage.targets +++ b/eng/testing/coverage.targets @@ -4,7 +4,7 @@ We need to filter the data to only the assembly being tested. Otherwise we will gather tons of data about other assemblies. If the code being tested is part of the runtime itself, it requires special treatment. --> - + <_ProjectDirectoryUnderSourceDir>$(MSBuildProjectDirectory.SubString($(LibrariesProjectRoot.Length))) $(_ProjectDirectoryUnderSourceDir.SubString(0, $(_ProjectDirectoryUnderSourceDir.IndexOfAny("\\/")))) @@ -74,4 +74,16 @@ + + + + + + diff --git a/eng/testing/runsettings.targets b/eng/testing/runsettings.targets index ffd1939b54255..10496127b8a90 100644 --- a/eng/testing/runsettings.targets +++ b/eng/testing/runsettings.targets @@ -1,9 +1,18 @@ - $(MSBuildThisFileDirectory).runsettings - $(OutDir).runsettings + $(MSBuildThisFileDirectory).runsettings + $(ArtifactsObjDir)$(TargetOS)-$(Configuration)-$(TargetArchitecture).runsettings + $(OutDir).runsettings + + false + $(RunSettingsIntermediateOutputFilePath) + $(RunSettingsAppOutputFilePath) + - $(RunSettingsOutputFilePath) + $(RunSettingsAppOutputFilePath) + + $(RunSettingsIntermediateOutputFilePath) + GenerateRunSettingsFile;$(PrepareForRunDependsOn) @@ -41,15 +50,4 @@ $(RunSettingsOutputFilePath) - - - - - diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets new file mode 100644 index 0000000000000..3fd1594b73bd5 --- /dev/null +++ b/eng/testing/tests.mobile.targets @@ -0,0 +1,154 @@ + + + + $([MSBuild]::NormalizeDirectory('$(OutDir)', 'AppBundle')) + $([MSBuild]::NormalizePath('$(BundleDir)', '$(RunScriptOutputName)')) + true + + + + + + + + arm64-v8a + armeabi-v7a + x86_64 + x86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @(MonoAOTCompilerDefaultAotArguments, ';') + @(MonoAOTCompilerDefaultProcessArguments, ';') + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_runnerFilesToPublish Include="$(AndroidTestRunnerDir)*" Condition="'$(TargetOS)' == 'Android'" /> + <_runnerFilesToPublish Include="$(AppleTestRunnerDir)*" Condition="'$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS'" /> + <_runnerFilesToPublish Include="$(WasmTestRunnerDir)*" Condition="'$(TargetOS)' == 'Browser'" /> + + + + + + + + + + + + + + + + + + + diff --git a/eng/testing/tests.props b/eng/testing/tests.props index cfdcc2b017144..cccce13b1c454 100644 --- a/eng/testing/tests.props +++ b/eng/testing/tests.props @@ -20,10 +20,18 @@ <_withoutCategories Condition="!$(_withCategories.Contains('failing'))">$(_withoutCategories);failing - - - - + + + $(NetCoreAppCurrent)-$(Configuration) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleTestRunner', '$(MobileRunnersDirSuffix)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidTestRunner', '$(MobileRunnersDirSuffix)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmTestRunner', '$(MobileRunnersDirSuffix)')) + + $(PackageRID) + true + false + + + + + + - - - - - $(ArtifactsDir)bin\lib-runtime-packs\runtimes\android-$(TargetArchitecture) - $(OutDir)\Bundle - $(RepoRoot)\src\mono\msbuild\AndroidTestRunner\bin - arm64-v8a - armeabi - x86_64 - $(TargetArchitecture) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(ArtifactsDir)bin\lib-runtime-packs\runtimes\ios-$(TargetArchitecture) - $(OutDir)\Bundle - $(RepoRoot)\src\mono\msbuild\AppleTestRunner\bin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/eng/testing/xunit/xunit.console.props b/eng/testing/xunit/xunit.console.props deleted file mode 100644 index c5b5fc38f17fb..0000000000000 --- a/eng/testing/xunit/xunit.console.props +++ /dev/null @@ -1,15 +0,0 @@ - - - true - testResults.xml - - - - - - - diff --git a/eng/testing/xunit/xunit.console.targets b/eng/testing/xunit/xunit.console.targets index 0f41550251d47..2824bd8410780 100644 --- a/eng/testing/xunit/xunit.console.targets +++ b/eng/testing/xunit/xunit.console.targets @@ -1,8 +1,13 @@ + + true + testResults.xml + + <_depsFileArgument Condition="'$(GenerateDependencyFile)' == 'true'">--depsfile $(AssemblyName).deps.json - "$(RunScriptHost)" exec --runtimeconfig $(AssemblyName).runtimeconfig.json $(_depsFileArgument) xunit.console.dll - xunit.console.exe + "$(RunScriptHost)" exec --runtimeconfig $(AssemblyName).runtimeconfig.json $(_depsFileArgument) xunit.console.dll + xunit.console.exe $(RunScriptCommand) $(TargetFileName) $(RunScriptCommand) -xml $(TestResultsName) @@ -14,7 +19,7 @@ $(RunScriptCommand) -method $(XUnitMethodName) $(RunScriptCommand) -class $(XUnitClassName) $(RunScriptCommand) -verbose - $(RunScriptCommand) -noappdomain + $(RunScriptCommand) -noappdomain $(RunScriptCommand)$(_withCategories.Replace(';', ' -trait category=')) @@ -24,6 +29,15 @@ $(RunScriptCommand) $(XUnitOptions) + + + + + - - diff --git a/global.json b/global.json index 572ecf2b8740e..1f55cf7ca46f2 100644 --- a/global.json +++ b/global.json @@ -1,21 +1,21 @@ { "sdk": { - "version": "5.0.100-preview.5.20228.8", + "version": "5.0.100-preview.5.20251.2", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "5.0.100-preview.5.20228.8" + "dotnet": "5.0.100-preview.5.20251.2" }, "native-tools": { "cmake": "3.14.2", "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "5.0.0-beta.20255.6", - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20255.6", - "Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk": "5.0.0-beta.20255.6", - "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20255.6", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "5.0.0-beta.20261.9", + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20261.9", + "Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk": "5.0.0-beta.20261.9", + "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20261.9", "FIX-85B6-MERGE-9C38-CONFLICT": "1.0.0", "Microsoft.NET.Sdk.IL": "5.0.0-preview.4.20202.18", "Microsoft.Build.NoTargets": "1.0.53", diff --git a/src/coreclr/build-test.cmd b/src/coreclr/build-test.cmd index 82389e45ad3ec..ceeca835dc7b6 100644 --- a/src/coreclr/build-test.cmd +++ b/src/coreclr/build-test.cmd @@ -663,15 +663,17 @@ for %%F in ("%CORE_ROOT%\System.*.dll";"%CORE_ROOT%\Microsoft.*.dll";%CORE_ROOT% ))))) ) -echo Composite response line^: %__CompositeResponseFile% -type "%__CompositeResponseFile%" +if defined __CompositeBuildMode ( + echo Composite response line^: %__CompositeResponseFile% + type "%__CompositeResponseFile%" +) if defined __CompositeBuildMode ( - set __CompositeCommandLine="%CORE_ROOT%\corerun" + set __CompositeCommandLine="%__RepoRootDir%\dotnet.cmd" set __CompositeCommandLine=!__CompositeCommandLine! "%CORE_ROOT%\crossgen2\crossgen2.dll" set __CompositeCommandLine=!__CompositeCommandLine! "@%__CompositeResponseFile%" echo Building composite R2R framework^: !__CompositeCommandLine! - !__CompositeCommandLine! + call !__CompositeCommandLine! set __FailedToPrecompile=!ERRORLEVEL! copy /Y "!__CompositeOutputDir!\*.*" "!CORE_ROOT!\" ) @@ -695,7 +697,7 @@ if /i "%__BuildArch%" == "arm64" ( set __CrossgenExe="%__BinDir%\x64\crossgen.ex set __CrossgenExe=%__CrossgenExe% if defined __DoCrossgen2 ( - set __CrossgenExe="%CORE_ROOT%\corerun" "%__BinDir%\crossgen2\crossgen2.dll" + set __CrossgenExe="%__RepoRootDir%\dotnet.cmd" "%CORE_ROOT%\crossgen2\crossgen2.dll" ) REM Intentionally avoid using the .dll extension to prevent @@ -705,12 +707,14 @@ set __CrossgenCmd= if defined __DoCrossgen ( set __CrossgenCmd=!__CrossgenExe! /Platform_Assemblies_Paths "!CORE_ROOT!" /in !AssemblyPath! /out !__CrossgenOutputFile! + echo !__CrossgenCmd! + !__CrossgenCmd! ) else ( set __CrossgenCmd=!__CrossgenExe! -r:"!CORE_ROOT!\System.*.dll" -r:"!CORE_ROOT!\Microsoft.*.dll" -r:"!CORE_ROOT!\mscorlib.dll" -r:"!CORE_ROOT!\netstandard.dll" -O --inputbubble --out:!__CrossgenOutputFile! !AssemblyPath! + echo !__CrossgenCmd! + call !__CrossgenCmd! ) -echo %__CrossgenCmd% -%__CrossgenCmd% set /a __exitCode = !errorlevel! set /a "%~3+=1" diff --git a/src/coreclr/build-test.sh b/src/coreclr/build-test.sh index 81f6933703c3a..9ad2fde622415 100755 --- a/src/coreclr/build-test.sh +++ b/src/coreclr/build-test.sh @@ -180,8 +180,8 @@ precompile_coreroot_fx() local totalPrecompiled=0 local failedToPrecompile=0 - local compositeCommandLine="$overlayDir/corerun" - compositeCommandLine+=" ${__BinDir}/crossgen2/crossgen2.dll" + local compositeCommandLine="${__DotNetCli}" + compositeCommandLine+=" $__BinDir/crossgen2/crossgen2.dll" compositeCommandLine+=" --composite" compositeCommandLine+=" -O" compositeCommandLine+=" --out:$outputDir/framework-r2r.dll" @@ -206,7 +206,7 @@ precompile_coreroot_fx() fi if [[ "$__DoCrossgen2" != 0 ]]; then - commandLine="$overlayDir/corerun $overlayDir/crossgen2/crossgen2.dll $crossgen2References -O --inputbubble --out $outputDir/$(basename $filename) $filename" + commandLine="${__DotNetCli} $overlayDir/crossgen2/crossgen2.dll $crossgen2References -O --inputbubble --out $outputDir/$(basename $filename) $filename" fi echo Precompiling "$filename" diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index ce2bc382a9937..469e009027109 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -105,7 +105,6 @@ endif(CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_BASICFREEZE) add_definitions(-DFEATURE_CORECLR) add_definitions(-DFEATURE_CORESYSTEM) -add_definitions(-DFEATURE_CORRUPTING_EXCEPTIONS) if(FEATURE_DBGIPC) add_definitions(-DFEATURE_DBGIPC_TRANSPORT_DI) add_definitions(-DFEATURE_DBGIPC_TRANSPORT_VM) @@ -196,6 +195,7 @@ add_compile_definitions($<$>>:F if (CLR_CMAKE_TARGET_ARCH_AMD64) add_compile_definitions($<$>>:FEATURE_ON_STACK_REPLACEMENT>) endif (CLR_CMAKE_TARGET_ARCH_AMD64) +add_compile_definitions($<$>>:FEATURE_PGO>) if (CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_TYPEEQUIVALENCE) endif(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/dir.common.props b/src/coreclr/dir.common.props index e4d212b2aee16..2ff54f14de24a 100644 --- a/src/coreclr/dir.common.props +++ b/src/coreclr/dir.common.props @@ -55,10 +55,11 @@ true true true + true true true - true + true $(__DistroRid) diff --git a/src/coreclr/run-cppcheck.sh b/src/coreclr/run-cppcheck.sh index c505fd184dedc..46e51e1e7471f 100755 --- a/src/coreclr/run-cppcheck.sh +++ b/src/coreclr/run-cppcheck.sh @@ -17,13 +17,13 @@ usage() check_dependencies() { # Check presence of cppcheck on the path - if [ "$RunCppCheck" == true ] + if [ "$RunCppCheck" = "true" ] then hash cppcheck 2>/dev/null || { echo >&2 "Please install cppcheck before running this script"; exit 1; } fi - + # Check presence of sloccount on the path - if [ "$RunSlocCount" == true ] + if [ "$RunSlocCount" = "true" ] then hash sloccount 2>/dev/null || { echo >&2 "Please install sloccount before running this script"; exit 1; } fi @@ -39,9 +39,10 @@ SloccountOutput="sloccount.sc" # Get the number of processors available to the scheduler # Other techniques such as `nproc` only get the number of # processors available to a single process. -if [ `uname` = "FreeBSD" ]; then -NumProc=`sysctl hw.ncpu | awk '{ print $2+1 }'` -elif [ `uname` = "NetBSD" ]; then +platform="$(uname)" +if [ "$platform" = "FreeBSD" ]; then +NumProc=$(sysctl hw.ncpu | awk '{ print $2+1 }') +elif [ "$platform" = "NetBSD" || "$platform" = "SunOS" ]; then NumProc=$(($(getconf NPROCESSORS_ONLN)+1)) else NumProc=$(($(getconf _NPROCESSORS_ONLN)+1)) @@ -80,19 +81,19 @@ do esac done -if [ "$FilesFromArgs" != "" ]; +if [ -n "$FilesFromArgs" ]; then Files=$FilesFromArgs fi -if [ "$CppCheckOutput" == "" ]; +if [ -z "$CppCheckOutput" ]; then echo "Expected: file for cppcheck output" usage exit 1 fi -if [ "$SloccountOutput" == "" ]; +if [ -z "$SloccountOutput" ]; then echo "Expected: file for sloccount output" usage @@ -101,14 +102,14 @@ fi check_dependencies -if [ "$RunCppCheck" == true ] +if [ "$RunCppCheck" = "true" ] then echo "Running cppcheck for files: $Files" cppcheck --enable=all -j $NumProc --xml --xml-version=2 --force $Files 2> $CppCheckOutput CppCheckOutputs="$CppCheckOutput (cppcheck)" fi -if [ "$RunSlocCount" == true ] +if [ "$RunSlocCount" = "true" ] then echo "Running sloccount for files: $Files" sloccount --wide --details $Files > $SloccountOutput diff --git a/src/coreclr/src/.nuget/Directory.Build.props b/src/coreclr/src/.nuget/Directory.Build.props index e321b384626e0..2fd932c03b84e 100644 --- a/src/coreclr/src/.nuget/Directory.Build.props +++ b/src/coreclr/src/.nuget/Directory.Build.props @@ -28,7 +28,7 @@ $(OSRid) - Windows_NT;OSX;Android;Linux;FreeBSD + Windows_NT;OSX;Android;Linux;FreeBSD;NetBSD;SunOS ;$(SupportedPackageOSGroups); + netbsd-$(TargetArchitecture) + + + + + sunos-$(TargetArchitecture) + + sunos-$(TargetArchitecture) + + android.21-$(TargetArchitecture) @@ -159,6 +173,12 @@ + + + + + + x86 diff --git a/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.Common.targets b/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.Common.targets index 0b60d9b5f46bf..452353b37096b 100644 --- a/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.Common.targets +++ b/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.Common.targets @@ -9,7 +9,7 @@ Copyright (c) .NET Foundation. All rights reserved. - + diff --git a/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.targets b/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.targets index 299511fa2a8be..f2c0a3fb64973 100644 --- a/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.targets +++ b/src/coreclr/src/.nuget/Microsoft.NET.Sdk.IL/targets/Microsoft.NET.Sdk.IL.targets @@ -7,7 +7,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and created a backup copy. Incorrect changes to this file will make it impossible to load or build your projects from the command-line or the IDE. -Copyright (c) .NET Foundation. All rights reserved. +Copyright (c) .NET Foundation. All rights reserved. *********************************************************************************************** --> @@ -24,13 +24,15 @@ Copyright (c) .NET Foundation. All rights reserved. <_OSPlatform Condition="$([MSBuild]::IsOSPlatform('linux'))">linux <_OSPlatform Condition="$([MSBuild]::IsOSPlatform('osx'))">osx <_OSPlatform Condition="$([MSBuild]::IsOSPlatform('freebsd'))">freebsd + <_OSPlatform Condition="$([MSBuild]::IsOSPlatform('netbsd'))">netbsd + <_OSPlatform Condition="$([MSBuild]::IsOSPlatform('sunos'))">sunos <_OSArchitecture>$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture) $(_OSPlatform)-$(_OSArchitecture.ToLower()) 5.0.0 runtime.$(MicrosoftNetCoreIlasmPackageRuntimeId).microsoft.netcore.ilasm runtime.$(MicrosoftNetCoreIlasmPackageRuntimeId).microsoft.netcore.ildasm - + <_IlasmDir Condition="'$(ILAsmToolPath)' != ''">$([MSBuild]::NormalizeDirectory($(ILAsmToolPath))) @@ -68,8 +70,8 @@ Copyright (c) .NET Foundation. All rights reserved. - @@ -122,7 +124,7 @@ Copyright (c) .NET Foundation. All rights reserved. <_KeyFileArgument Condition="'$(KeyOriginatorFile)' != ''">-KEY="$(KeyOriginatorFile)" - <_IlasmSwitches>-QUIET -NOLOGO + <_IlasmSwitches>-QUIET -NOLOGO <_IlasmSwitches Condition="'$(FoldIdenticalMethods)' == 'True'">$(_IlasmSwitches) -FOLD <_IlasmSwitches Condition="'$(SizeOfStackReserve)' != ''">$(_IlasmSwitches) -STACK=$(SizeOfStackReserve) <_IlasmSwitches Condition="'$(DebugType)' == 'Full'">$(_IlasmSwitches) -DEBUG diff --git a/src/coreclr/src/.nuget/optdata/optdata.csproj b/src/coreclr/src/.nuget/optdata/optdata.csproj index d19c3125fe5d3..14ec28443321b 100644 --- a/src/coreclr/src/.nuget/optdata/optdata.csproj +++ b/src/coreclr/src/.nuget/optdata/optdata.csproj @@ -6,6 +6,7 @@ True True win7-x64;win7-x86;linux-x64 + true <_TargetOSArchLowercase>$(TargetOS.ToLower())-$(TargetArchitecture.ToLower()) diff --git a/src/coreclr/src/System.Private.CoreLib/PinvokeAnalyzerExceptionList.analyzerdata b/src/coreclr/src/System.Private.CoreLib/PinvokeAnalyzerExceptionList.analyzerdata index f2570c7c958ee..e1c58c0c50381 100644 --- a/src/coreclr/src/System.Private.CoreLib/PinvokeAnalyzerExceptionList.analyzerdata +++ b/src/coreclr/src/System.Private.CoreLib/PinvokeAnalyzerExceptionList.analyzerdata @@ -7,41 +7,4 @@ user32.dll!GetProcessWindowStation user32.dll!GetUserObjectInformationW -kernel32.dll!GetGeoInfo - - -libSystem.Globalization.Native!GlobalizationNative_ChangeCase -libSystem.Globalization.Native!GlobalizationNative_ChangeCaseInvariant -libSystem.Globalization.Native!GlobalizationNative_ChangeCaseTurkish -libSystem.Globalization.Native!GlobalizationNative_CloseSortHandle -libSystem.Globalization.Native!GlobalizationNative_CompareString -libSystem.Globalization.Native!GlobalizationNative_CompareStringOrdinalIgnoreCase -libSystem.Globalization.Native!GlobalizationNative_EndsWith -libSystem.Globalization.Native!GlobalizationNative_EnumCalendarInfo -libSystem.Globalization.Native!GlobalizationNative_GetCalendarInfo -libSystem.Globalization.Native!GlobalizationNative_GetCalendars -libSystem.Globalization.Native!GlobalizationNative_GetDefaultLocaleName -libSystem.Globalization.Native!GlobalizationNative_GetICUVersion -libSystem.Globalization.Native!GlobalizationNative_GetJapaneseEraStartDate -libSystem.Globalization.Native!GlobalizationNative_GetLatestJapaneseEra -libSystem.Globalization.Native!GlobalizationNative_GetLocaleInfoGroupingSizes -libSystem.Globalization.Native!GlobalizationNative_GetLocaleInfoInt -libSystem.Globalization.Native!GlobalizationNative_GetLocaleInfoString -libSystem.Globalization.Native!GlobalizationNative_GetLocaleName -libSystem.Globalization.Native!GlobalizationNative_GetLocales -libSystem.Globalization.Native!GlobalizationNative_GetLocaleTimeFormat -libSystem.Globalization.Native!GlobalizationNative_GetSortHandle -libSystem.Globalization.Native!GlobalizationNative_GetSortKey -libSystem.Globalization.Native!GlobalizationNative_GetSortVersion -libSystem.Globalization.Native!GlobalizationNative_GetTimeZoneDisplayName -libSystem.Globalization.Native!GlobalizationNative_IndexOf -libSystem.Globalization.Native!GlobalizationNative_IndexOfOrdinalIgnoreCase -libSystem.Globalization.Native!GlobalizationNative_InitICUFunctions -libSystem.Globalization.Native!GlobalizationNative_IsNormalized -libSystem.Globalization.Native!GlobalizationNative_IsPredefinedLocale -libSystem.Globalization.Native!GlobalizationNative_LastIndexOf -libSystem.Globalization.Native!GlobalizationNative_LoadICU -libSystem.Globalization.Native!GlobalizationNative_NormalizeString -libSystem.Globalization.Native!GlobalizationNative_StartsWith -libSystem.Globalization.Native!GlobalizationNative_ToAscii -libSystem.Globalization.Native!GlobalizationNative_ToUnicode +kernel32.dll!GetGeoInfo \ No newline at end of file diff --git a/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj b/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj index a3fde0fd8eab2..73e115381ce75 100644 --- a/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj +++ b/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj @@ -43,7 +43,6 @@ - diff --git a/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs b/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs index eba104a0145c3..17db43fcd1c37 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs @@ -131,7 +131,7 @@ public static object GetClassFactoryForType(ComActivationContext cxt) if (!Path.IsPathRooted(cxt.AssemblyPath)) { - throw new ArgumentException(); + throw new ArgumentException(null, nameof(cxt)); } Type classType = FindClassType(cxt.ClassId, cxt.AssemblyPath, cxt.AssemblyName, cxt.TypeName); @@ -167,7 +167,7 @@ public static void ClassRegistrationScenarioForType(ComActivationContext cxt, bo if (!Path.IsPathRooted(cxt.AssemblyPath)) { - throw new ArgumentException(); + throw new ArgumentException(null, nameof(cxt)); } Type classType = FindClassType(cxt.ClassId, cxt.AssemblyPath, cxt.AssemblyName, cxt.TypeName); @@ -307,7 +307,7 @@ public static unsafe int RegisterClassForTypeInternal(ComActivationContextIntern if (cxtInt.InterfaceId != Guid.Empty || cxtInt.ClassFactoryDest != IntPtr.Zero) { - throw new ArgumentException(); + throw new ArgumentException(null, nameof(pCxtInt)); } try @@ -351,7 +351,7 @@ public static unsafe int UnregisterClassForTypeInternal(ComActivationContextInte if (cxtInt.InterfaceId != Guid.Empty || cxtInt.ClassFactoryDest != IntPtr.Zero) { - throw new ArgumentException(); + throw new ArgumentException(null, nameof(pCxtInt)); } try diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/ArgIterator.cs b/src/coreclr/src/System.Private.CoreLib/src/System/ArgIterator.cs index d32d53ae753b6..8c7039e557b45 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/ArgIterator.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/ArgIterator.cs @@ -85,7 +85,9 @@ public TypedReference GetNextArg(RuntimeTypeHandle rth) // malicious caller to increment the pointer to an arbitrary // location in memory and read the contents. if (ArgPtr == IntPtr.Zero) +#pragma warning disable CA2208 // Instantiate argument exceptions correctly, the argument not applicable throw new ArgumentNullException(); +#pragma warning restore CA2208 TypedReference result = default; // reference to TypedReference is banned, so have to pass result as pointer diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs index 55ed9f70b082b..75f6aa40ce4d1 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs @@ -9,13 +9,6 @@ using System.Reflection; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { // Note that we make a T[] (single-dimensional w/ zero as the lower bound) implement both diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs index 8c7bc784ad896..5e1d8249e3ddd 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs @@ -7,15 +7,6 @@ using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -using nint = System.UInt64; -#else -using nuint = System.UInt32; -using nint = System.UInt32; -#endif - namespace System { public partial class Buffer diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.CoreCLR.cs index bd1ad774bea18..7d3ab6c6af68d 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.CoreCLR.cs @@ -33,7 +33,7 @@ internal static partial class EventPipeInternal internal static extern IntPtr CreateProvider(string providerName, Interop.Advapi32.EtwEnableCallback callbackFunc); [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] - internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, long keywords, uint eventVersion, uint level, void* pMetadata, uint metadataLength); + internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, long keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength); [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern IntPtr GetProvider(string providerName); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs index 20a0c57492d8a..41b1dd72e0102 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs @@ -131,7 +131,7 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception? exc object? target = Activator.CreateInstance(symbolsType); // Create an instance delegate for the GetSourceLineInfo method - GetSourceLineInfoDelegate getSourceLineInfo = (GetSourceLineInfoDelegate)symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target); + GetSourceLineInfoDelegate getSourceLineInfo = symbolsMethodInfo.CreateDelegate(target); // We could race with another thread. It doesn't matter if we win or lose, the losing instance will be GC'ed and all threads including this one will // use the winning instance diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/GC.cs b/src/coreclr/src/System.Private.CoreLib/src/System/GC.cs index fc8a9650f63b7..a44047cc4d8e9 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/GC.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/GC.cs @@ -135,7 +135,7 @@ public static void AddMemoryPressure(long bytesAllocated) if ((4 == IntPtr.Size) && (bytesAllocated > int.MaxValue)) { - throw new ArgumentOutOfRangeException("pressure", + throw new ArgumentOutOfRangeException(nameof(bytesAllocated), SR.ArgumentOutOfRange_MustBeNonNegInt32); } @@ -353,7 +353,7 @@ public static long GetTotalMemory(bool forceFullCollection) } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] - private static extern IntPtr _RegisterFrozenSegment(IntPtr sectionAddress, IntPtr sectionSize); + private static extern IntPtr _RegisterFrozenSegment(IntPtr sectionAddress, nint sectionSize); [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void _UnregisterFrozenSegment(IntPtr segmentHandle); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index dd460b178945f..2c173244bb83d 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -59,12 +59,6 @@ private static void LoadAppLocalIcu(string icuSuffixAndVersion, bool suffixWithS if (indexOfSeparator >= 0) { icuSuffix = icuSuffixAndVersion.AsSpan().Slice(0, indexOfSeparator); - - if (icuSuffix.Length > 35) - { - Environment.FailFast($"The resolved \"{icuSuffix.ToString()}\" suffix from System.Globalization.AppLocalIcu switch has to be < 20 chars long."); - } - version = icuSuffixAndVersion.AsSpan().Slice(icuSuffix.Length + 1); } else @@ -72,11 +66,6 @@ private static void LoadAppLocalIcu(string icuSuffixAndVersion, bool suffixWithS version = icuSuffixAndVersion; } - if (version.Length > 33) - { - Environment.FailFast($"The resolved version \"{version.ToString()}\" from System.Globalization.AppLocalIcu switch has to be < 33 chars long."); - } - if (suffixWithSeparator) { icuSuffix = string.Concat(icuSuffix, "."); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Object.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Object.CoreCLR.cs index 3c7cb5c23982a..a65358449ee8c 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Object.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Object.CoreCLR.cs @@ -4,13 +4,6 @@ using System.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { public partial class Object diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 3b190943be0d4..1407f8705246e 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.SymbolStore; using System.Globalization; using System.IO; @@ -125,7 +126,7 @@ public sealed class AssemblyBuilder : Assembly // This is only valid in the "external" AssemblyBuilder internal AssemblyBuilderData _assemblyData; private readonly InternalAssemblyBuilder _internalAssemblyBuilder; - private ModuleBuilder _manifestModuleBuilder = null!; + private ModuleBuilder _manifestModuleBuilder; // Set to true if the manifest module was returned by code:DefineDynamicModule to the user private bool _isManifestModuleUsedAsDefinedModule; @@ -208,6 +209,7 @@ internal ModuleBuilder GetModuleBuilder(InternalModuleBuilder module) } } + [MemberNotNull(nameof(_manifestModuleBuilder))] private void InitManifestModule() { InternalModuleBuilder modBuilder = (InternalModuleBuilder)GetInMemoryAssemblyModule(GetNativeHandle()); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs index 80cb55b796c50..fb6b4c623eab9 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs @@ -19,7 +19,7 @@ public sealed class ConstructorBuilder : ConstructorInfo m_methodBuilder = new MethodBuilder(name, attributes, callingConvention, null, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers, mod, type); - type.m_listMethods.Add(m_methodBuilder); + type.m_listMethods!.Add(m_methodBuilder); m_methodBuilder.GetMethodSignature().InternalGetSignature(out _); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs index 506c98b28e5e2..d1e89aaf0c3bf 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs @@ -14,91 +14,42 @@ ===========================================================*/ using System.Buffers.Binary; +using System.Diagnostics; using System.IO; using System.Text; -using System.Diagnostics; namespace System.Reflection.Emit { public class CustomAttributeBuilder { + internal ConstructorInfo m_con; + private object?[] m_constructorArgs; + private byte[] m_blob; + // public constructor to form the custom attribute with constructor and constructor // parameters. - public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs) + public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs) : + this(con, constructorArgs, Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty()) { - InitCustomAttributeBuilder(con, constructorArgs, - Array.Empty(), Array.Empty(), - Array.Empty(), Array.Empty()); } // public constructor to form the custom attribute with constructor, constructor // parameters and named properties. - public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, - PropertyInfo[] namedProperties, object?[] propertyValues) + public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, PropertyInfo[] namedProperties, object?[] propertyValues) : + this(con, constructorArgs, namedProperties, propertyValues, Array.Empty(), Array.Empty()) { - InitCustomAttributeBuilder(con, constructorArgs, namedProperties, - propertyValues, Array.Empty(), Array.Empty()); } // public constructor to form the custom attribute with constructor and constructor // parameters. - public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, - FieldInfo[] namedFields, object?[] fieldValues) + public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, FieldInfo[] namedFields, object?[] fieldValues) : + this(con, constructorArgs, Array.Empty(), Array.Empty(), namedFields, fieldValues) { - InitCustomAttributeBuilder(con, constructorArgs, Array.Empty(), - Array.Empty(), namedFields, fieldValues); } // public constructor to form the custom attribute with constructor and constructor // parameters. - public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, - PropertyInfo[] namedProperties, object?[] propertyValues, - FieldInfo[] namedFields, object?[] fieldValues) - { - InitCustomAttributeBuilder(con, constructorArgs, namedProperties, - propertyValues, namedFields, fieldValues); - } - - // Check that a type is suitable for use in a custom attribute. - private bool ValidateType(Type t) - { - if (t.IsPrimitive) - { - return t != typeof(IntPtr) && t != typeof(UIntPtr); - } - if (t == typeof(string) || t == typeof(Type)) - { - return true; - } - if (t.IsEnum) - { - switch (Type.GetTypeCode(Enum.GetUnderlyingType(t))) - { - case TypeCode.SByte: - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - return true; - default: - return false; - } - } - if (t.IsArray) - { - if (t.GetArrayRank() != 1) - return false; - return ValidateType(t.GetElementType()!); - } - return t == typeof(object); - } - - internal void InitCustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, - PropertyInfo[] namedProperties, object?[] propertyValues, - FieldInfo[] namedFields, object?[] fieldValues) + public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, PropertyInfo[] namedProperties, object?[] propertyValues, FieldInfo[] namedFields, object?[] fieldValues) { if (con == null) throw new ArgumentNullException(nameof(con)); @@ -289,6 +240,43 @@ private bool ValidateType(Type t) m_blob = ((MemoryStream)writer.BaseStream).ToArray(); } + // Check that a type is suitable for use in a custom attribute. + private bool ValidateType(Type t) + { + if (t.IsPrimitive) + { + return t != typeof(IntPtr) && t != typeof(UIntPtr); + } + if (t == typeof(string) || t == typeof(Type)) + { + return true; + } + if (t.IsEnum) + { + switch (Type.GetTypeCode(Enum.GetUnderlyingType(t))) + { + case TypeCode.SByte: + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + return true; + default: + return false; + } + } + if (t.IsArray) + { + if (t.GetArrayRank() != 1) + return false; + return ValidateType(t.GetElementType()!); + } + return t == typeof(object); + } + private static void VerifyTypeAndPassedObjectType(Type type, Type passedType, string paramName) { if (type != typeof(object) && Type.GetTypeCode(passedType) != Type.GetTypeCode(type)) @@ -549,9 +537,5 @@ internal void CreateCustomAttribute(ModuleBuilder mod, int tkOwner, int tkAttrib TypeBuilder.DefineCustomAttribute(mod, tkOwner, tkAttrib, m_blob, toDisk, typeof(System.Diagnostics.DebuggableAttribute) == m_con.DeclaringType); } - - internal ConstructorInfo m_con = null!; - internal object?[] m_constructorArgs = null!; - internal byte[] m_blob = null!; } } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs index a1a85b47d0bf3..d8e330dd7f98b 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -345,7 +345,7 @@ public override void BeginExceptFilterBlock() if (CurrExcStackCount == 0) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); - __ExceptionInfo current = CurrExcStack[CurrExcStackCount - 1]; + __ExceptionInfo current = CurrExcStack![CurrExcStackCount - 1]; Label endLabel = current.GetEndLabel(); Emit(OpCodes.Leave, endLabel); @@ -359,7 +359,7 @@ public override void BeginCatchBlock(Type exceptionType) if (CurrExcStackCount == 0) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); - __ExceptionInfo current = CurrExcStack[CurrExcStackCount - 1]; + __ExceptionInfo current = CurrExcStack![CurrExcStackCount - 1]; RuntimeType? rtType = exceptionType as RuntimeType; @@ -558,7 +558,7 @@ private int GetTokenForSig(byte[] sig) internal class DynamicResolver : Resolver { #region Private Data Members - private __ExceptionInfo[] m_exceptions = null!; + private __ExceptionInfo[]? m_exceptions; private byte[]? m_exceptionHeader; private DynamicMethod m_method; private byte[] m_code; @@ -571,7 +571,7 @@ internal class DynamicResolver : Resolver internal DynamicResolver(DynamicILGenerator ilGenerator) { m_stackSize = ilGenerator.GetMaxStackSize(); - m_exceptions = ilGenerator.GetExceptions()!; + m_exceptions = ilGenerator.GetExceptions(); m_code = ilGenerator.BakeByteArray()!; m_localSignature = ilGenerator.m_localSignature.InternalGetSignatureArray(); m_scope = ilGenerator.m_scope; @@ -586,7 +586,6 @@ internal DynamicResolver(DynamicILInfo dynamicILInfo) m_code = dynamicILInfo.Code; m_localSignature = dynamicILInfo.LocalSignature; m_exceptionHeader = dynamicILInfo.Exceptions; - // m_exceptions = dynamicILInfo.Exceptions; m_scope = dynamicILInfo.DynamicScope; m_method = dynamicILInfo.DynamicMethod; @@ -740,6 +739,8 @@ internal override byte[] GetLocalsSignature() internal override unsafe void GetEHInfo(int excNumber, void* exc) { + Debug.Assert(m_exceptions != null); + CORINFO_EH_CLAUSE* exception = (CORINFO_EH_CLAUSE*)exc; for (int i = 0; i < m_exceptions.Length; i++) { @@ -819,11 +820,13 @@ internal override void ResolveToken(int token, out IntPtr typeHandle, out IntPtr { if (vaMeth.m_dynamicMethod == null) { - methodHandle = vaMeth.m_method.MethodHandle.Value; + methodHandle = vaMeth.m_method!.MethodHandle.Value; typeHandle = vaMeth.m_method.GetDeclaringTypeInternal().GetTypeHandleInternal().Value; } else + { methodHandle = vaMeth.m_dynamicMethod.GetMethodDescriptor().Value; + } return; } @@ -1098,8 +1101,8 @@ internal GenericFieldInfo(RuntimeFieldHandle fieldHandle, RuntimeTypeHandle cont internal sealed class VarArgMethod { - internal RuntimeMethodInfo m_method = null!; - internal DynamicMethod m_dynamicMethod = null!; + internal RuntimeMethodInfo? m_method; + internal DynamicMethod? m_dynamicMethod; internal SignatureHelper m_signature; internal VarArgMethod(DynamicMethod dm, SignatureHelper signature) diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 35a708a1f867d..c8c5468801d72 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using System.Text; @@ -12,9 +13,9 @@ namespace System.Reflection.Emit { public sealed class DynamicMethod : MethodInfo { - private RuntimeType[] m_parameterTypes = null!; + private RuntimeType[] m_parameterTypes; internal IRuntimeMethodInfo? m_methodHandle; - private RuntimeType m_returnType = null!; + private RuntimeType m_returnType; private DynamicILGenerator? m_ilGenerator; private DynamicILInfo? m_DynamicILInfo; private bool m_fInitLocals; @@ -28,7 +29,7 @@ public sealed class DynamicMethod : MethodInfo // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would // not be able to bound access to the DynamicMethod. Hence, we need to ensure that // we do not allow direct use of RTDynamicMethod. - private RTDynamicMethod m_dynMethod = null!; + private RTDynamicMethod m_dynMethod; // needed to keep the object alive during jitting // assigned by the DynamicResolver ctor @@ -249,6 +250,9 @@ private static RuntimeModule GetDynamicMethodsModule() return s_anonymouslyHostedDynamicMethodsModule; } + [MemberNotNull(nameof(m_parameterTypes))] + [MemberNotNull(nameof(m_returnType))] + [MemberNotNull(nameof(m_dynMethod))] private void Init(string name, MethodAttributes attributes, CallingConventions callingConvention, diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index c8f6febd432e5..354d470bb982a 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -40,20 +40,20 @@ internal static T[] EnlargeArray(T[] incoming, int requiredSize) private int m_length; private byte[] m_ILStream; - private int[] m_labelList; + private int[]? m_labelList; private int m_labelCount; - private __FixupData[] m_fixupData; + private __FixupData[]? m_fixupData; private int m_fixupCount; - private int[] m_RelocFixupList; + private int[]? m_RelocFixupList; private int m_RelocFixupCount; private int m_exceptionCount; private int m_currExcStackCount; - private __ExceptionInfo[] m_exceptions; // This is the list of all of the exceptions in this ILStream. - private __ExceptionInfo[] m_currExcStack; // This is the stack of exceptions which we're currently in. + private __ExceptionInfo[]? m_exceptions; // This is the list of all of the exceptions in this ILStream. + private __ExceptionInfo[]? m_currExcStack; // This is the stack of exceptions which we're currently in. internal ScopeTree m_ScopeTree; // this variable tracks all debugging scope information internal LineNumberInfo m_LineNumberInfo; // this variable tracks all line number information @@ -69,7 +69,7 @@ internal static T[] EnlargeArray(T[] incoming, int requiredSize) internal int CurrExcStackCount => m_currExcStackCount; - internal __ExceptionInfo[] CurrExcStack => m_currExcStack; + internal __ExceptionInfo[]? CurrExcStack => m_currExcStack; #endregion @@ -87,29 +87,12 @@ internal ILGenerator(MethodInfo methodBuilder, int size) m_ILStream = new byte[Math.Max(size, DefaultSize)]; - m_length = 0; - - m_labelCount = 0; - m_fixupCount = 0; - m_labelList = null!; - - m_fixupData = null!; - - m_exceptions = null!; - m_exceptionCount = 0; - m_currExcStack = null!; - m_currExcStackCount = 0; - - m_RelocFixupList = null!; - m_RelocFixupCount = 0; - // initialize the scope tree m_ScopeTree = new ScopeTree(); m_LineNumberInfo = new LineNumberInfo(); m_methodBuilder = methodBuilder; // initialize local signature - m_localCount = 0; MethodBuilder? mb = m_methodBuilder as MethodBuilder; m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb?.GetTypeBuilder().Module); } @@ -215,7 +198,7 @@ private int GetMethodToken(MethodBase method, Type[]? optionalParameterTypes, bo // replacing them with their proper values. for (int i = 0; i < m_fixupCount; i++) { - __FixupData fixupData = m_fixupData[i]; + __FixupData fixupData = m_fixupData![i]; int updateAddr = GetLabelPos(fixupData.m_fixupLabel) - (fixupData.m_fixupPos + fixupData.m_fixupInstSize); // Handle single byte instructions @@ -253,7 +236,7 @@ private int GetMethodToken(MethodBase method, Type[]? optionalParameterTypes, bo } var temp = new __ExceptionInfo[m_exceptionCount]; - Array.Copy(m_exceptions, temp, m_exceptionCount); + Array.Copy(m_exceptions!, temp, m_exceptionCount); SortExceptions(temp); return temp; } @@ -288,7 +271,7 @@ private int GetLabelPos(Label lbl) int index = lbl.GetLabelValue(); - if (index < 0 || index >= m_labelCount) + if (index < 0 || index >= m_labelCount || m_labelList is null) throw new ArgumentException(SR.Argument_BadLabel); if (m_labelList[index] < 0) @@ -355,7 +338,7 @@ private static void SortExceptions(__ExceptionInfo[] exceptions) } int[] narrowTokens = new int[m_RelocFixupCount]; - Array.Copy(m_RelocFixupList, narrowTokens, m_RelocFixupCount); + Array.Copy(m_RelocFixupList!, narrowTokens, m_RelocFixupCount); return narrowTokens; } #endregion @@ -964,7 +947,7 @@ public virtual void EndExceptionBlock() } // Pop the current exception block - __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; + __ExceptionInfo current = m_currExcStack![m_currExcStackCount - 1]; m_currExcStack[--m_currExcStackCount] = null!; Label endLabel = current.GetEndLabel(); @@ -988,7 +971,7 @@ public virtual void EndExceptionBlock() // Check if we've already set this label. // The only reason why we might have set this is if we have a finally block. - Label label = m_labelList[endLabel.GetLabelValue()] != -1 + Label label = m_labelList![endLabel.GetLabelValue()] != -1 ? current.m_finallyEndLabel : endLabel; @@ -1004,7 +987,7 @@ public virtual void BeginExceptFilterBlock() if (m_currExcStackCount == 0) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); - __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; + __ExceptionInfo current = m_currExcStack![m_currExcStackCount - 1]; Emit(OpCodes.Leave, current.GetEndLabel()); @@ -1019,7 +1002,7 @@ public virtual void BeginCatchBlock(Type exceptionType) { throw new NotSupportedException(SR.Argument_NotInExceptionBlock); } - __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; + __ExceptionInfo current = m_currExcStack![m_currExcStackCount - 1]; if (current.GetCurrentState() == __ExceptionInfo.State_Filter) { @@ -1050,7 +1033,7 @@ public virtual void BeginFaultBlock() { throw new NotSupportedException(SR.Argument_NotInExceptionBlock); } - __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; + __ExceptionInfo current = m_currExcStack![m_currExcStackCount - 1]; // emit the leave for the clause before this one. Emit(OpCodes.Leave, current.GetEndLabel()); @@ -1064,7 +1047,7 @@ public virtual void BeginFinallyBlock() { throw new NotSupportedException(SR.Argument_NotInExceptionBlock); } - __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; + __ExceptionInfo current = m_currExcStack![m_currExcStackCount - 1]; int state = current.GetCurrentState(); Label endLabel = current.GetEndLabel(); int catchEndAddr = 0; @@ -1114,8 +1097,8 @@ public virtual void MarkLabel(Label loc) int labelIndex = loc.GetLabelValue(); - // This should never happen. - if (labelIndex < 0 || labelIndex >= m_labelList.Length) + // This should only happen if a label from another generator is used with this one. + if (m_labelList is null || labelIndex < 0 || labelIndex >= m_labelList.Length) { throw new ArgumentException(SR.Argument_InvalidLabel); } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs index c5ae82adaeed6..e3c189f910beb 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs @@ -620,7 +620,7 @@ public MethodToken GetToken() // We need to lock here to prevent a method from being "tokenized" twice. // We don't need to synchronize this with Type.DefineMethod because it only appends newly // constructed MethodBuilders to the end of m_listMethods - lock (m_containingType.m_listMethods) + lock (m_containingType.m_listMethods!) { if (m_tkMethod.Token != 0) { diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs index 0808335d3b8de..a9db943c8ae58 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs @@ -2,10 +2,11 @@ // 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.Text; using System.Buffers.Binary; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using System.Text; namespace System.Reflection.Emit { @@ -185,7 +186,7 @@ internal static SignatureHelper GetTypeSigToken(Module module, Type type) #endregion #region Private Data Members - private byte[] m_signature = null!; + private byte[] m_signature; private int m_currSig; // index into m_signature buffer for next available byte private int m_sizeLoc; // index into m_signature buffer to put m_argCount (will be NO_SIZE_IN_SIG if no arg count is needed) private ModuleBuilder? m_module; @@ -225,6 +226,7 @@ private SignatureHelper(Module mod, Type type) AddOneArgTypeHelper(type); } + [MemberNotNull(nameof(m_signature))] private void Init(Module? mod) { m_signature = new byte[32]; @@ -238,11 +240,13 @@ private void Init(Module? mod) throw new ArgumentException(SR.NotSupported_MustBeModuleBuilder); } + [MemberNotNull(nameof(m_signature))] private void Init(Module? mod, MdSigCallingConvention callingConvention) { Init(mod, callingConvention, 0); } + [MemberNotNull(nameof(m_signature))] private void Init(Module? mod, MdSigCallingConvention callingConvention, int cGenericParam) { Init(mod); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs index a78fd852c9799..65d61ca28adee 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs @@ -396,15 +396,15 @@ internal static unsafe void SetConstantValue(ModuleBuilder module, int tk, Type #region Private Data Members private List? m_ca; private TypeToken m_tdType; - private readonly ModuleBuilder m_module = null!; + private readonly ModuleBuilder m_module; private readonly string? m_strName; private readonly string? m_strNameSpace; private string? m_strFullQualName; private Type? m_typeParent; - private List m_typeInterfaces = null!; + private List? m_typeInterfaces; private readonly TypeAttributes m_iAttr; private GenericParameterAttributes m_genParamAttributes; - internal List m_listMethods = null!; + internal List? m_listMethods; internal int m_lastTokenizedMethod; private int m_constructorCount; private readonly int m_iTypeSize; @@ -430,7 +430,7 @@ internal TypeBuilder(ModuleBuilder module) { m_tdType = new TypeToken((int)MetadataTokenType.TypeDef); m_isHiddenGlobalType = true; - m_module = (ModuleBuilder)module; + m_module = module; m_listMethods = new List(); // No token has been created so let's initialize it to -1 // The first time we call MethodBuilder.GetToken this will incremented. @@ -438,8 +438,13 @@ internal TypeBuilder(ModuleBuilder module) } // ctor for generic method parameter - internal TypeBuilder(string szName, int genParamPos, MethodBuilder declMeth) : this(szName, genParamPos) + internal TypeBuilder(string szName, int genParamPos, MethodBuilder declMeth) { + m_strName = szName; + m_genParamPos = genParamPos; + m_bIsGenParam = true; + m_typeInterfaces = new List(); + Debug.Assert(declMeth != null); m_declMeth = declMeth; m_DeclaringType = m_declMeth.GetTypeBuilder(); @@ -447,20 +452,16 @@ internal TypeBuilder(string szName, int genParamPos, MethodBuilder declMeth) : t } // ctor for generic type parameter - private TypeBuilder(string szName, int genParamPos, TypeBuilder declType) : this(szName, genParamPos) - { - Debug.Assert(declType != null); - m_DeclaringType = declType; - m_module = declType.GetModuleBuilder(); - } - - // only for delegating to by other ctors - private TypeBuilder(string szName, int genParamPos) + private TypeBuilder(string szName, int genParamPos, TypeBuilder declType) { m_strName = szName; m_genParamPos = genParamPos; m_bIsGenParam = true; m_typeInterfaces = new List(); + + Debug.Assert(declType != null); + m_DeclaringType = declType; + m_module = declType.GetModuleBuilder(); } internal TypeBuilder( @@ -1295,7 +1296,7 @@ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, Call } } - m_listMethods.Add(method); + m_listMethods!.Add(method); return method; } @@ -1381,7 +1382,7 @@ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, Call // and our equals check won't work. _ = method.GetMethodSignature().InternalGetSignature(out _); - if (m_listMethods.Contains(method)) + if (m_listMethods!.Contains(method)) { throw new ArgumentException(SR.Argument_MethodRedefined); } @@ -1954,7 +1955,7 @@ internal void CheckContext(params Type?[]? types) } } - int size = m_listMethods.Count; + int size = m_listMethods!.Count; for (int i = 0; i < size; i++) { @@ -2032,12 +2033,12 @@ internal void CheckContext(params Type?[]? types) m_hasBeenCreated = true; // Terminate the process. - RuntimeType cls = null!; + RuntimeType? cls = null; TermCreateClass(new QCallModule(ref module), m_tdType.Token, ObjectHandleOnStack.Create(ref cls)); if (!m_isHiddenGlobalType) { - m_bakedRuntimeType = cls; + m_bakedRuntimeType = cls!; // if this type is a nested type, we need to invalidate the cached nested runtime type on the nesting type if (m_DeclaringType != null && m_DeclaringType.m_bakedRuntimeType != null) @@ -2105,7 +2106,7 @@ public void AddInterfaceImplementation(Type interfaceType) ModuleBuilder module = m_module; AddInterfaceImpl(new QCallModule(ref module), m_tdType.Token, tkInterface.Token); - m_typeInterfaces.Add(interfaceType); + m_typeInterfaces!.Add(interfaceType); } public TypeToken TypeToken diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs index 3c467b743290d..7ab2a594ab52f 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs @@ -69,7 +69,7 @@ internal virtual Type[] GetParameterTypes() // copy the arguments in a different array so we detach from any user changes object[] copyOfParameters = new object[parameters.Length]; - ParameterInfo[] p = null!; + ParameterInfo[]? p = null; for (int i = 0; i < parameters.Length; i++) { object arg = parameters[i]; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index 77367461e462d..133f825dbcc06 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -18,11 +18,11 @@ internal sealed class RuntimeConstructorInfo : ConstructorInfo, IRuntimeMethodIn private RuntimeTypeCache m_reflectedTypeCache; private string? m_toString; private ParameterInfo[]? m_parameters; // Created lazily when GetParameters() is called. -#pragma warning disable CA1823, 414 - private object _empty1 = null!; // These empties are used to ensure that RuntimeConstructorInfo and RuntimeMethodInfo are have a layout which is sufficiently similar - private object _empty2 = null!; - private object _empty3 = null!; -#pragma warning restore CA1823, 414 +#pragma warning disable CA1823, 414, 169 + private object? _empty1; // These empties are used to ensure that RuntimeConstructorInfo and RuntimeMethodInfo are have a layout which is sufficiently similar + private object? _empty2; + private object? _empty3; +#pragma warning restore CA1823, 414, 169 private IntPtr m_handle; private MethodAttributes m_methodAttributes; private BindingFlags m_bindingFlags; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs index 0b24a02472d5a..2a14dc6b9a188 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs @@ -15,20 +15,16 @@ internal sealed unsafe class RuntimeEventInfo : EventInfo private EventAttributes m_flags; private string? m_name; private void* m_utf8name; - private RuntimeTypeCache m_reflectedTypeCache = null!; + private RuntimeTypeCache m_reflectedTypeCache; private RuntimeMethodInfo? m_addMethod; private RuntimeMethodInfo? m_removeMethod; private RuntimeMethodInfo? m_raiseMethod; private MethodInfo[]? m_otherMethod; - private RuntimeType m_declaringType = null!; + private RuntimeType m_declaringType; private BindingFlags m_bindingFlags; #endregion #region Constructor - internal RuntimeEventInfo() - { - // Used for dummy head node during population - } internal RuntimeEventInfo(int tkEvent, RuntimeType declaredType, RuntimeTypeCache reflectedTypeCache, out bool isPrivate) { Debug.Assert(declaredType != null); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs index 5eb9a5fd3cc20..fc64e1d9713a6 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs @@ -11,15 +11,11 @@ internal abstract class RuntimeFieldInfo : FieldInfo { #region Private Data Members private BindingFlags m_bindingFlags; - protected RuntimeTypeCache m_reflectedTypeCache = null!; - protected RuntimeType m_declaringType = null!; + protected RuntimeTypeCache m_reflectedTypeCache; + protected RuntimeType m_declaringType; #endregion #region Constructor - protected RuntimeFieldInfo() - { - // Used for dummy head node during population - } protected RuntimeFieldInfo(RuntimeTypeCache reflectedTypeCache, RuntimeType declaringType, BindingFlags bindingFlags) { m_bindingFlags = bindingFlags; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index c7ad03319ddf3..f8a0ff0b329ce 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -113,7 +113,7 @@ internal static ParameterInfo GetReturnParameter(IRuntimeMethodInfo method, Memb #region Private Data Members private int m_tkParamDef; private MetadataImport m_scope; - private Signature m_signature = null!; + private Signature? m_signature; private volatile bool m_nameIsCached = false; private readonly bool m_noMetadata = false; private bool m_noDefaultValue = false; @@ -217,6 +217,8 @@ public override Type ParameterType // only instance of ParameterInfo has ClassImpl, all its subclasses don't if (ClassImpl == null) { + Debug.Assert(m_signature != null); + RuntimeType parameterType; if (PositionImpl == -1) parameterType = m_signature.ReturnType; @@ -481,12 +483,16 @@ private static DateTime GetRawDateTimeConstant(CustomAttributeData attr) public override Type[] GetRequiredCustomModifiers() { - return m_signature.GetCustomModifiers(PositionImpl + 1, true); + return m_signature is null ? + Type.EmptyTypes : + m_signature.GetCustomModifiers(PositionImpl + 1, true); } public override Type[] GetOptionalCustomModifiers() { - return m_signature.GetCustomModifiers(PositionImpl + 1, false); + return m_signature is null ? + Type.EmptyTypes : + m_signature.GetCustomModifiers(PositionImpl + 1, false); } #endregion diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index a5db6f21277f4..15cad52659557 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -9,13 +9,6 @@ using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System.Runtime.CompilerServices { internal static unsafe class CastHelpers diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs index 9f45efa3df1c5..89d0773075d8a 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs @@ -30,7 +30,7 @@ internal class LAHashDependentHashTracker [StructLayout(LayoutKind.Sequential)] internal class LAHashKeyToTrackers { - private object _trackerOrTrackerSet = null!; - private object _laLocalKeyValueStore = null!; + private object? _trackerOrTrackerSet; + private object? _laLocalKeyValueStore; } } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs index 763ab98ceb3ca..396967048ff0b 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs @@ -13,7 +13,7 @@ namespace System.Runtime.CompilerServices [StructLayout(LayoutKind.Sequential)] internal class GCHeapHash { - private Array _data = null!; + private Array? _data; private int _count; private int _deletedCount; } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index a0e841070d15e..55d7ee78afc3a 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -7,13 +7,6 @@ using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System.Runtime.CompilerServices { public static partial class RuntimeHelpers @@ -295,6 +288,12 @@ public static IntPtr AllocateTypeAssociatedMemory(Type type, int size) [MethodImpl(MethodImplOptions.InternalCall)] private static unsafe extern TailCallTls* GetTailCallInfo(IntPtr retAddrSlot, IntPtr* retAddr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern long GetILBytesJitted(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int GetMethodsJittedCount(); } // Helper class to assist with unsafe pinning of arbitrary objects. // It's used by VM code. @@ -348,31 +347,31 @@ internal unsafe struct MethodTable | 0x40000000 // enum_flag_ComObject | 0x00400000;// enum_flag_ICastable; - private const int ParentMethodTableOffset = 0x10 + private const int DebugClassNamePtr = // adjust for debug_m_szClassName #if DEBUG - + sizeof(nuint) // adjust for debug_m_szClassName -#endif - ; - #if TARGET_64BIT - private const int ElementTypeOffset = 0x30 + 8 #else - private const int ElementTypeOffset = 0x20 + 4 #endif -#if DEBUG - + sizeof(nuint) // adjust for debug_m_szClassName +#else + 0 #endif - ; + ; + + private const int ParentMethodTableOffset = 0x10 + DebugClassNamePtr; #if TARGET_64BIT - private const int InterfaceMapOffset = 0x38 + private const int ElementTypeOffset = 0x30 + DebugClassNamePtr; #else - private const int InterfaceMapOffset = 0x24 + private const int ElementTypeOffset = 0x20 + DebugClassNamePtr; #endif -#if DEBUG - + sizeof(nuint) // adjust for debug_m_szClassName + +#if TARGET_64BIT + private const int InterfaceMapOffset = 0x38 + DebugClassNamePtr; +#else + private const int InterfaceMapOffset = 0x24 + DebugClassNamePtr; #endif - ; public bool HasComponentSize { diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 323e60a564801..6bdd48d7290a9 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -136,7 +136,7 @@ public IntPtr GetOrCreateComInterfaceForObject(object instance, CreateComInterfa { IntPtr ptr; if (!TryGetOrCreateComInterfaceForObjectInternal(this, instance, flags, out ptr)) - throw new ArgumentException(); + throw new ArgumentException(null, nameof(instance)); return ptr; } @@ -215,7 +215,7 @@ public object GetOrCreateObjectForComInstance(IntPtr externalComObject, CreateOb { object? obj; if (!TryGetOrCreateObjectForComInstanceInternal(this, externalComObject, flags, null, out obj)) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(externalComObject)); return obj!; } @@ -271,7 +271,7 @@ public object GetOrRegisterObjectForComInstance(IntPtr externalComObject, Create object? obj; if (!TryGetOrCreateObjectForComInstanceInternal(this, externalComObject, flags, wrapper, out obj)) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(externalComObject)); return obj!; } @@ -331,8 +331,15 @@ public static void RegisterForTrackerSupport(ComWrappers instance) { throw new InvalidOperationException(SR.InvalidOperation_ResetGlobalComWrappersInstance); } + + SetGlobalInstanceRegisteredForTrackerSupport(); } + + [DllImport(RuntimeHelpers.QCall)] + [SuppressGCTransition] + private static extern void SetGlobalInstanceRegisteredForTrackerSupport(); + /// /// Register a instance to be used as the global instance for marshalling in the runtime. /// @@ -390,4 +397,4 @@ internal static int CallICustomQueryInterface(object customQueryInterfaceMaybe, return (int)customQueryInterface.GetInterface(ref iid, out ppObject); } } -} \ No newline at end of file +} diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 7b494115f72d6..997fa49107dce 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -95,6 +95,16 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) } #endif + // This method is invoked by the VM to resolve a satellite assembly reference + // after trying assembly resolution via Load override without success. + private static Assembly? ResolveSatelliteAssembly(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + { + AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; + + // Invoke the ResolveSatelliteAssembly method + return context.ResolveSatelliteAssembly(assemblyName); + } + // This method is invoked by the VM when using the host-provided assembly load context // implementation. private static IntPtr ResolveUnmanagedDll(string unmanagedDllName, IntPtr gchManagedAssemblyLoadContext) diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs index 5661ce8130ec5..c95afb2036300 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -446,10 +446,10 @@ internal static RuntimeType GetTypeByNameUsingCARules(string name, RuntimeModule if (string.IsNullOrEmpty(name)) throw new ArgumentException(null, nameof(name)); - RuntimeType type = null!; + RuntimeType? type = null; GetTypeByNameUsingCARules(name, new QCallModule(ref scope), ObjectHandleOnStack.Create(ref type)); - return type; + return type!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -457,18 +457,18 @@ internal static RuntimeType GetTypeByNameUsingCARules(string name, RuntimeModule internal RuntimeType[] GetInstantiationInternal() { - RuntimeType[] types = null!; + RuntimeType[]? types = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); GetInstantiation(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref types), Interop.BOOL.TRUE); - return types; + return types!; } internal Type[] GetInstantiationPublic() { - Type[] types = null!; + Type[]? types = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); GetInstantiation(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref types), Interop.BOOL.FALSE); - return types; + return types!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -481,11 +481,11 @@ internal RuntimeType Instantiate(Type[]? inst) fixed (IntPtr* pInst = instHandles) { - RuntimeType type = null!; + RuntimeType? type = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); Instantiate(new QCallTypeHandle(ref nativeHandle), pInst, instCount, ObjectHandleOnStack.Create(ref type)); GC.KeepAlive(inst); - return type; + return type!; } } @@ -494,10 +494,10 @@ internal RuntimeType Instantiate(Type[]? inst) internal RuntimeType MakeArray(int rank) { - RuntimeType type = null!; + RuntimeType? type = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); MakeArray(new QCallTypeHandle(ref nativeHandle), rank, ObjectHandleOnStack.Create(ref type)); - return type; + return type!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -505,10 +505,10 @@ internal RuntimeType MakeArray(int rank) internal RuntimeType MakeSZArray() { - RuntimeType type = null!; + RuntimeType? type = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); MakeSZArray(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref type)); - return type; + return type!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -516,10 +516,10 @@ internal RuntimeType MakeSZArray() internal RuntimeType MakeByRef() { - RuntimeType type = null!; + RuntimeType? type = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); MakeByRef(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref type)); - return type; + return type!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -527,10 +527,10 @@ internal RuntimeType MakeByRef() internal RuntimeType MakePointer() { - RuntimeType type = null!; + RuntimeType? type = null; RuntimeTypeHandle nativeHandle = GetNativeHandle(); MakePointer(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref type)); - return type; + return type!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -665,15 +665,15 @@ public RuntimeMethodInfoStub(IntPtr methodHandleValue, object keepalive) private readonly object m_keepalive; // These unused variables are used to ensure that this class has the same layout as RuntimeMethodInfo -#pragma warning disable CA1823, 414 - private object m_a = null!; - private object m_b = null!; - private object m_c = null!; - private object m_d = null!; - private object m_e = null!; - private object m_f = null!; - private object m_g = null!; -#pragma warning restore CA1823, 414 +#pragma warning disable CA1823, 414, 169 + private object? m_a; + private object? m_b; + private object? m_c; + private object? m_d; + private object? m_e; + private object? m_f; + private object? m_g; +#pragma warning restore CA1823, 414, 169 public RuntimeMethodHandleInternal m_value; @@ -861,25 +861,25 @@ internal static MdUtf8String GetUtf8Name(RuntimeMethodHandleInternal method) internal static RuntimeType[] GetMethodInstantiationInternal(IRuntimeMethodInfo method) { - RuntimeType[] types = null!; + RuntimeType[]? types = null; GetMethodInstantiation(EnsureNonNullMethodInfo(method).Value, ObjectHandleOnStack.Create(ref types), Interop.BOOL.TRUE); GC.KeepAlive(method); - return types; + return types!; } internal static RuntimeType[] GetMethodInstantiationInternal(RuntimeMethodHandleInternal method) { - RuntimeType[] types = null!; + RuntimeType[]? types = null; GetMethodInstantiation(method, ObjectHandleOnStack.Create(ref types), Interop.BOOL.TRUE); - return types; + return types!; } internal static Type[] GetMethodInstantiationPublic(IRuntimeMethodInfo method) { - RuntimeType[] types = null!; + RuntimeType[]? types = null; GetMethodInstantiation(EnsureNonNullMethodInfo(method).Value, ObjectHandleOnStack.Create(ref types), Interop.BOOL.FALSE); GC.KeepAlive(method); - return types; + return types!; } [MethodImpl(MethodImplOptions.InternalCall)] @@ -1000,14 +1000,14 @@ RuntimeFieldHandleInternal Value internal class RuntimeFieldInfoStub : IRuntimeFieldInfo { // These unused variables are used to ensure that this class has the same layout as RuntimeFieldInfo -#pragma warning disable 414 - private object m_keepalive = null!; - private object m_c = null!; - private object m_d = null!; +#pragma warning disable 414, 169 + private object? m_keepalive; + private object? m_c; + private object? m_d; private int m_b; - private object m_e = null!; + private object? m_e; private RuntimeFieldHandleInternal m_fieldHandle; -#pragma warning restore 414 +#pragma warning restore 414, 169 RuntimeFieldHandleInternal IRuntimeFieldInfo.Value => m_fieldHandle; } @@ -1209,11 +1209,11 @@ internal static RuntimeType ResolveTypeHandleInternal(RuntimeModule module, int fixed (IntPtr* typeInstArgs = typeInstantiationContextHandles, methodInstArgs = methodInstantiationContextHandles) { - RuntimeType type = null!; + RuntimeType? type = null; ResolveType(new QCallModule(ref module), typeToken, typeInstArgs, typeInstCount, methodInstArgs, methodInstCount, ObjectHandleOnStack.Create(ref type)); GC.KeepAlive(typeInstantiationContext); GC.KeepAlive(methodInstantiationContext); - return type; + return type!; } } @@ -1288,11 +1288,11 @@ internal static IRuntimeFieldInfo ResolveFieldHandleInternal(RuntimeModule modul fixed (IntPtr* typeInstArgs = typeInstantiationContextHandles, methodInstArgs = methodInstantiationContextHandles) { - IRuntimeFieldInfo field = null!; + IRuntimeFieldInfo? field = null; ResolveField(new QCallModule(ref module), fieldToken, typeInstArgs, typeInstCount, methodInstArgs, methodInstCount, ObjectHandleOnStack.Create(ref field)); GC.KeepAlive(typeInstantiationContext); GC.KeepAlive(methodInstantiationContext); - return field; + return field!; } } @@ -1318,9 +1318,9 @@ internal static bool ContainsPropertyMatchingHash(RuntimeModule module, int prop internal static RuntimeType GetModuleType(RuntimeModule module) { - RuntimeType type = null!; + RuntimeType? type = null; GetModuleType(new QCallModule(ref module), ObjectHandleOnStack.Create(ref type)); - return type; + return type!; } [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] @@ -1375,6 +1375,8 @@ internal enum MdSigCallingConvention : byte #endregion #region FCalls + [MemberNotNull(nameof(m_arguments))] + [MemberNotNull(nameof(m_returnTypeORfieldType))] [MethodImpl(MethodImplOptions.InternalCall)] private extern void GetSignature( void* pCorSig, int cCorSig, @@ -1386,9 +1388,9 @@ internal enum MdSigCallingConvention : byte // // Keep the layout in sync with SignatureNative in the VM // - internal RuntimeType[] m_arguments = null!; - internal RuntimeType m_declaringType = null!; // seems not used - internal RuntimeType m_returnTypeORfieldType = null!; + internal RuntimeType[] m_arguments; + internal RuntimeType? m_declaringType; + internal RuntimeType m_returnTypeORfieldType; internal object? m_keepalive; internal void* m_sig; internal int m_managedCallingConventionAndArgIteratorFlags; // lowest byte is CallingConvention, upper 3 bytes are ArgIterator flags diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 93cfd86bc167b..38511276255be 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -244,14 +244,17 @@ internal MethodBase AddMethod(RuntimeType declaringType, RuntimeMethodHandleInte switch (cacheType) { case CacheType.Method: - list = (T[])(object)new RuntimeMethodInfo[1] { - new RuntimeMethodInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null) - }; + list = (T[])(object)new RuntimeMethodInfo[1] + { + new RuntimeMethodInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null) + }; break; + case CacheType.Constructor: - list = (T[])(object)new RuntimeConstructorInfo[1] { - new RuntimeConstructorInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags) - }; + list = (T[])(object)new RuntimeConstructorInfo[1] + { + new RuntimeConstructorInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags) + }; break; } @@ -2752,7 +2755,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) protected override PropertyInfo? GetPropertyImpl( string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers) { - if (name == null) throw new ArgumentNullException(); + if (name == null) throw new ArgumentNullException(nameof(name)); ListBuilder candidates = GetPropertyCandidates(name, bindingAttr, types, false); @@ -2788,7 +2791,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) { - if (name is null) throw new ArgumentNullException(); + if (name is null) throw new ArgumentNullException(nameof(name)); FilterHelper(bindingAttr, ref name, out _, out MemberListType listType); @@ -2851,7 +2854,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) public override Type? GetInterface(string fullname, bool ignoreCase) { - if (fullname is null) throw new ArgumentNullException(); + if (fullname is null) throw new ArgumentNullException(nameof(fullname)); BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic; @@ -2885,7 +2888,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) public override Type? GetNestedType(string fullname, BindingFlags bindingAttr) { - if (fullname is null) throw new ArgumentNullException(); + if (fullname is null) throw new ArgumentNullException(nameof(fullname)); bindingAttr &= ~BindingFlags.Static; string name, ns; @@ -2913,7 +2916,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) { - if (name is null) throw new ArgumentNullException(); + if (name is null) throw new ArgumentNullException(nameof(name)); ListBuilder methods = default; ListBuilder constructors = default; @@ -4062,7 +4065,7 @@ internal static Type GetTypeFromCLSIDImpl(Guid clsid, string? server, bool throw // Handle arguments that are passed as ByRef and those // arguments that need to be wrapped. - ParameterModifier[] aParamMod = null!; + ParameterModifier[]? aParamMod = null; if (cArgs > 0) { ParameterModifier paramMod = new ParameterModifier(cArgs); @@ -4087,7 +4090,7 @@ internal static Type GetTypeFromCLSIDImpl(Guid clsid, string? server, bool throw for (int i = 0; i < cArgs; i++) { // Determine if the parameter is ByRef. - if (aParamMod[0][i] && aArgs[i] != null) + if (aParamMod![0][i] && aArgs[i] != null) { Type argType = aArgsTypes[i]; if (!ReferenceEquals(argType, aArgs[i].GetType())) diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs index c2d72e3915cae..719576c06d033 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs @@ -192,6 +192,13 @@ public static partial class ThreadPool // Time in ms for which ThreadPoolWorkQueue.Dispatch keeps executing work items before returning to the OS private const uint DispatchQuantum = 30; + private static bool GetEnableWorkerTracking() + { + bool enableWorkerTracking = false; + InitializeVMTp(ref enableWorkerTracking); + return enableWorkerTracking; + } + internal static bool KeepDispatching(int startTickCount) { // Note: this function may incorrectly return false due to TickCount overflow @@ -260,7 +267,7 @@ public static void GetAvailableThreads(out int workerThreads, out int completion get; } - private static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException + private static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, WaitOrTimerCallback callBack, object? state, @@ -302,25 +309,6 @@ bool compressStack public static unsafe bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) => PostQueuedCompletionStatus(overlapped); - // The thread pool maintains a per-appdomain managed work queue. - // New thread pool entries are added in the managed queue. - // The VM is responsible for the actual growing/shrinking of - // threads. - private static void EnsureInitialized() - { - if (!ThreadPoolGlobals.threadPoolInitialized) - { - EnsureVMInitializedCore(); // separate out to help with inlining - } - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void EnsureVMInitializedCore() - { - InitializeVMTp(ref ThreadPoolGlobals.enableWorkerTracking); - ThreadPoolGlobals.threadPoolInitialized = true; - } - // Native methods: [MethodImpl(MethodImplOptions.InternalCall)] @@ -346,7 +334,6 @@ private static void EnsureVMInitializedCore() internal static void NotifyWorkItemProgress() { - EnsureInitialized(); NotifyWorkItemProgressNative(); } diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 1591f347cbe90..24bc4415e586e 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1578,6 +1578,18 @@ bool MyICJI::runWithErrorTrap(void (*function)(void*), void* param) return RunWithErrorTrap(function, param); } +// Ideally we'd just use the copies of this in standardmacros.h +// however, superpmi is missing various other dependencies as well +static size_t ALIGN_UP_SPMI(size_t val, size_t alignment) +{ + return (val + (alignment - 1)) & ~(alignment - 1); +} + +static void* ALIGN_UP_SPMI(void* val, size_t alignment) +{ + return (void*)ALIGN_UP_SPMI((size_t)val, alignment); +} + // get a block of memory for the code, readonly data, and read-write data void MyICJI::allocMem(ULONG hotCodeSize, /* IN */ ULONG coldCodeSize, /* IN */ @@ -1590,13 +1602,46 @@ void MyICJI::allocMem(ULONG hotCodeSize, /* IN */ ) { jitInstance->mc->cr->AddCall("allocMem"); - // TODO-Cleanup: investigate if we need to check roDataBlock as well. Could hot block size be ever 0? + + // TODO-Cleanup: Could hot block size be ever 0? *hotCodeBlock = jitInstance->mc->cr->allocateMemory(hotCodeSize); + if (coldCodeSize > 0) *coldCodeBlock = jitInstance->mc->cr->allocateMemory(coldCodeSize); else *coldCodeBlock = nullptr; - *roDataBlock = jitInstance->mc->cr->allocateMemory(roDataSize); + + if (roDataSize > 0) + { + size_t roDataAlignment = sizeof(void*); + size_t roDataAlignedSize = static_cast(roDataSize); + + if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN) != 0) + { + roDataAlignment = 32; + } + else if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) != 0) + { + roDataAlignment = 16; + } + else if (roDataSize >= 8) + { + roDataAlignment = 8; + } + + // We need to round the roDataSize up to the alignment size and then + // overallocate by at most alignment - sizeof(void*) to ensure that + // we can offset roDataBlock to be an aligned address and that the + // allocation contains at least the originally requested size after + + roDataAlignedSize = ALIGN_UP_SPMI(roDataAlignedSize, roDataAlignment); + roDataAlignedSize = roDataAlignedSize + (roDataAlignment - sizeof(void*)); + *roDataBlock = jitInstance->mc->cr->allocateMemory(roDataAlignedSize); + *roDataBlock = ALIGN_UP_SPMI(*roDataBlock, roDataAlignment); + } + else + *roDataBlock = nullptr; + jitInstance->mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); } diff --git a/src/coreclr/src/binder/assemblybinder.cpp b/src/coreclr/src/binder/assemblybinder.cpp index 784b91260ee75..362c2b867802f 100644 --- a/src/coreclr/src/binder/assemblybinder.cpp +++ b/src/coreclr/src/binder/assemblybinder.cpp @@ -14,7 +14,6 @@ #include "assemblybinder.hpp" #include "assemblyname.hpp" - #include "assembly.hpp" #include "applicationcontext.hpp" #include "bindertracing.h" @@ -380,23 +379,36 @@ namespace BINDER_SPACE _ASSERTE(ppSystemAssembly != NULL); - StackSString sCoreLibDir(systemDirectory); ReleaseHolder pSystemAssembly; - if (!sCoreLibDir.EndsWith(DIRECTORY_SEPARATOR_CHAR_W)) - { - sCoreLibDir.Append(DIRECTORY_SEPARATOR_CHAR_W); - } + // At run-time, System.Private.CoreLib.dll is expected to be the NI image. + // System.Private.CoreLib.dll is expected to be found at one of the following locations: + // * Non-single-file app: In systemDirectory, beside coreclr.dll + // * Framework-dependent single-file app: In systemDirectory, beside coreclr.dll + // * Self-contained single-file app: Within the single-file bundle. + // + // CoreLib path (sCoreLib): + // * Absolute path when looking for a file on disk + // * Bundle-relative path when looking within the single-file bundle. + StackSString sCoreLibName(CoreLibName_IL_W); StackSString sCoreLib; + BinderTracing::PathSource pathSource = BinderTracing::PathSource::Bundle; + BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(sCoreLibName, /*pathIsBundleRelative */ true); + if (!bundleFileLocation.IsValid()) + { + sCoreLib.Set(systemDirectory); + pathSource = BinderTracing::PathSource::ApplicationAssemblies; + } + CombinePath(sCoreLib, sCoreLibName, sCoreLib); - // At run-time, System.Private.CoreLib.dll is expected to be the NI image. - sCoreLib = sCoreLibDir; - sCoreLib.Append(CoreLibName_IL_W); IF_FAIL_GO(AssemblyBinder::GetAssembly(sCoreLib, TRUE /* fIsInGAC */, fBindToNativeImage, - &pSystemAssembly)); + &pSystemAssembly, + NULL /* szMDAssemblyPath */, + bundleFileLocation)); + BinderTracing::PathProbed(sCoreLib, pathSource, hr); *ppSystemAssembly = pSystemAssembly.Extract(); @@ -406,10 +418,10 @@ namespace BINDER_SPACE /* static */ - HRESULT AssemblyBinder::BindToSystemSatellite(SString &systemDirectory, - SString &simpleName, - SString &cultureName, - Assembly **ppSystemAssembly) + HRESULT AssemblyBinder::BindToSystemSatellite(SString& systemDirectory, + SString& simpleName, + SString& cultureName, + Assembly** ppSystemAssembly) { // Indirect check that binder was initialized. _ASSERTE(g_BinderVariables != NULL); @@ -418,25 +430,43 @@ namespace BINDER_SPACE _ASSERTE(ppSystemAssembly != NULL); - StackSString sMscorlibSatellite(systemDirectory); - ReleaseHolder pSystemAssembly; + // Satellite assembly's relative path + StackSString relativePath; // append culture name if (!cultureName.IsEmpty()) { - CombinePath(sMscorlibSatellite, cultureName, sMscorlibSatellite); + CombinePath(relativePath, cultureName, relativePath); } // append satellite assembly's simple name - CombinePath(sMscorlibSatellite, simpleName, sMscorlibSatellite); + CombinePath(relativePath, simpleName, relativePath); // append extension - sMscorlibSatellite.Append(W(".dll")); + relativePath.Append(W(".dll")); + // Satellite assembly's path: + // * Absolute path when looking for a file on disk + // * Bundle-relative path when looking within the single-file bundle. + StackSString sMscorlibSatellite; + + BinderTracing::PathSource pathSource = BinderTracing::PathSource::Bundle; + BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /*pathIsBundleRelative */ true); + if (!bundleFileLocation.IsValid()) + { + sMscorlibSatellite.Set(systemDirectory); + pathSource = BinderTracing::PathSource::ApplicationAssemblies; + } + CombinePath(sMscorlibSatellite, relativePath, sMscorlibSatellite); + + ReleaseHolder pSystemAssembly; IF_FAIL_GO(AssemblyBinder::GetAssembly(sMscorlibSatellite, TRUE /* fIsInGAC */, FALSE /* fExplicitBindToNativeImage */, - &pSystemAssembly)); + &pSystemAssembly, + NULL /* szMDAssemblyPath */, + bundleFileLocation)); + BinderTracing::PathProbed(sMscorlibSatellite, pathSource, hr); *ppSystemAssembly = pSystemAssembly.Extract(); @@ -553,7 +583,9 @@ namespace BINDER_SPACE // specified. Generally only NGEN PDB generation has // this TRUE. fExplicitBindToNativeImage, - &pAssembly)); + &pAssembly, + NULL /* szMDAssemblyPath */, + Bundle::ProbeAppBundle(assemblyPath))); AssemblyName *pAssemblyName; pAssemblyName = pAssembly->GetAssemblyName(); @@ -721,36 +753,75 @@ namespace BINDER_SPACE namespace { - typedef void (*OnPathProbed)(const WCHAR *path, HRESULT hr); - - HRESULT BindSatelliteResourceByProbingPaths( - const StringArrayList *pResourceRoots, - AssemblyName *pRequestedAssemblyName, - BindResult *pBindResult, - OnPathProbed onPathProbed) + HRESULT BindSatelliteResourceFromBundle( + AssemblyName* pRequestedAssemblyName, + SString &relativePath, + BindResult* pBindResult) { HRESULT hr = S_OK; - SString &simpleNameRef = pRequestedAssemblyName->GetSimpleName(); - SString &cultureRef = pRequestedAssemblyName->GetCulture(); + BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /* pathIsBundleRelative */ true); + if (!bundleFileLocation.IsValid()) + { + return hr; + } - _ASSERTE(!cultureRef.IsEmpty() && !cultureRef.EqualsCaseInsensitive(g_BinderVariables->cultureNeutral)); + ReleaseHolder pAssembly; + hr = AssemblyBinder::GetAssembly(relativePath, + FALSE /* fIsInGAC */, + FALSE /* fExplicitBindToNativeImage */, + &pAssembly, + NULL, // szMDAssemblyPath + bundleFileLocation); + + BinderTracing::PathProbed(relativePath, BinderTracing::PathSource::Bundle, hr); + + // Missing files are okay and expected when probing + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + return S_OK; + } + + pBindResult->SetAttemptResult(hr, pAssembly); + if (FAILED(hr)) + return hr; + + AssemblyName* pBoundAssemblyName = pAssembly->GetAssemblyName(); + if (TestCandidateRefMatchesDef(pRequestedAssemblyName, pBoundAssemblyName, false /*tpaListAssembly*/)) + { + pBindResult->SetResult(pAssembly); + hr = S_OK; + } + else + { + hr = FUSION_E_REF_DEF_MISMATCH; + } + + pBindResult->SetAttemptResult(hr, pAssembly); + return hr; + } + + HRESULT BindSatelliteResourceByProbingPaths( + const StringArrayList *pResourceRoots, + AssemblyName *pRequestedAssemblyName, + SString &relativePath, + BindResult *pBindResult, + BinderTracing::PathSource pathSource) + { + HRESULT hr = S_OK; for (UINT i = 0; i < pResourceRoots->GetCount(); i++) { ReleaseHolder pAssembly; SString &wszBindingPath = (*pResourceRoots)[i]; SString fileName(wszBindingPath); - - CombinePath(fileName, cultureRef, fileName); - CombinePath(fileName, simpleNameRef, fileName); - fileName.Append(W(".dll")); + CombinePath(fileName, relativePath, fileName); hr = AssemblyBinder::GetAssembly(fileName, FALSE /* fIsInGAC */, FALSE /* fExplicitBindToNativeImage */, &pAssembly); - onPathProbed(fileName, hr); + BinderTracing::PathProbed(fileName, pathSource, hr); // Missing files are okay and expected when probing if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) @@ -781,6 +852,59 @@ namespace BINDER_SPACE return S_OK; } + HRESULT BindSatelliteResource( + ApplicationContext* pApplicationContext, + AssemblyName* pRequestedAssemblyName, + BindResult* pBindResult) + { + // Satellite resource probing strategy is to look: + // * First within the single-file bundle + // * Then under each of the Platform Resource Roots + // * Then under each of the App Paths. + // + // During each search, if we find a platform resource file with matching file name, but whose ref-def didn't match, + // fall back to application resource lookup to handle case where a user creates resources with the same + // names as platform ones. + + HRESULT hr = S_OK; + SString& simpleNameRef = pRequestedAssemblyName->GetSimpleName(); + SString& cultureRef = pRequestedAssemblyName->GetCulture(); + + _ASSERTE(!cultureRef.IsEmpty() && !cultureRef.EqualsCaseInsensitive(g_BinderVariables->cultureNeutral)); + + ReleaseHolder pAssembly; + SString fileName; + CombinePath(fileName, cultureRef, fileName); + CombinePath(fileName, simpleNameRef, fileName); + fileName.Append(W(".dll")); + + hr = BindSatelliteResourceFromBundle(pRequestedAssemblyName, fileName, pBindResult); + + if (pBindResult->HaveResult() || (FAILED(hr) && hr != FUSION_E_CONFIGURATION_ERROR)) + { + return hr; + } + + hr = BindSatelliteResourceByProbingPaths(pApplicationContext->GetPlatformResourceRoots(), + pRequestedAssemblyName, + fileName, + pBindResult, + BinderTracing::PathSource::PlatformResourceRoots); + + if (pBindResult->HaveResult() || (FAILED(hr) && hr != FUSION_E_CONFIGURATION_ERROR)) + { + return hr; + } + + hr = BindSatelliteResourceByProbingPaths(pApplicationContext->GetAppPaths(), + pRequestedAssemblyName, + fileName, + pBindResult, + BinderTracing::PathSource::AppPaths); + + return hr; + } + HRESULT BindAssemblyByProbingPaths( const StringArrayList *pBindingPaths, AssemblyName *pRequestedAssemblyName, @@ -788,7 +912,6 @@ namespace BINDER_SPACE Assembly **ppAssembly) { SString &simpleName = pRequestedAssemblyName->GetSimpleName(); - BinderTracing::PathSource pathSource = useNativeImages ? BinderTracing::PathSource::AppNativeImagePaths : BinderTracing::PathSource::AppPaths; // Loop through the binding paths looking for a matching assembly for (DWORD i = 0; i < pBindingPaths->GetCount(); i++) @@ -850,6 +973,13 @@ namespace BINDER_SPACE /* * BindByTpaList is the entry-point for the custom binding algorithm in CoreCLR. + * + * The search for assemblies will proceed in the following order: + * + * If this application is a single-file bundle, the meta-data contained in the bundle + * will be probed to find the requested assembly. If the assembly is not found, + * The list of platform assemblies (TPAs) are considered next. + * * Platform assemblies are specified as a list of files. This list is the only set of * assemblies that we will load as platform. They can be specified as IL or NIs. * @@ -875,39 +1005,65 @@ namespace BINDER_SPACE if (!culture.IsEmpty() && !culture.EqualsCaseInsensitive(g_BinderVariables->cultureNeutral)) { - // - // Satellite resource probing strategy is to look under each of the Platform Resource Roots - // followed by App Paths. - // + IF_FAIL_GO(BindSatelliteResource(pApplicationContext, pRequestedAssemblyName, pBindResult)); + } + else + { + ReleaseHolder pTPAAssembly; + SString& simpleName = pRequestedAssemblyName->GetSimpleName(); + + // Is assembly in the bundle? + // Single-file bundle contents take precedence over TPA. + // The list of bundled assemblies is contained in the bundle manifest, and NOT in the TPA. + // Therefore the bundle is first probed using the assembly's simple name. + // If found, the assembly is loaded from the bundle. + if (Bundle::AppIsBundle()) + { + // Search Assembly.ni.dll, then Assembly.dll + // The Assembly.ni.dll paths are rare, and intended for supporting managed C++ R2R assemblies. + SString candidates[] = { W(".ni.dll"), W(".dll") }; - hr = BindSatelliteResourceByProbingPaths(pApplicationContext->GetPlatformResourceRoots(), - pRequestedAssemblyName, - pBindResult, - [](const WCHAR *path, HRESULT res) { BinderTracing::PathProbed(path, BinderTracing::PathSource::PlatformResourceRoots, res); }); + // Loop through the binding paths looking for a matching assembly + for (int i = 0; i < 2; i++) + { + SString assemblyFileName(simpleName); + assemblyFileName.Append(candidates[i]); - // We found a platform resource file with matching file name, but whose ref-def didn't match. Fall - // back to application resource lookup to handle case where a user creates resources with the same - // names as platform ones. - if (hr != FUSION_E_CONFIGURATION_ERROR) - { - IF_FAIL_GO(hr); - } + SString assemblyFilePath(Bundle::AppBundle->BasePath()); + assemblyFilePath.Append(assemblyFileName); - if (!pBindResult->HaveResult()) - { - IF_FAIL_GO(BindSatelliteResourceByProbingPaths(pApplicationContext->GetAppPaths(), - pRequestedAssemblyName, - pBindResult, - [](const WCHAR *path, HRESULT res) { BinderTracing::PathProbed(path, BinderTracing::PathSource::AppPaths, res); })); + BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(assemblyFileName, /* pathIsBundleRelative */ true); + if (bundleFileLocation.IsValid()) + { + hr = GetAssembly(assemblyFilePath, + TRUE, // fIsInGAC + FALSE, // fExplicitBindToNativeImage + &pTPAAssembly, + NULL, // szMDAssemblyPath + bundleFileLocation); + + BinderTracing::PathProbed(assemblyFilePath, BinderTracing::PathSource::Bundle, hr); + + if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + // Any other error is fatal + IF_FAIL_GO(hr); + + if (TestCandidateRefMatchesDef(pRequestedAssemblyName, pTPAAssembly->GetAssemblyName(), true /*tpaListAssembly*/)) + { + // We have found the requested assembly match in the bundle with validation of the full-qualified name. + // Bind to it. + pBindResult->SetResult(pTPAAssembly); + GO_WITH_HRESULT(S_OK); + } + } + } + } } - } - else - { + // Is assembly on TPA list? - SString &simpleName = pRequestedAssemblyName->GetSimpleName(); SimpleNameToFileNameMap * tpaMap = pApplicationContext->GetTpaList(); const SimpleNameToFileNameMapEntry *pTpaEntry = tpaMap->LookupPtr(simpleName.GetUnicode()); - ReleaseHolder pTPAAssembly; if (pTpaEntry != nullptr) { if (pTpaEntry->m_wszNIFileName != nullptr) @@ -1020,20 +1176,21 @@ namespace BINDER_SPACE } /* static */ - HRESULT AssemblyBinder::GetAssembly(SString &assemblyPath, - BOOL fIsInGAC, + HRESULT AssemblyBinder::GetAssembly(SString &assemblyPath, + BOOL fIsInGAC, // When binding to the native image, should we // assume assemblyPath explicitly specifies that // NI? (If not, infer the path to the NI // implicitly.) - BOOL fExplicitBindToNativeImage, + BOOL fExplicitBindToNativeImage, - Assembly **ppAssembly, + Assembly **ppAssembly, // If assemblyPath refers to a native image without metadata, // szMDAssemblyPath gives the alternative file to get metadata. - LPCTSTR szMDAssemblyPath) + LPCTSTR szMDAssemblyPath, + BundleFileLocation bundleFileLocation) { HRESULT hr = S_OK; @@ -1053,7 +1210,7 @@ namespace BINDER_SPACE { LPCTSTR szAssemblyPath = const_cast(assemblyPath.GetUnicode()); - hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, &pNativePEImage, fExplicitBindToNativeImage); + hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, &pNativePEImage, fExplicitBindToNativeImage, bundleFileLocation); IF_FAIL_GO(hr); // If we found a native image, it might be an MSIL assembly masquerading as an native image @@ -1068,7 +1225,7 @@ namespace BINDER_SPACE BinderReleasePEImage(pPEImage); BinderReleasePEImage(pNativePEImage); - hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, &pNativePEImage, false); + hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, &pNativePEImage, false, bundleFileLocation); IF_FAIL_GO(hr); } } @@ -1094,7 +1251,7 @@ namespace BINDER_SPACE } else { - hr = BinderAcquirePEImage(szMDAssemblyPath, &pPEImage, NULL, FALSE); + hr = BinderAcquirePEImage(szMDAssemblyPath, &pPEImage, NULL, FALSE, bundleFileLocation); IF_FAIL_GO(hr); hr = BinderAcquireImport(pPEImage, &pIMetaDataAssemblyImport, dwPAFlags, FALSE); diff --git a/src/coreclr/src/binder/coreclrbindercommon.cpp b/src/coreclr/src/binder/coreclrbindercommon.cpp index afd64cfc4dc58..e415b9067bb34 100644 --- a/src/coreclr/src/binder/coreclrbindercommon.cpp +++ b/src/coreclr/src/binder/coreclrbindercommon.cpp @@ -7,6 +7,7 @@ #include "assemblybinder.hpp" #include "coreclrbindercommon.h" #include "clrprivbindercoreclr.h" +#include "bundle.h" using namespace BINDER_SPACE; diff --git a/src/coreclr/src/binder/inc/assembly.hpp b/src/coreclr/src/binder/inc/assembly.hpp index 0d5500afb8203..f42cee4e62268 100644 --- a/src/coreclr/src/binder/inc/assembly.hpp +++ b/src/coreclr/src/binder/inc/assembly.hpp @@ -27,15 +27,18 @@ #include "clrprivbinderassemblyloadcontext.h" #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) -STDAPI BinderAcquirePEImage(LPCTSTR szAssemblyPath, - PEImage **ppPEImage, - PEImage **ppNativeImage, - BOOL fExplicitBindToNativeImage); - -STDAPI BinderAcquireImport(PEImage *pPEImage, - IMDInternalImport **pIMetaDataAssemblyImport, - DWORD *pdwPAFlags, - BOOL bNativeImage); +#include "bundle.h" + +STDAPI BinderAcquirePEImage(LPCTSTR szAssemblyPath, + PEImage **ppPEImage, + PEImage **ppNativeImage, + BOOL fExplicitBindToNativeImage, + BundleFileLocation bundleFileLocation); + +STDAPI BinderAcquireImport(PEImage *pPEImage, + IMDInternalImport **pIMetaDataAssemblyImport, + DWORD *pdwPAFlags, + BOOL bNativeImage); STDAPI BinderHasNativeHeader(PEImage *pPEImage, BOOL *result); diff --git a/src/coreclr/src/binder/inc/assemblybinder.hpp b/src/coreclr/src/binder/inc/assemblybinder.hpp index 1332b671edc2d..5246676b1a47f 100644 --- a/src/coreclr/src/binder/inc/assemblybinder.hpp +++ b/src/coreclr/src/binder/inc/assemblybinder.hpp @@ -18,6 +18,7 @@ #include "bindertypes.hpp" #include "bindresult.hpp" #include "coreclrbindercommon.h" +#include "bundle.h" class CLRPrivBinderAssemblyLoadContext; class CLRPrivBinderCoreCLR; @@ -54,7 +55,8 @@ namespace BINDER_SPACE /* in */ BOOL fIsInGAC, /* in */ BOOL fExplicitBindToNativeImage, /* out */ Assembly **ppAssembly, - /* in */ LPCTSTR szMDAssemblyPath = NULL); + /* in */ LPCTSTR szMDAssemblyPath = NULL, + /* in */ BundleFileLocation bundleFileLocation = BundleFileLocation::Invalid()); #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) static HRESULT BindUsingHostAssemblyResolver (/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin, diff --git a/src/coreclr/src/binder/inc/bindertracing.h b/src/coreclr/src/binder/inc/bindertracing.h index 472197bf5b4e3..6fb5137349e02 100644 --- a/src/coreclr/src/binder/inc/bindertracing.h +++ b/src/coreclr/src/binder/inc/bindertracing.h @@ -180,7 +180,8 @@ namespace BinderTracing AppNativeImagePaths, AppPaths, PlatformResourceRoots, - SatelliteSubdirectory + SatelliteSubdirectory, + Bundle }; void PathProbed(const WCHAR *path, PathSource source, HRESULT hr); diff --git a/src/coreclr/src/binder/utils.cpp b/src/coreclr/src/binder/utils.cpp index 27f1d4c6b3f6d..953da35d8ffa3 100644 --- a/src/coreclr/src/binder/utils.cpp +++ b/src/coreclr/src/binder/utils.cpp @@ -80,7 +80,7 @@ namespace BINDER_SPACE SString platformPathSeparator(SString::Literal, GetPlatformPathSeparator()); combinedPath.Set(pathA); - if (!combinedPath.EndsWith(platformPathSeparator)) + if (!combinedPath.IsEmpty() && !combinedPath.EndsWith(platformPathSeparator)) { combinedPath.Append(platformPathSeparator); } diff --git a/src/coreclr/src/classlibnative/bcltype/stringnative.h b/src/coreclr/src/classlibnative/bcltype/stringnative.h index 6aea696e41af7..c8e1fcecc9f35 100644 --- a/src/coreclr/src/classlibnative/bcltype/stringnative.h +++ b/src/coreclr/src/classlibnative/bcltype/stringnative.h @@ -42,10 +42,8 @@ class COMString { public: // - // Search/Query Methods + // Query Methods // - static FCDECL6(INT32, CompareOrdinalEx, StringObject* strA, INT32 indexA, INT32 countA, StringObject* strB, INT32 indexB, INT32 countB); - static FCDECL2(FC_CHAR_RET, GetCharAt, StringObject* pThisRef, INT32 index); static FCDECL1(INT32, Length, StringObject* pThisRef); diff --git a/src/coreclr/src/debug/daccess/CMakeLists.txt b/src/coreclr/src/debug/daccess/CMakeLists.txt index 6d18ad64fded8..b683d762885b4 100644 --- a/src/coreclr/src/debug/daccess/CMakeLists.txt +++ b/src/coreclr/src/debug/daccess/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(BEFORE ${VM_DIR}/${ARCH_SOURCES_DIR}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CLR_DIR}/src/debug/ee) include_directories(${CLR_DIR}/src/gcdump) +include_directories(${CLR_DIR}/src/interop/inc) if(CLR_CMAKE_HOST_UNIX) include_directories(${GENERATED_INCLUDE_DIR}) diff --git a/src/coreclr/src/debug/daccess/daccess.cpp b/src/coreclr/src/debug/daccess/daccess.cpp index a05d4f09d0d68..444114587c2ab 100644 --- a/src/coreclr/src/debug/daccess/daccess.cpp +++ b/src/coreclr/src/debug/daccess/daccess.cpp @@ -8252,7 +8252,7 @@ void CALLBACK DacHandleWalker::EnumCallbackSOS(PTR_UNCHECKED_OBJECTREF handle, u if (param->Type == HNDTYPE_DEPENDENT) data.Secondary = GetDependentHandleSecondary(handle.GetAddr()).GetAddr(); #ifdef FEATURE_COMINTEROP - else if (param->Type == HNDTYPE_WEAK_WINRT) + else if (param->Type == HNDTYPE_WEAK_NATIVE_COM) data.Secondary = HndGetHandleExtraInfo(handle.GetAddr()); #endif // FEATURE_COMINTEROP else diff --git a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp index 905698ad4fd71..e3152652fb5f9 100644 --- a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp @@ -7491,8 +7491,8 @@ UINT32 DacRefWalker::GetHandleWalkerMask() if ((mHandleMask & CorHandleWeakRefCount) || (mHandleMask & CorHandleStrongRefCount)) result |= (1 << HNDTYPE_REFCOUNTED); - if (mHandleMask & CorHandleWeakWinRT) - result |= (1 << HNDTYPE_WEAK_WINRT); + if (mHandleMask & CorHandleWeakNativeCom) + result |= (1 << HNDTYPE_WEAK_NATIVE_COM); #endif // FEATURE_COMINTEROP if (mHandleMask & CorHandleStrongDependent) @@ -7667,8 +7667,8 @@ void CALLBACK DacHandleWalker::EnumCallbackDac(PTR_UNCHECKED_OBJECTREF handle, u data.i64ExtraData = refCnt; break; - case HNDTYPE_WEAK_WINRT: - data.dwType = (DWORD)CorHandleWeakWinRT; + case HNDTYPE_WEAK_NATIVE_COM: + data.dwType = (DWORD)CorHandleWeakNativeCom; break; #endif diff --git a/src/coreclr/src/debug/daccess/dacimpl.h b/src/coreclr/src/debug/daccess/dacimpl.h index 958adb1fd9178..29183751fb53e 100644 --- a/src/coreclr/src/debug/daccess/dacimpl.h +++ b/src/coreclr/src/debug/daccess/dacimpl.h @@ -1456,6 +1456,10 @@ class ClrDataAccess PTR_IUnknown DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtableIndex); #endif +#ifdef FEATURE_COMWRAPPERS + HRESULT DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef); +#endif + static LONG s_procInit; public: diff --git a/src/coreclr/src/debug/daccess/enummem.cpp b/src/coreclr/src/debug/daccess/enummem.cpp index 6a3feec6cf9f5..5c5f402b99ad0 100644 --- a/src/coreclr/src/debug/daccess/enummem.cpp +++ b/src/coreclr/src/debug/daccess/enummem.cpp @@ -1298,7 +1298,7 @@ HRESULT ClrDataAccess::EnumMemDumpAllThreadsStack(CLRDataEnumMemoryFlags flags) } -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // WinRT stowed exception holds the (CCW)pointer to a managed exception object. @@ -1431,11 +1431,26 @@ HRESULT ClrDataAccess::DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, C if (ccwPtr == NULL) return S_OK; + OBJECTREF managedExceptionObject = NULL; + +#ifdef FEATURE_COMINTEROP // dump the managed exception object wrapped in CCW // memory of the CCW object itself is dumped later by DacInstanceManager::DumpAllInstances DacpCCWData ccwData; GetCCWData(ccwPtr, &ccwData); // this call collects some memory implicitly - DumpManagedExcepObject(flags, OBJECTREF(TO_TADDR(ccwData.managedObject))); + managedExceptionObject = OBJECTREF(CLRDATA_ADDRESS_TO_TADDR(ccwData.managedObject)); +#endif +#ifdef FEATURE_COMWRAPPERS + if (managedExceptionObject == NULL) + { + OBJECTREF wrappedObjAddress; + if (DACTryGetComWrappersObjectFromCCW(ccwPtr, &wrappedObjAddress) == S_OK) + { + managedExceptionObject = wrappedObjAddress; + } + } +#endif + DumpManagedExcepObject(flags, managedExceptionObject); // dump memory of the 2nd slot in the CCW's vtable // this is used in DACGetCCWFromAddress to identify if the passed in pointer is a valid CCW. @@ -1450,7 +1465,8 @@ HRESULT ClrDataAccess::DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, C CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED ( - ReportMem(vTableAddress + sizeof(PBYTE)* TEAR_OFF_SLOT, sizeof(TADDR)); + ReportMem(vTableAddress, sizeof(TADDR)); // Report the QI slot on the vtable for ComWrappers + ReportMem(vTableAddress + sizeof(PBYTE) * TEAR_OFF_SLOT, sizeof(TADDR)); // Report the AddRef slot on the vtable for built-in CCWs ); return S_OK; diff --git a/src/coreclr/src/debug/daccess/request.cpp b/src/coreclr/src/debug/daccess/request.cpp index 2be663ebd77ea..8fc4896abdcd1 100644 --- a/src/coreclr/src/debug/daccess/request.cpp +++ b/src/coreclr/src/debug/daccess/request.cpp @@ -20,6 +20,8 @@ #include #endif // FEATURE_COMINTEROP +#include + #ifndef TARGET_UNIX // It is unfortunate having to include this header just to get the definition of GenericModeBlock #include @@ -3253,7 +3255,7 @@ HRESULT ClrDataAccess::GetHandleEnum(ISOSHandleEnum **ppHandleEnum) unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_VARIABLE, HNDTYPE_DEPENDENT, HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, #ifdef FEATURE_COMINTEROP - HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_WINRT + HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_NATIVE_COM #endif }; @@ -3291,7 +3293,7 @@ HRESULT ClrDataAccess::GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppH unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_VARIABLE, HNDTYPE_DEPENDENT, HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, #ifdef FEATURE_COMINTEROP - HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_WINRT + HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_NATIVE_COM #endif }; @@ -4065,6 +4067,76 @@ PTR_IUnknown ClrDataAccess::DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtab } #endif +#ifdef FEATURE_COMWRAPPERS +HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef) +{ + if (ccwPtr == 0 || objRef == NULL) + return E_INVALIDARG; + + SOSDacEnter(); + + // Read CCWs QI address and compare it to the managed object wrapper's implementation. + ULONG32 bytesRead = 0; + TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr); + TADDR vTableAddress = NULL; + IfFailGo(m_pTarget->ReadVirtual(ccw, (PBYTE)&vTableAddress, sizeof(TADDR), &bytesRead)); + if (bytesRead != sizeof(TADDR) + || vTableAddress == NULL) + { + hr = E_FAIL; + goto ErrExit; + } + + TADDR qiAddress = NULL; + IfFailGo(m_pTarget->ReadVirtual(vTableAddress, (PBYTE)&qiAddress, sizeof(TADDR), &bytesRead)); + if (bytesRead != sizeof(TADDR) + || qiAddress == NULL) + { + hr = E_FAIL; + goto ErrExit; + } + + +#ifdef TARGET_ARM + // clear the THUMB bit on qiAddress before comparing with known vtable entry + qiAddress &= ~THUMB_CODE; +#endif + + if (qiAddress != GetEEFuncEntryPoint(ManagedObjectWrapper_QueryInterface)) + { + hr = E_FAIL; + goto ErrExit; + } + + // Mask the "dispatch pointer" to get a double pointer to the ManagedObjectWrapper + TADDR managedObjectWrapperPtrPtr = ccw & InteropLib::ABI::DispatchThisPtrMask; + + // Return ManagedObjectWrapper as an OBJECTHANDLE. (The OBJECTHANDLE is guaranteed to live at offset 0). + TADDR managedObjectWrapperPtr; + IfFailGo(m_pTarget->ReadVirtual(managedObjectWrapperPtrPtr, (PBYTE)&managedObjectWrapperPtr, sizeof(TADDR), &bytesRead)); + if (bytesRead != sizeof(TADDR)) + { + hr = E_FAIL; + goto ErrExit; + } + + OBJECTHANDLE handle; + IfFailGo(m_pTarget->ReadVirtual(managedObjectWrapperPtr, (PBYTE)&handle, sizeof(OBJECTHANDLE), &bytesRead)); + if (bytesRead != sizeof(OBJECTHANDLE)) + { + hr = E_FAIL; + goto ErrExit; + } + + *objRef = ObjectFromHandle(handle); + + SOSDacLeave(); + + return S_OK; + +ErrExit: return hr; +} +#endif HRESULT ClrDataAccess::GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *ccwData) { diff --git a/src/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp b/src/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp index e70f35884f510..046350317cde1 100644 --- a/src/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp +++ b/src/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp @@ -12,13 +12,20 @@ #include "diagnosticsipc.h" #include "processdescriptor.h" -IpcStream::DiagnosticsIpc::DiagnosticsIpc(const int serverSocket, sockaddr_un *const pServerAddress) : +#if __GNUC__ + #include +#else + #include +#endif // __GNUC__ + +IpcStream::DiagnosticsIpc::DiagnosticsIpc(const int serverSocket, sockaddr_un *const pServerAddress, ConnectionMode mode) : + mode(mode), _serverSocket(serverSocket), _pServerAddress(new sockaddr_un), - _isClosed(false) + _isClosed(false), + _isListening(false) { _ASSERTE(_pServerAddress != nullptr); - _ASSERTE(_serverSocket != -1); _ASSERTE(pServerAddress != nullptr); if (_pServerAddress == nullptr || pServerAddress == nullptr) @@ -32,24 +39,8 @@ IpcStream::DiagnosticsIpc::~DiagnosticsIpc() delete _pServerAddress; } -IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ErrorCallback callback) +IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ConnectionMode mode, ErrorCallback callback) { -#ifdef __APPLE__ - mode_t prev_mask = umask(~(S_IRUSR | S_IWUSR)); // This will set the default permission bit to 600 -#endif // __APPLE__ - - const int serverSocket = ::socket(AF_UNIX, SOCK_STREAM, 0); - if (serverSocket == -1) - { - if (callback != nullptr) - callback(strerror(errno), errno); -#ifdef __APPLE__ - umask(prev_mask); -#endif // __APPLE__ - _ASSERTE(!"Failed to create diagnostics IPC socket."); - return nullptr; - } - sockaddr_un serverAddress{}; serverAddress.sun_family = AF_UNIX; @@ -71,6 +62,24 @@ IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const p "socket"); } + if (mode == ConnectionMode::CLIENT) + return new IpcStream::DiagnosticsIpc(-1, &serverAddress, ConnectionMode::CLIENT); + +#ifdef __APPLE__ + mode_t prev_mask = umask(~(S_IRUSR | S_IWUSR)); // This will set the default permission bit to 600 +#endif // __APPLE__ + + const int serverSocket = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (serverSocket == -1) + { + if (callback != nullptr) + callback(strerror(errno), errno); +#ifdef __APPLE__ + umask(prev_mask); +#endif // __APPLE__ + _ASSERTE(!"Failed to create diagnostics IPC socket."); + return nullptr; + } #ifndef __APPLE__ if (fchmod(serverSocket, S_IRUSR | S_IWUSR) == -1) @@ -99,33 +108,52 @@ IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const p return nullptr; } - const int fSuccessfulListen = ::listen(serverSocket, /* backlog */ 255); +#ifdef __APPLE__ + umask(prev_mask); +#endif // __APPLE__ + + return new IpcStream::DiagnosticsIpc(serverSocket, &serverAddress, mode); +} + +bool IpcStream::DiagnosticsIpc::Listen(ErrorCallback callback) +{ + _ASSERTE(mode == ConnectionMode::SERVER); + if (mode != ConnectionMode::SERVER) + { + if (callback != nullptr) + callback("Cannot call Listen on a client connection", -1); + return false; + } + + if (_isListening) + return true; + + const int fSuccessfulListen = ::listen(_serverSocket, /* backlog */ 255); if (fSuccessfulListen == -1) { if (callback != nullptr) callback(strerror(errno), errno); _ASSERTE(fSuccessfulListen != -1); - const int fSuccessUnlink = ::unlink(serverAddress.sun_path); + const int fSuccessUnlink = ::unlink(_pServerAddress->sun_path); _ASSERTE(fSuccessUnlink != -1); - const int fSuccessClose = ::close(serverSocket); + const int fSuccessClose = ::close(_serverSocket); _ASSERTE(fSuccessClose != -1); -#ifdef __APPLE__ - umask(prev_mask); -#endif // __APPLE__ - return nullptr; + return false; + } + else + { + _isListening = true; + return true; } - -#ifdef __APPLE__ - umask(prev_mask); -#endif // __APPLE__ - - return new IpcStream::DiagnosticsIpc(serverSocket, &serverAddress); } -IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const +IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) { + _ASSERTE(mode == ConnectionMode::SERVER); + _ASSERTE(_isListening); + sockaddr_un from; socklen_t fromlen = sizeof(from); const int clientSocket = ::accept(_serverSocket, (sockaddr *)&from, &fromlen); @@ -136,10 +164,117 @@ IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const return nullptr; } - return new IpcStream(clientSocket); + return new IpcStream(clientSocket, mode); +} + +IpcStream *IpcStream::DiagnosticsIpc::Connect(ErrorCallback callback) +{ + _ASSERTE(mode == ConnectionMode::CLIENT); + + sockaddr_un clientAddress{}; + clientAddress.sun_family = AF_UNIX; + const int clientSocket = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (clientSocket == -1) + { + if (callback != nullptr) + callback(strerror(errno), errno); + return nullptr; + } + + // We don't expect this to block since this is a Unix Domain Socket. `connect` may block until the + // TCP handshake is complete for TCP/IP sockets, but UDS don't use TCP. `connect` will return even if + // the server hasn't called `accept`. + if (::connect(clientSocket, (struct sockaddr *)_pServerAddress, sizeof(*_pServerAddress)) < 0) + { + if (callback != nullptr) + callback(strerror(errno), errno); + return nullptr; + } + + return new IpcStream(clientSocket, ConnectionMode::CLIENT); } -void IpcStream::DiagnosticsIpc::Close(ErrorCallback callback) +int32_t IpcStream::DiagnosticsIpc::Poll(IpcPollHandle *rgIpcPollHandles, uint32_t nHandles, int32_t timeoutMs, ErrorCallback callback) +{ + // prepare the pollfd structs + pollfd *pollfds = new pollfd[nHandles]; + for (uint32_t i = 0; i < nHandles; i++) + { + rgIpcPollHandles[i].revents = 0; // ignore any values in revents + int fd = -1; + if (rgIpcPollHandles[i].pIpc != nullptr) + { + // SERVER + _ASSERTE(rgIpcPollHandles[i].pIpc->mode == ConnectionMode::SERVER); + fd = rgIpcPollHandles[i].pIpc->_serverSocket; + } + else + { + // CLIENT + _ASSERTE(rgIpcPollHandles[i].pStream != nullptr); + fd = rgIpcPollHandles[i].pStream->_clientSocket; + } + + pollfds[i].fd = fd; + pollfds[i].events = POLLIN; + } + + int retval = poll(pollfds, nHandles, timeoutMs); + + // Check results + if (retval < 0) + { + for (uint32_t i = 0; i < nHandles; i++) + { + if ((pollfds[i].revents & POLLERR) && callback != nullptr) + callback(strerror(errno), errno); + rgIpcPollHandles[i].revents = (uint8_t)PollEvents::ERR; + } + delete[] pollfds; + return -1; + } + else if (retval == 0) + { + // we timed out + delete[] pollfds; + return 0; + } + + for (uint32_t i = 0; i < nHandles; i++) + { + if (pollfds[i].revents != 0) + { + // error check FIRST + if (pollfds[i].revents & POLLHUP) + { + // check for hangup first because a closed socket + // will technically meet the requirements for POLLIN + // i.e., a call to recv/read won't block + rgIpcPollHandles[i].revents = (uint8_t)PollEvents::HANGUP; + delete[] pollfds; + return -1; + } + else if ((pollfds[i].revents & (POLLERR|POLLNVAL))) + { + if (callback != nullptr) + callback("Poll error", (uint32_t)pollfds[i].revents); + rgIpcPollHandles[i].revents = (uint8_t)PollEvents::ERR; + delete[] pollfds; + return -1; + } + else if (pollfds[i].revents & POLLIN) + { + rgIpcPollHandles[i].revents = (uint8_t)PollEvents::SIGNALED; + break; + } + } + } + + delete[] pollfds; + return 1; +} + +void IpcStream::DiagnosticsIpc::Close(bool isShutdown, ErrorCallback callback) { if (_isClosed) return; @@ -147,13 +282,19 @@ void IpcStream::DiagnosticsIpc::Close(ErrorCallback callback) if (_serverSocket != -1) { - if (::close(_serverSocket) == -1) + // only close the socket if not shutting down, let the OS handle it in that case + if (!isShutdown && ::close(_serverSocket) == -1) { if (callback != nullptr) callback(strerror(errno), errno); _ASSERTE(!"Failed to close unix domain socket."); } + // N.B. - it is safe to unlink the unix domain socket file while the server + // is still alive: + // "The usual UNIX close-behind semantics apply; the socket can be unlinked + // at any time and will be finally removed from the file system when the last + // reference to it is closed." - unix(7) man page Unlink(callback); } } @@ -172,6 +313,11 @@ void IpcStream::DiagnosticsIpc::Unlink(ErrorCallback callback) } IpcStream::~IpcStream() +{ + Close(); +} + +void IpcStream::Close(ErrorCallback) { if (_clientSocket != -1) { @@ -179,38 +325,89 @@ IpcStream::~IpcStream() const int fSuccessClose = ::close(_clientSocket); _ASSERTE(fSuccessClose != -1); + _clientSocket = -1; } } -bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead) const +bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead, const int32_t timeoutMs) { _ASSERTE(lpBuffer != nullptr); - const ssize_t ssize = ::recv(_clientSocket, lpBuffer, nBytesToRead, 0); - const bool fSuccess = ssize != -1; + if (timeoutMs != InfiniteTimeout) + { + pollfd pfd; + pfd.fd = _clientSocket; + pfd.events = POLLIN; + int retval = poll(&pfd, 1, timeoutMs); + if (retval <= 0 || pfd.revents != POLLIN) + { + // timeout or error + return false; + } + // else fallthrough + } + + uint8_t *lpBufferCursor = (uint8_t*)lpBuffer; + ssize_t currentBytesRead = 0; + ssize_t totalBytesRead = 0; + bool fSuccess = true; + while (fSuccess && nBytesToRead - totalBytesRead > 0) + { + currentBytesRead = ::recv(_clientSocket, lpBufferCursor, nBytesToRead - totalBytesRead, 0); + fSuccess = currentBytesRead != 0; + if (!fSuccess) + break; + totalBytesRead += currentBytesRead; + lpBufferCursor += currentBytesRead; + } if (!fSuccess) { // TODO: Add error handling. } - nBytesRead = static_cast(ssize); + nBytesRead = static_cast(totalBytesRead); return fSuccess; } -bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const +bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten, const int32_t timeoutMs) { _ASSERTE(lpBuffer != nullptr); - const ssize_t ssize = ::send(_clientSocket, lpBuffer, nBytesToWrite, 0); - const bool fSuccess = ssize != -1; + if (timeoutMs != InfiniteTimeout) + { + pollfd pfd; + pfd.fd = _clientSocket; + pfd.events = POLLOUT; + int retval = poll(&pfd, 1, timeoutMs); + if (retval <= 0 || pfd.revents != POLLOUT) + { + // timeout or error + return false; + } + // else fallthrough + } + + uint8_t *lpBufferCursor = (uint8_t*)lpBuffer; + ssize_t currentBytesWritten = 0; + ssize_t totalBytesWritten = 0; + bool fSuccess = true; + while (fSuccess && nBytesToWrite - totalBytesWritten > 0) + { + currentBytesWritten = ::send(_clientSocket, lpBufferCursor, nBytesToWrite - totalBytesWritten, 0); + fSuccess = currentBytesWritten != -1; + if (!fSuccess) + break; + lpBufferCursor += currentBytesWritten; + totalBytesWritten += currentBytesWritten; + } if (!fSuccess) { // TODO: Add error handling. } - nBytesWritten = static_cast(ssize); + nBytesWritten = static_cast(totalBytesWritten); return fSuccess; } diff --git a/src/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp b/src/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp index 36c11857cabe9..f7b41b92fc1e6 100644 --- a/src/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp +++ b/src/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp @@ -7,9 +7,14 @@ #include #include "diagnosticsipc.h" -IpcStream::DiagnosticsIpc::DiagnosticsIpc(const char(&namedPipeName)[MaxNamedPipeNameLength]) +#define _ASSERTE assert + +IpcStream::DiagnosticsIpc::DiagnosticsIpc(const char(&namedPipeName)[MaxNamedPipeNameLength], ConnectionMode mode) : + mode(mode), + _isListening(false) { memcpy(_pNamedPipeName, namedPipeName, sizeof(_pNamedPipeName)); + memset(&_oOverlap, 0, sizeof(OVERLAPPED)); } IpcStream::DiagnosticsIpc::~DiagnosticsIpc() @@ -17,7 +22,7 @@ IpcStream::DiagnosticsIpc::~DiagnosticsIpc() Close(); } -IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ErrorCallback callback) +IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ConnectionMode mode, ErrorCallback callback) { char namedPipeName[MaxNamedPipeNameLength]{}; int nCharactersWritten = -1; @@ -43,20 +48,32 @@ IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const p { if (callback != nullptr) callback("Failed to generate the named pipe name", nCharactersWritten); - assert(nCharactersWritten != -1); + _ASSERTE(nCharactersWritten != -1); return nullptr; } - return new IpcStream::DiagnosticsIpc(namedPipeName); + return new IpcStream::DiagnosticsIpc(namedPipeName, mode); } -IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const +bool IpcStream::DiagnosticsIpc::Listen(ErrorCallback callback) { + _ASSERTE(mode == ConnectionMode::SERVER); + if (mode != ConnectionMode::SERVER) + { + if (callback != nullptr) + callback("Cannot call Listen on a client connection", -1); + return false; + } + + if (_isListening) + return true; + const uint32_t nInBufferSize = 16 * 1024; const uint32_t nOutBufferSize = 16 * 1024; - HANDLE hPipe = ::CreateNamedPipeA( + _hPipe = ::CreateNamedPipeA( _pNamedPipeName, // pipe name - PIPE_ACCESS_DUPLEX, // read/write access + PIPE_ACCESS_DUPLEX | // read/write access + FILE_FLAG_OVERLAPPED, // async listening PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, // message type pipe, message-read and blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances nOutBufferSize, // output buffer size @@ -64,19 +81,32 @@ IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const 0, // default client time-out NULL); // default security attribute - if (hPipe == INVALID_HANDLE_VALUE) + if (_hPipe == INVALID_HANDLE_VALUE) { if (callback != nullptr) callback("Failed to create an instance of a named pipe.", ::GetLastError()); - return nullptr; + return false; } - const BOOL fSuccess = ::ConnectNamedPipe(hPipe, NULL) != 0; + HANDLE hOverlapEvent = CreateEvent(NULL, true, false, NULL); + if (hOverlapEvent == NULL) + { + if (callback != nullptr) + callback("Failed to create overlap event", ::GetLastError()); + ::CloseHandle(_hPipe); + _hPipe = INVALID_HANDLE_VALUE; + return false; + } + _oOverlap.hEvent = hOverlapEvent; + + BOOL fSuccess = ::ConnectNamedPipe(_hPipe, &_oOverlap) != 0; if (!fSuccess) { const DWORD errorCode = ::GetLastError(); switch (errorCode) { + case ERROR_IO_PENDING: + // There was a pending connection that can be waited on (will happen in poll) case ERROR_PIPE_CONNECTED: // Occurs when a client connects before the function is called. // In this case, there is a connection between client and @@ -86,46 +116,333 @@ IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const default: if (callback != nullptr) callback("A client process failed to connect.", errorCode); - ::CloseHandle(hPipe); - return nullptr; + ::CloseHandle(_hPipe); + _hPipe = INVALID_HANDLE_VALUE; + ::CloseHandle(_oOverlap.hEvent); + _oOverlap.hEvent = INVALID_HANDLE_VALUE; + return false; + } + } + + _isListening = true; + return true; +} + +IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) +{ + _ASSERTE(_isListening); + _ASSERTE(mode == ConnectionMode::SERVER); + + DWORD dwDummy = 0; + bool fSuccess = GetOverlappedResult( + _hPipe, // handle + &_oOverlap, // overlapped + &dwDummy, // throw-away dword + true); // wait till event signals + + if (!fSuccess) + { + if (callback != nullptr) + callback("Failed to GetOverlappedResults for NamedPipe server", ::GetLastError()); + return nullptr; + } + + // create new IpcStream using handle and reset the Server object so it can listen again + IpcStream *pStream = new IpcStream(_hPipe, ConnectionMode::SERVER); + + // reset the server + _hPipe = INVALID_HANDLE_VALUE; + _isListening = false; + ::CloseHandle(_oOverlap.hEvent); + memset(&_oOverlap, 0, sizeof(OVERLAPPED)); // clear the overlapped objects state + fSuccess = Listen(callback); + if (!fSuccess) + { + delete pStream; + return nullptr; + } + + return pStream; +} + +IpcStream *IpcStream::DiagnosticsIpc::Connect(ErrorCallback callback) +{ + _ASSERTE(mode == ConnectionMode::CLIENT); + if (mode != ConnectionMode::CLIENT) + { + if (callback != nullptr) + callback("Cannot call connect on a server connection", 0); + return nullptr; + } + + HANDLE hPipe = ::CreateFileA( + _pNamedPipeName, // pipe name + PIPE_ACCESS_DUPLEX, // read/write access + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // Overlapped + NULL); // no template file + + if (hPipe == INVALID_HANDLE_VALUE) + { + if (callback != nullptr) + callback("Failed to connect to named pipe.", ::GetLastError()); + return nullptr; + } + + return new IpcStream(hPipe, mode); +} + +void IpcStream::DiagnosticsIpc::Close(bool isShutdown, ErrorCallback) +{ + // don't attempt cleanup on shutdown and let the OS handle it + if (isShutdown) + return; + + if (_hPipe != INVALID_HANDLE_VALUE) + { + if (mode == DiagnosticsIpc::ConnectionMode::SERVER) + { + const BOOL fSuccessDisconnectNamedPipe = ::DisconnectNamedPipe(_hPipe); + _ASSERTE(fSuccessDisconnectNamedPipe != 0); } + + const BOOL fSuccessCloseHandle = ::CloseHandle(_hPipe); + _ASSERTE(fSuccessCloseHandle != 0); } - return new IpcStream(hPipe); + if (_oOverlap.hEvent != INVALID_HANDLE_VALUE) + { + ::CloseHandle(_oOverlap.hEvent); + } } -void IpcStream::DiagnosticsIpc::Close(ErrorCallback) +IpcStream::IpcStream(HANDLE hPipe, DiagnosticsIpc::ConnectionMode mode) : + _hPipe(hPipe), + _mode(mode) { + memset(&_oOverlap, 0, sizeof(OVERLAPPED)); + _oOverlap.hEvent = CreateEvent(NULL, true, false, NULL); } IpcStream::~IpcStream() +{ + Close(); +} + +void IpcStream::Close(ErrorCallback) { if (_hPipe != INVALID_HANDLE_VALUE) { Flush(); - const BOOL fSuccessDisconnectNamedPipe = ::DisconnectNamedPipe(_hPipe); - assert(fSuccessDisconnectNamedPipe != 0); + if (_mode == DiagnosticsIpc::ConnectionMode::SERVER) + { + const BOOL fSuccessDisconnectNamedPipe = ::DisconnectNamedPipe(_hPipe); + _ASSERTE(fSuccessDisconnectNamedPipe != 0); + } const BOOL fSuccessCloseHandle = ::CloseHandle(_hPipe); - assert(fSuccessCloseHandle != 0); + _ASSERTE(fSuccessCloseHandle != 0); + } + + if (_oOverlap.hEvent != INVALID_HANDLE_VALUE) + { + ::CloseHandle(_oOverlap.hEvent); + } +} + +int32_t IpcStream::DiagnosticsIpc::Poll(IpcPollHandle *rgIpcPollHandles, uint32_t nHandles, int32_t timeoutMs, ErrorCallback callback) +{ + // load up an array of handles + HANDLE *pHandles = new HANDLE[nHandles]; + for (uint32_t i = 0; i < nHandles; i++) + { + rgIpcPollHandles[i].revents = 0; // ignore any inputs on revents + if (rgIpcPollHandles[i].pIpc != nullptr) + { + // SERVER + _ASSERTE(rgIpcPollHandles[i].pIpc->mode == DiagnosticsIpc::ConnectionMode::SERVER); + pHandles[i] = rgIpcPollHandles[i].pIpc->_oOverlap.hEvent; + } + else + { + // CLIENT + bool fSuccess = false; + DWORD dwDummy = 0; + if (!rgIpcPollHandles[i].pStream->_isTestReading) + { + // check for data by doing an asynchronous 0 byte read. + // This will signal if the pipe closes (hangup) or the server + // sends new data + fSuccess = ::ReadFile( + rgIpcPollHandles[i].pStream->_hPipe, // handle + nullptr, // null buffer + 0, // read 0 bytes + &dwDummy, // dummy variable + &rgIpcPollHandles[i].pStream->_oOverlap); // overlap object to use + rgIpcPollHandles[i].pStream->_isTestReading = true; + if (!fSuccess) + { + DWORD error = ::GetLastError(); + switch (error) + { + case ERROR_IO_PENDING: + pHandles[i] = rgIpcPollHandles[i].pStream->_oOverlap.hEvent; + break; + case ERROR_PIPE_NOT_CONNECTED: + // hangup + rgIpcPollHandles[i].revents = (uint8_t)PollEvents::HANGUP; + delete[] pHandles; + return -1; + default: + if (callback != nullptr) + callback("0 byte async read on client connection failed", error); + delete[] pHandles; + return -1; + } + } + } + else + { + pHandles[i] = rgIpcPollHandles[i].pStream->_oOverlap.hEvent; + } + } + } + + // call wait for multiple obj + DWORD dwWait = WaitForMultipleObjects( + nHandles, // count + pHandles, // handles + false, // Don't wait-all + timeoutMs); + + if (dwWait == WAIT_TIMEOUT) + { + // we timed out + delete[] pHandles; + return 0; + } + + if (dwWait == WAIT_FAILED) + { + // we errored + if (callback != nullptr) + callback("WaitForMultipleObjects failed", ::GetLastError()); + delete[] pHandles; + return -1; + } + + // determine which of the streams signaled + DWORD index = dwWait - WAIT_OBJECT_0; + // error check the index + if (index < 0 || index > (nHandles - 1)) + { + // check if we abandoned something + DWORD abandonedIndex = dwWait - WAIT_ABANDONED_0; + if (abandonedIndex > 0 || abandonedIndex < (nHandles - 1)) + { + rgIpcPollHandles[abandonedIndex].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::HANGUP; + delete[] pHandles; + return -1; + } + else + { + if (callback != nullptr) + callback("WaitForMultipleObjects failed", ::GetLastError()); + delete[] pHandles; + return -1; + } } + + // Set revents depending on what signaled the stream + if (rgIpcPollHandles[index].pIpc == nullptr) + { + // CLIENT + // check if the connection got hung up + DWORD dwDummy = 0; + bool fSuccess = GetOverlappedResult(rgIpcPollHandles[index].pStream->_hPipe, + &rgIpcPollHandles[index].pStream->_oOverlap, + &dwDummy, + true); + rgIpcPollHandles[index].pStream->_isTestReading = false; + if (!fSuccess) + { + DWORD error = ::GetLastError(); + if (error == ERROR_PIPE_NOT_CONNECTED) + rgIpcPollHandles[index].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::HANGUP; + else + { + if (callback != nullptr) + callback("Client connection error", -1); + rgIpcPollHandles[index].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::ERR; + delete[] pHandles; + return -1; + } + } + else + { + rgIpcPollHandles[index].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::SIGNALED; + } + } + else + { + // SERVER + rgIpcPollHandles[index].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::SIGNALED; + } + + delete[] pHandles; + return 1; } -bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead) const +bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead, const int32_t timeoutMs) { - assert(lpBuffer != nullptr); + _ASSERTE(lpBuffer != nullptr); DWORD nNumberOfBytesRead = 0; - const bool fSuccess = ::ReadFile( + LPOVERLAPPED overlap = &_oOverlap; + bool fSuccess = ::ReadFile( _hPipe, // handle to pipe lpBuffer, // buffer to receive data nBytesToRead, // size of buffer &nNumberOfBytesRead, // number of bytes read - NULL) != 0; // not overlapped I/O + overlap) != 0; // overlapped I/O if (!fSuccess) { + if (timeoutMs == InfiniteTimeout) + { + fSuccess = GetOverlappedResult(_hPipe, + overlap, + &nNumberOfBytesRead, + true) != 0; + } + else + { + DWORD dwError = GetLastError(); + if (dwError == ERROR_IO_PENDING) + { + DWORD dwWait = WaitForSingleObject(_oOverlap.hEvent, (DWORD)timeoutMs); + if (dwWait == WAIT_OBJECT_0) + { + // get the result + fSuccess = GetOverlappedResult(_hPipe, + overlap, + &nNumberOfBytesRead, + true) != 0; + } + else + { + // cancel IO and ensure the cancel happened + if (CancelIo(_hPipe)) + { + // check if the async write beat the cancellation + fSuccess = GetOverlappedResult(_hPipe, overlap, &nNumberOfBytesRead, true) != 0; + } + } + } + } // TODO: Add error handling. } @@ -133,20 +450,54 @@ bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nByt return fSuccess; } -bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const +bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten, const int32_t timeoutMs) { - assert(lpBuffer != nullptr); + _ASSERTE(lpBuffer != nullptr); DWORD nNumberOfBytesWritten = 0; - const bool fSuccess = ::WriteFile( + LPOVERLAPPED overlap = &_oOverlap; + bool fSuccess = ::WriteFile( _hPipe, // handle to pipe lpBuffer, // buffer to write from nBytesToWrite, // number of bytes to write &nNumberOfBytesWritten, // number of bytes written - NULL) != 0; // not overlapped I/O + overlap) != 0; // overlapped I/O if (!fSuccess) { + DWORD dwError = GetLastError(); + if (dwError == ERROR_IO_PENDING) + { + if (timeoutMs == InfiniteTimeout) + { + // if we're waiting infinitely, don't bother with extra kernel call + fSuccess = GetOverlappedResult(_hPipe, + overlap, + &nNumberOfBytesWritten, + true) != 0; + } + else + { + DWORD dwWait = WaitForSingleObject(_oOverlap.hEvent, (DWORD)timeoutMs); + if (dwWait == WAIT_OBJECT_0) + { + // get the result + fSuccess = GetOverlappedResult(_hPipe, + overlap, + &nNumberOfBytesWritten, + true) != 0; + } + else + { + // cancel IO and ensure the cancel happened + if (CancelIo(_hPipe)) + { + // check if the async write beat the cancellation + fSuccess = GetOverlappedResult(_hPipe, overlap, &nNumberOfBytesWritten, true) != 0; + } + } + } + } // TODO: Add error handling. } diff --git a/src/coreclr/src/debug/di/process.cpp b/src/coreclr/src/debug/di/process.cpp index 4e6fe0bf64984..f13e7b9f0eaa1 100644 --- a/src/coreclr/src/debug/di/process.cpp +++ b/src/coreclr/src/debug/di/process.cpp @@ -10990,8 +10990,7 @@ void CordbWin32EventThread::ThreadProc() } // Define a holder that calls code:DeleteIPCEventHelper -NEW_WRAPPER_TEMPLATE1(DeleteIPCEventHolderHelper, DeleteIPCEventHelper); -typedef DeleteIPCEventHolderHelper DeleteIPCEventHolder; +using DeleteIPCEventHolder = SpecializedWrapper; //--------------------------------------------------------------------------------------- // diff --git a/src/coreclr/src/debug/inc/diagnosticsipc.h b/src/coreclr/src/debug/inc/diagnosticsipc.h index eabea6c3ceaea..225299c2b8992 100644 --- a/src/coreclr/src/debug/inc/diagnosticsipc.h +++ b/src/coreclr/src/debug/inc/diagnosticsipc.h @@ -18,24 +18,80 @@ typedef void (*ErrorCallback)(const char *szMessage, uint32_t code); class IpcStream final { public: + static constexpr int32_t InfiniteTimeout = -1; ~IpcStream(); - bool Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead) const; - bool Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const; + bool Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead, const int32_t timeoutMs = IpcStream::InfiniteTimeout); + bool Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten, const int32_t timeoutMs = IpcStream::InfiniteTimeout); bool Flush() const; + void Close(ErrorCallback callback = nullptr); class DiagnosticsIpc final { public: + enum ConnectionMode + { + CLIENT, + SERVER + }; + + enum class PollEvents : uint8_t + { + TIMEOUT = 0x00, // implies timeout + SIGNALED = 0x01, // ready for use + HANGUP = 0x02, // connection remotely closed + ERR = 0x04 // other error + }; + + // The bookeeping struct used for polling on server and client structs + struct IpcPollHandle + { + // Only one of these will be non-null, treat as a union + DiagnosticsIpc *pIpc; + IpcStream *pStream; + + // contains some set of PollEvents + // will be set by Poll + // Any values here are ignored by Poll + uint8_t revents; + + // a cookie assignable by upstream users for additional bookkeeping + void *pUserData; + }; + + // Poll + // Parameters: + // - IpcPollHandle * rgpIpcPollHandles: Array of IpcPollHandles to poll + // - uint32_t nHandles: The number of handles to poll + // - int32_t timeoutMs: The timeout in milliseconds for the poll (-1 == infinite) + // Returns: + // int32_t: -1 on error, 0 on timeout, >0 on successful poll + // Remarks: + // Check the events returned in revents for each IpcPollHandle to find the signaled handle. + // Signaled DiagnosticsIpcs can call Accept() without blocking. + // Signaled IpcStreams can call Read(...) without blocking. + // The caller is responsible for cleaning up "hung up" connections. + static int32_t Poll(IpcPollHandle *rgIpcPollHandles, uint32_t nHandles, int32_t timeoutMs, ErrorCallback callback = nullptr); + + ConnectionMode mode; + ~DiagnosticsIpc(); - //! Creates an IPC object - static DiagnosticsIpc *Create(const char *const pIpcName, ErrorCallback callback = nullptr); + // Creates an IPC object + static DiagnosticsIpc *Create(const char *const pIpcName, ConnectionMode mode, ErrorCallback callback = nullptr); + + // puts the DiagnosticsIpc into Listening Mode + // Re-entrant safe + bool Listen(ErrorCallback callback = nullptr); + + // produces a connected stream from a server-mode DiagnosticsIpc. Blocks until a connection is available. + IpcStream *Accept(ErrorCallback callback = nullptr); - //! Enables the underlaying IPC implementation to accept connection. - IpcStream *Accept(ErrorCallback callback = nullptr) const; + // Connect to a server and returns a connected stream + IpcStream *Connect(ErrorCallback callback = nullptr); - //! Closes an open IPC. - void Close(ErrorCallback callback = nullptr); + // Closes an open IPC. + // Only attempts minimal cleanup if isShutdown==true, i.e., unlinks Unix Domain Socket on Linux, no-op on Windows + void Close(bool isShutdown = false, ErrorCallback callback = nullptr); private: @@ -44,18 +100,22 @@ class IpcStream final sockaddr_un *const _pServerAddress; bool _isClosed; - DiagnosticsIpc(const int serverSocket, sockaddr_un *const pServerAddress); + DiagnosticsIpc(const int serverSocket, sockaddr_un *const pServerAddress, ConnectionMode mode = ConnectionMode::SERVER); - //! Used to unlink the socket so it can be removed from the filesystem - //! when the last reference to it is closed. + // Used to unlink the socket so it can be removed from the filesystem + // when the last reference to it is closed. void Unlink(ErrorCallback callback = nullptr); #else static const uint32_t MaxNamedPipeNameLength = 256; char _pNamedPipeName[MaxNamedPipeNameLength]; // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createnamedpipea + HANDLE _hPipe = INVALID_HANDLE_VALUE; + OVERLAPPED _oOverlap = {}; - DiagnosticsIpc(const char(&namedPipeName)[MaxNamedPipeNameLength]); + DiagnosticsIpc(const char(&namedPipeName)[MaxNamedPipeNameLength], ConnectionMode mode = ConnectionMode::SERVER); #endif /* TARGET_UNIX */ + bool _isListening; + DiagnosticsIpc() = delete; DiagnosticsIpc(const DiagnosticsIpc &src) = delete; DiagnosticsIpc(DiagnosticsIpc &&src) = delete; @@ -66,12 +126,17 @@ class IpcStream final private: #ifdef TARGET_UNIX int _clientSocket = -1; - IpcStream(int clientSocket) : _clientSocket(clientSocket) {} + IpcStream(int clientSocket, int serverSocket, DiagnosticsIpc::ConnectionMode mode = DiagnosticsIpc::ConnectionMode::SERVER) + : _clientSocket(clientSocket), _mode(mode) {} #else HANDLE _hPipe = INVALID_HANDLE_VALUE; - IpcStream(HANDLE hPipe) : _hPipe(hPipe) {} + OVERLAPPED _oOverlap = {}; + BOOL _isTestReading = false; // used to check whether we are already doing a 0-byte read to test for data + IpcStream(HANDLE hPipe, DiagnosticsIpc::ConnectionMode mode = DiagnosticsIpc::ConnectionMode::SERVER); #endif /* TARGET_UNIX */ + DiagnosticsIpc::ConnectionMode _mode; + IpcStream() = delete; IpcStream(const IpcStream &src) = delete; IpcStream(IpcStream &&src) = delete; diff --git a/src/coreclr/src/dlls/dbgshim/CMakeLists.txt b/src/coreclr/src/dlls/dbgshim/CMakeLists.txt index 8f3ef4a3330c1..ef2d0e360782b 100644 --- a/src/coreclr/src/dlls/dbgshim/CMakeLists.txt +++ b/src/coreclr/src/dlls/dbgshim/CMakeLists.txt @@ -26,25 +26,24 @@ else(CLR_CMAKE_TARGET_WIN32) generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE}) endif(CLR_CMAKE_TARGET_WIN32) -if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) +if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) # This option is necessary to ensure that the overloaded delete operator defined inside # of the utilcode will be used instead of the standard library delete operator. set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic") # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) + if(CLR_CMAKE_HOST_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) + else(CLR_CMAKE_HOST_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) + endif(CLR_CMAKE_HOST_SUNOS) +endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) if(CLR_CMAKE_HOST_OSX) # Add linker exports file option set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${EXPORTS_FILE}) endif(CLR_CMAKE_HOST_OSX) -if(CLR_CMAKE_HOST_SUNOS) - # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_SUNOS) - add_library_clr(dbgshim SHARED ${DBGSHIM_SOURCES}) if(CLR_CMAKE_HOST_UNIX) diff --git a/src/coreclr/src/dlls/mscordac/CMakeLists.txt b/src/coreclr/src/dlls/mscordac/CMakeLists.txt index d005acc8c5a74..ddf66b4a0d45b 100644 --- a/src/coreclr/src/dlls/mscordac/CMakeLists.txt +++ b/src/coreclr/src/dlls/mscordac/CMakeLists.txt @@ -73,7 +73,7 @@ else(CLR_CMAKE_HOST_WIN32) endif(CLR_CMAKE_HOST_LINUX) endif(CLR_CMAKE_HOST_WIN32) -if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) +if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) # This option is necessary to ensure that the overloaded delete operator defined inside # of the utilcode will be used instead of the standard library delete operator. set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic") @@ -88,19 +88,18 @@ if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive) # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) + if(CLR_CMAKE_HOST_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) + else(CLR_CMAKE_HOST_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) + endif(CLR_CMAKE_HOST_SUNOS) +endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) if(CLR_CMAKE_HOST_OSX) # Add linker exports file option set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${EXPORTS_FILE}) endif(CLR_CMAKE_HOST_OSX) -if(CLR_CMAKE_HOST_SUNOS) - # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_SUNOS) - # Create object library to enable creation of proper dependency of mscordaccore.exp on mscordac.obj and # mscordaccore on both the mscordaccore.exp and mscordac.obj. _add_library(mscordacobj OBJECT mscordac.cpp) diff --git a/src/coreclr/src/dlls/mscordbi/CMakeLists.txt b/src/coreclr/src/dlls/mscordbi/CMakeLists.txt index 6a54e77733246..ffd48ee489aba 100644 --- a/src/coreclr/src/dlls/mscordbi/CMakeLists.txt +++ b/src/coreclr/src/dlls/mscordbi/CMakeLists.txt @@ -41,25 +41,24 @@ else(CLR_CMAKE_HOST_WIN32) generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE}) endif(CLR_CMAKE_HOST_WIN32) -if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) +if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) # This option is necessary to ensure that the overloaded new/delete operators defined inside # of the utilcode will be used instead of the standard library delete operator. set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic") # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD) + if(CLR_CMAKE_HOST_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) + else(CLR_CMAKE_HOST_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) + endif(CLR_CMAKE_HOST_SUNOS) +endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) if(CLR_CMAKE_HOST_OSX) # Add linker exports file option set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${EXPORTS_FILE}) endif(CLR_CMAKE_HOST_OSX) -if(CLR_CMAKE_HOST_SUNOS) - # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_SUNOS) - add_library_clr(mscordbi SHARED ${MSCORDBI_SOURCES}) target_precompile_header(TARGET mscordbi HEADER stdafx.h) diff --git a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt index 4358d79669b45..918fbf27a6848 100644 --- a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt @@ -32,7 +32,7 @@ else(CLR_CMAKE_HOST_WIN32) set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/coreclr.exports) generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE}) - if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD OR CLR_CMAKE_TARGET_SUNOS) # This option is necessary to ensure that the overloaded delete operator defined inside # of the utilcode will be used instead of the standard library delete operator. add_link_options("LINKER:-Bsymbolic") @@ -46,8 +46,12 @@ else(CLR_CMAKE_HOST_WIN32) set(START_WHOLE_ARCHIVE -Wl,--whole-archive) set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive) - set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) - endif(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + if(CLR_CMAKE_TARGET_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) + elseif(CLR_CMAKE_TARGET_SUNOS) + set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) + endif(CLR_CMAKE_TARGET_SUNOS) + endif(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD OR CLR_CMAKE_TARGET_SUNOS) if(CLR_CMAKE_TARGET_OSX) # These options are used to force every object to be included even if it's unused. @@ -61,11 +65,6 @@ else(CLR_CMAKE_HOST_WIN32) set(EXPORTS_LINKER_OPTION "${EXPORTS_LINKER_OPTION} -Wl,--no-warn-shared-textrel") endif(CLR_CMAKE_TARGET_ANDROID AND CLR_CMAKE_HOST_ARCH_ARM) - if(CLR_CMAKE_HOST_SUNOS) - # Add linker exports file option - set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) - endif(CLR_CMAKE_HOST_SUNOS) - endif (CLR_CMAKE_HOST_WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=CoreCLR.dll) @@ -151,6 +150,10 @@ if(CLR_CMAKE_TARGET_LINUX) tracepointprovider ${END_WHOLE_ARCHIVE} ) +elseif(CLR_CMAKE_TARGET_SUNOS) + list(APPEND CORECLR_LIBRARIES + socket + ) endif(CLR_CMAKE_TARGET_LINUX) if(FEATURE_PERFTRACING) diff --git a/src/coreclr/src/dlls/mscoree/unixinterface.cpp b/src/coreclr/src/dlls/mscoree/unixinterface.cpp index f54e7c7be0604..ca4d452a8edae 100644 --- a/src/coreclr/src/dlls/mscoree/unixinterface.cpp +++ b/src/coreclr/src/dlls/mscoree/unixinterface.cpp @@ -18,6 +18,7 @@ #ifdef FEATURE_GDBJIT #include "../../vm/gdbjithelpers.h" #endif // FEATURE_GDBJIT +#include "bundle.h" #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr)) @@ -112,7 +113,8 @@ static void ConvertConfigPropertiesToUnicode( const char** propertyValues, int propertyCount, LPCWSTR** propertyKeysWRef, - LPCWSTR** propertyValuesWRef) + LPCWSTR** propertyValuesWRef, + BundleProbe** bundleProbe) { LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount]; ASSERTE_ALL_BUILDS(propertyKeysW != nullptr); @@ -124,6 +126,13 @@ static void ConvertConfigPropertiesToUnicode( { propertyKeysW[propertyIndex] = StringToUnicode(propertyKeys[propertyIndex]); propertyValuesW[propertyIndex] = StringToUnicode(propertyValues[propertyIndex]); + + if (strcmp(propertyKeys[propertyIndex], "BUNDLE_PROBE") == 0) + { + // If this application is a single-file bundle, the bundle-probe callback + // is passed in as the value of "BUNDLE_PROBE" property (encoded as a string). + *bundleProbe = (BundleProbe*)_wcstoui64(propertyValuesW[propertyIndex], nullptr, 0); + } } *propertyKeysWRef = propertyKeysW; @@ -183,12 +192,21 @@ int coreclr_initialize( LPCWSTR* propertyKeysW; LPCWSTR* propertyValuesW; + BundleProbe* bundleProbe = nullptr; + ConvertConfigPropertiesToUnicode( propertyKeys, propertyValues, propertyCount, &propertyKeysW, - &propertyValuesW); + &propertyValuesW, + &bundleProbe); + + if (bundleProbe != nullptr) + { + static Bundle bundle(StringToUnicode(exePath), bundleProbe); + Bundle::AppBundle = &bundle; + } // This will take ownership of propertyKeysWTemp and propertyValuesWTemp Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW); diff --git a/src/coreclr/src/dlls/mscorrc/mscorrc.rc b/src/coreclr/src/dlls/mscorrc/mscorrc.rc index 8a7410ef25b2d..4573e20be97ae 100644 --- a/src/coreclr/src/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/src/dlls/mscorrc/mscorrc.rc @@ -344,7 +344,7 @@ BEGIN IDS_EE_WINRT_NOT_FACTORY_FOR_TYPE "Windows Runtime factory '%1' is not a factory for Windows Runtime type '%2'." IDS_EE_WINRT_INVALID_FACTORY_FOR_TYPE "Windows Runtime type '%1' has a invalid Windows Runtime factory" IDS_EE_CANNOTCAST_NOMARSHAL "The Windows Runtime Object can only be used in the threading context where it was created, because it implements INoMarshal or has MarshalingBehaviorAttribute(MarshalingType.None) set." - IDS_EE_WINRT_WEAKREF_BAD_TYPE "The object resolved by a native IWeakReference has an incompatible type for its managed WeakReference instance.\r\nExpected WeakReference target type: '%1'\r\nNative IWeakReference returned type: '%2'" + IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE "The object resolved by a native IWeakReference has an incompatible type for its managed WeakReference instance.\r\nExpected WeakReference target type: '%1'\r\nNative IWeakReference returned type: '%2'" #endif // FEATURE_COMINTEROP IDS_EE_INTEROP_CODE_SIZE_COMMENT "Code size" diff --git a/src/coreclr/src/dlls/mscorrc/resource.h b/src/coreclr/src/dlls/mscorrc/resource.h index 342c0570d493b..4011efb748215 100644 --- a/src/coreclr/src/dlls/mscorrc/resource.h +++ b/src/coreclr/src/dlls/mscorrc/resource.h @@ -600,7 +600,7 @@ #ifdef FEATURE_COMINTEROP -#define IDS_EE_WINRT_WEAKREF_BAD_TYPE 0x262e +#define IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE 0x262e #endif // FEATURE_COMINTEROP #define IDS_EE_BADMARSHAL_TYPE_ANSIBSTR 0x262f diff --git a/src/coreclr/src/gc/env/etmdummy.h b/src/coreclr/src/gc/env/etmdummy.h index 7435df7f8137b..ba4c4cf96a5db 100644 --- a/src/coreclr/src/gc/env/etmdummy.h +++ b/src/coreclr/src/gc/env/etmdummy.h @@ -164,6 +164,7 @@ #define FireEtwGCMarkWithType(HeapNum, ClrInstanceID, Type, Bytes) 0 #define FireEtwGCJoin_V2(Heap, JoinTime, JoinType, ClrInstanceID, JoinID) 0 #define FireEtwGCPerHeapHistory_V3(ClrInstanceID, FreeListAllocated, FreeListRejected, EndOfSegAllocated, CondemnedAllocated, PinnedAllocated, PinnedAllocatedAdvance, RunningFreeListEfficiency, CondemnReasons0, CondemnReasons1, CompactMechanisms, ExpandMechanisms, HeapIndex, ExtraGen0Commit, Count, Values_Len_, Values) 0 +#define FireEtwGCGlobalHeapHistory_V2(FinalYoungestDesired, NumHeaps, CondemnedGeneration, Gen0ReductionCount, Reason, GlobalMechanisms, ClrInstanceID, PauseMode, MemoryPressure) 0 #define FireEtwGCGlobalHeapHistory_V3(FinalYoungestDesired, NumHeaps, CondemnedGeneration, Gen0ReductionCount, Reason, GlobalMechanisms, ClrInstanceID, PauseMode, MemoryPressure, CondemnReasons0, CondemnReasons1) 0 #define FireEtwDebugIPCEventStart() 0 #define FireEtwDebugIPCEventEnd() 0 diff --git a/src/coreclr/src/gc/env/gcenv.os.h b/src/coreclr/src/gc/env/gcenv.os.h index ae398e5503e3b..6a6477f3c4650 100644 --- a/src/coreclr/src/gc/env/gcenv.os.h +++ b/src/coreclr/src/gc/env/gcenv.os.h @@ -66,8 +66,9 @@ struct VirtualReserveFlags // are run on process exit, potentially concurrently with other threads that may still be // operating on the static event. To avoid these sorts of unsafety, GCEvent chooses to // not have a destructor at all. The cost of this is leaking a small amount of memory, but -// this is not a problem since a majority of the uses of GCEvent are static. See CoreCLR#11111 -// for more details on the hazards of static destructors. +// this is not a problem since a majority of the uses of GCEvent are static. +// See https://github.com/dotnet/runtime/issues/7919 for more details on the hazards of +// static destructors. class GCEvent { private: class Impl; @@ -433,20 +434,19 @@ class GCToOSInterface // Remarks: // If a process runs with a restricted memory limit, it returns the limit. If there's no limit // specified, it returns amount of actual physical memory. - // - // PERF TODO: Requires more work to not treat the restricted case to be special. - // To be removed before 3.0 ships. static uint64_t GetPhysicalMemoryLimit(bool* is_restricted=NULL); // Get memory status // Parameters: + // restricted_limit - The amount of physical memory in bytes that the current process is being restricted to. If non-zero, it used to calculate + // memory_load and available_physical. If zero, memory_load and available_physical is calculate based on all available memory. // memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. // Remarks: // Any parameter can be null. - static void GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file); + static void GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file); // Get size of an OS memory page static size_t GetPageSize(); diff --git a/src/coreclr/src/gc/env/volatile.h b/src/coreclr/src/gc/env/volatile.h index c7964e9107d8f..32b6fca3b6a7c 100644 --- a/src/coreclr/src/gc/env/volatile.h +++ b/src/coreclr/src/gc/env/volatile.h @@ -67,8 +67,8 @@ #error The Volatile type is currently only defined for Visual C++ and GNU C++ #endif -#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) -#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM or ARM64 CPUs +#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) && !defined(HOST_WASM) +#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM, ARM64 or Wasm #endif #if defined(__GNUC__) diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index a91de0d388d5e..3c26bd5b60e2e 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -192,6 +192,25 @@ BOOL is_induced_blocking (gc_reason reason) (reason == reason_lowmemory_host_blocking)); } +gc_oh_num gen_to_oh(int gen) +{ + switch (gen) + { + case soh_gen0: + return gc_oh_num::soh; + case soh_gen1: + return gc_oh_num::soh; + case soh_gen2: + return gc_oh_num::soh; + case loh_generation: + return gc_oh_num::loh; + case poh_generation: + return gc_oh_num::poh; + default: + return gc_oh_num::none; + } +} + #ifndef DACCESS_COMPILE int64_t qpf; size_t start_time; @@ -1866,7 +1885,14 @@ const int max_snoop_level = 128; #define MH_TH_CARD_BUNDLE (180*1024*1024) #endif //CARD_BUNDLE -#define GC_EPHEMERAL_DECOMMIT_TIMEOUT 5000 +// min size to decommit to make the OS call worthwhile +#define MIN_DECOMMIT_SIZE (100*OS_PAGE_SIZE) + +// max size to decommit per millisecond +#define DECOMMIT_SIZE_PER_MILLISECOND (160*1024) + +// time in milliseconds between decommit steps +#define DECOMMIT_TIME_STEP_MILLISECONDS (100) inline size_t align_on_page (size_t add) @@ -2060,7 +2086,6 @@ void qsort1(uint8_t** low, uint8_t** high, unsigned int depth); void* virtual_alloc (size_t size); void* virtual_alloc (size_t size, bool use_large_pages_p); -void virtual_free (void* add, size_t size); /* per heap static initialization */ #if defined(BACKGROUND_GC) && !defined(MULTIPLE_HEAPS) @@ -2112,6 +2137,8 @@ int* gc_heap::g_mark_stack_busy; size_t* gc_heap::g_bpromoted; #endif //BACKGROUND_GC +BOOL gc_heap::gradual_decommit_in_progress_p = FALSE; +size_t gc_heap::max_decommit_step_size = 0; #else //MULTIPLE_HEAPS size_t gc_heap::g_promoted; @@ -2138,12 +2165,12 @@ gc_history_global gc_heap::gc_data_global; size_t gc_heap::gc_last_ephemeral_decommit_time = 0; -size_t gc_heap::gc_gen0_desired_high; - CLRCriticalSection gc_heap::check_commit_cs; size_t gc_heap::current_total_committed = 0; +size_t gc_heap::committed_by_oh[total_oh_count] = {0, 0, 0, 0}; + size_t gc_heap::current_total_committed_bookkeeping = 0; #ifdef SHORT_PLUGS @@ -2175,6 +2202,8 @@ uint32_t gc_heap::m_high_memory_load_th; uint32_t gc_heap::v_high_memory_load_th; +bool gc_heap::is_restricted_physical_mem; + uint64_t gc_heap::total_physical_mem = 0; uint64_t gc_heap::entry_available_physical_mem = 0; @@ -3941,7 +3970,7 @@ struct initial_memory_details initial_memory_details memory_details; -BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinned_size, int num_heaps, bool use_large_pages_p) +BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinned_size, int num_heaps, bool use_large_pages_p) { BOOL reserve_success = FALSE; @@ -4080,7 +4109,7 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinne return reserve_success; } -void destroy_initial_memory() +void gc_heap::destroy_initial_memory() { if (memory_details.initial_memory != NULL) { @@ -4100,7 +4129,7 @@ void destroy_initial_memory() virtual_free (memory_details.initial_pinned_heap[0].memory_base, memory_details.block_count*memory_details.block_size_pinned); - } + } else { assert (memory_details.allocation_pattern == initial_memory_details::EACH_BLOCK); @@ -4127,7 +4156,8 @@ heap_segment* make_initial_segment (int gen, int h_number) { void* mem = memory_details.get_initial_memory (gen, h_number); size_t size = memory_details.get_initial_size (gen); - heap_segment* res = gc_heap::make_heap_segment ((uint8_t*)mem, size , h_number); + gc_oh_num oh = gen_to_oh (gen); + heap_segment* res = gc_heap::make_heap_segment ((uint8_t*)mem, size, oh, h_number); return res; } @@ -4194,14 +4224,6 @@ void* virtual_alloc (size_t size, bool use_large_pages_p) return aligned_mem; } -void virtual_free (void* add, size_t size) -{ - GCToOSInterface::VirtualRelease (add, size); - gc_heap::reserved_memory -= size; - dprintf (2, ("Virtual Free size %Id: [%Ix, %Ix[", - size, (size_t)add, (size_t)((uint8_t*)add+size))); -} - static size_t get_valid_segment_size (BOOL large_seg=FALSE) { size_t seg_size, initial_seg_size; @@ -4375,7 +4397,7 @@ gc_heap::soh_get_segment_to_expand() } } - heap_segment* result = get_segment (size, FALSE); + heap_segment* result = get_segment (size, gc_oh_num::soh); if(result) { @@ -4416,8 +4438,10 @@ gc_heap::soh_get_segment_to_expand() //returns 0 in case of allocation failure heap_segment* -gc_heap::get_segment (size_t size, BOOL loh_p) +gc_heap::get_segment (size_t size, gc_oh_num oh) { + assert(oh != gc_oh_num::none); + BOOL uoh_p = (oh == gc_oh_num::loh) || (oh == gc_oh_num::poh); if (heap_hard_limit) return NULL; @@ -4486,11 +4510,11 @@ gc_heap::get_segment (size_t size, BOOL loh_p) void* mem = virtual_alloc (size); if (!mem) { - fgm_result.set_fgm (fgm_reserve_segment, size, loh_p); + fgm_result.set_fgm (fgm_reserve_segment, size, uoh_p); return 0; } - result = gc_heap::make_heap_segment ((uint8_t*)mem, size, heap_number); + result = gc_heap::make_heap_segment ((uint8_t*)mem, size, oh, heap_number); if (result) { @@ -4514,7 +4538,7 @@ gc_heap::get_segment (size_t size, BOOL loh_p) end = (uint8_t*)g_gc_highest_address; } - if (gc_heap::grow_brick_card_tables (start, end, size, result, __this, loh_p) != 0) + if (gc_heap::grow_brick_card_tables (start, end, size, result, __this, uoh_p) != 0) { virtual_free (mem, size); return 0; @@ -4522,7 +4546,7 @@ gc_heap::get_segment (size_t size, BOOL loh_p) } else { - fgm_result.set_fgm (fgm_commit_segment_beg, SEGMENT_INITIAL_COMMIT, loh_p); + fgm_result.set_fgm (fgm_commit_segment_beg, SEGMENT_INITIAL_COMMIT, uoh_p); virtual_free (mem, size); } @@ -4546,11 +4570,11 @@ gc_heap::get_segment (size_t size, BOOL loh_p) return result; } -void release_segment (heap_segment* sg) +void gc_heap::release_segment (heap_segment* sg) { ptrdiff_t delta = 0; FIRE_EVENT(GCFreeSegment_V1, heap_segment_mem(sg)); - virtual_free (sg, (uint8_t*)heap_segment_reserved (sg)-(uint8_t*)sg); + virtual_free (sg, (uint8_t*)heap_segment_reserved (sg)-(uint8_t*)sg, sg); } heap_segment* gc_heap::get_segment_for_uoh (int gen_number, size_t size @@ -4562,7 +4586,8 @@ heap_segment* gc_heap::get_segment_for_uoh (int gen_number, size_t size #ifndef MULTIPLE_HEAPS gc_heap* hp = 0; #endif //MULTIPLE_HEAPS - heap_segment* res = hp->get_segment (size, TRUE); + gc_oh_num oh = gen_to_oh (gen_number); + heap_segment* res = hp->get_segment (size, oh); if (res != 0) { #ifdef MULTIPLE_HEAPS @@ -5395,7 +5420,12 @@ void gc_heap::gc_thread_function () if (heap_number == 0) { - gc_heap::ee_suspend_event.Wait(INFINITE, FALSE); + uint32_t wait_result = gc_heap::ee_suspend_event.Wait(gradual_decommit_in_progress_p ? DECOMMIT_TIME_STEP_MILLISECONDS : INFINITE, FALSE); + if (wait_result == WAIT_TIMEOUT) + { + gradual_decommit_in_progress_p = decommit_step (); + continue; + } BEGIN_TIMING(suspend_ee_during_log); GCToEEInterface::SuspendEE(SUSPEND_FOR_GC); @@ -5477,6 +5507,12 @@ void gc_heap::gc_thread_function () hp->set_gc_done(); } } + + // check if we should do some decommitting + if (gradual_decommit_in_progress_p) + { + gradual_decommit_in_progress_p = decommit_step (); + } } else { @@ -5521,7 +5557,7 @@ bool gc_heap::virtual_alloc_commit_for_heap (void* addr, size_t size, int h_numb return GCToOSInterface::VirtualCommit(addr, size); } -bool gc_heap::virtual_commit (void* address, size_t size, int h_number, bool* hard_limit_exceeded_p) +bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_number, bool* hard_limit_exceeded_p) { #ifndef HOST_64BIT assert (heap_hard_limit == 0); @@ -5529,9 +5565,9 @@ bool gc_heap::virtual_commit (void* address, size_t size, int h_number, bool* ha if (heap_hard_limit) { - bool exceeded_p = false; - check_commit_cs.Enter(); + committed_by_oh[oh] += size; + bool exceeded_p = false; if ((current_total_committed + size) > heap_hard_limit) { @@ -5570,6 +5606,8 @@ bool gc_heap::virtual_commit (void* address, size_t size, int h_number, bool* ha if (!commit_succeeded_p && heap_hard_limit) { check_commit_cs.Enter(); + committed_by_oh[oh] -= size; + dprintf (1, ("commit failed, updating %Id to %Id", current_total_committed, (current_total_committed - size))); current_total_committed -= size; @@ -5578,11 +5616,10 @@ bool gc_heap::virtual_commit (void* address, size_t size, int h_number, bool* ha check_commit_cs.Leave(); } - return commit_succeeded_p; } -bool gc_heap::virtual_decommit (void* address, size_t size, int h_number) +bool gc_heap::virtual_decommit (void* address, size_t size, gc_oh_num oh, int h_number) { #ifndef HOST_64BIT assert (heap_hard_limit == 0); @@ -5593,6 +5630,7 @@ bool gc_heap::virtual_decommit (void* address, size_t size, int h_number) if (decommit_succeeded_p && heap_hard_limit) { check_commit_cs.Enter(); + committed_by_oh[oh] -= size; current_total_committed -= size; if (h_number < 0) current_total_committed_bookkeeping -= size; @@ -5602,6 +5640,18 @@ bool gc_heap::virtual_decommit (void* address, size_t size, int h_number) return decommit_succeeded_p; } +void gc_heap::virtual_free (void* add, size_t allocated_size, heap_segment* sg) +{ + assert(!heap_hard_limit); + bool release_succeeded_p = GCToOSInterface::VirtualRelease (add, allocated_size); + if (release_succeeded_p) + { + reserved_memory -= allocated_size; + dprintf (2, ("Virtual Free size %Id: [%Ix, %Ix[", + allocated_size, (size_t)add, (size_t)((uint8_t*)add + allocated_size))); + } +} + class mark { public: @@ -7205,7 +7255,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) // mark array will be committed separately (per segment). size_t commit_size = alloc_size - ms; - if (!virtual_commit (mem, commit_size)) + if (!virtual_commit (mem, commit_size, gc_oh_num::none)) { dprintf (1, ("Card table commit failed")); GCToOSInterface::VirtualRelease (mem, alloc_size); @@ -7275,7 +7325,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, size_t size, heap_segment* new_seg, gc_heap* hp, - BOOL loh_p) + BOOL uoh_p) { uint8_t* la = g_gc_lowest_address; uint8_t* ha = g_gc_highest_address; @@ -7400,7 +7450,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, if (!mem) { - set_fgm_result (fgm_grow_table, alloc_size, loh_p); + set_fgm_result (fgm_grow_table, alloc_size, uoh_p); goto fail; } @@ -7411,10 +7461,10 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // mark array will be committed separately (per segment). size_t commit_size = alloc_size - ms; - if (!virtual_commit (mem, commit_size)) + if (!virtual_commit (mem, commit_size, gc_oh_num::none)) { dprintf (GC_TABLE_LOG, ("Table commit failed")); - set_fgm_result (fgm_commit_table, commit_size, loh_p); + set_fgm_result (fgm_commit_table, commit_size, uoh_p); goto fail; } } @@ -7481,14 +7531,14 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, if (!commit_new_mark_array_global (new_mark_array)) { dprintf (GC_TABLE_LOG, ("failed to commit portions in the mark array for existing segments")); - set_fgm_result (fgm_commit_table, logging_ma_commit_size, loh_p); + set_fgm_result (fgm_commit_table, logging_ma_commit_size, uoh_p); goto fail; } if (!commit_mark_array_new_seg (hp, new_seg, translated_ct, saved_g_lowest_address)) { dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new seg")); - set_fgm_result (fgm_commit_table, logging_ma_commit_size, loh_p); + set_fgm_result (fgm_commit_table, logging_ma_commit_size, uoh_p); goto fail; } } @@ -7605,7 +7655,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, if (!commit_mark_array_new_seg (hp, new_seg)) { dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new seg in range")); - set_fgm_result (fgm_commit_table, logging_ma_commit_size, loh_p); + set_fgm_result (fgm_commit_table, logging_ma_commit_size, uoh_p); return -1; } } @@ -9138,11 +9188,12 @@ int gc_heap::object_gennum_plan (uint8_t* o) #pragma optimize("", on) // Go back to command line default optimizations #endif //_MSC_VER && TARGET_X86 -heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, int h_number) +heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, gc_oh_num oh, int h_number) { + assert(oh != gc_oh_num::none); size_t initial_commit = SEGMENT_INITIAL_COMMIT; - if (!virtual_commit (new_pages, initial_commit, h_number)) + if (!virtual_commit (new_pages, initial_commit, oh, h_number)) { return 0; } @@ -9242,22 +9293,40 @@ void gc_heap::decommit_heap_segment_pages (heap_segment* seg, uint8_t* page_start = align_on_page (heap_segment_allocated(seg)); size_t size = heap_segment_committed (seg) - page_start; extra_space = align_on_page (extra_space); - if (size >= max ((extra_space + 2*OS_PAGE_SIZE), 100*OS_PAGE_SIZE)) + if (size >= max ((extra_space + 2*OS_PAGE_SIZE), MIN_DECOMMIT_SIZE)) { page_start += max(extra_space, 32*OS_PAGE_SIZE); - size -= max (extra_space, 32*OS_PAGE_SIZE); + decommit_heap_segment_pages_worker (seg, page_start); + } +} - virtual_decommit (page_start, size, heap_number); - dprintf (3, ("Decommitting heap segment [%Ix, %Ix[(%d)", - (size_t)page_start, - (size_t)(page_start + size), - size)); - heap_segment_committed (seg) = page_start; - if (heap_segment_used (seg) > heap_segment_committed (seg)) +size_t gc_heap::decommit_heap_segment_pages_worker (heap_segment* seg, + uint8_t* new_committed) +{ + assert (!use_large_pages_p); + uint8_t* page_start = align_on_page (new_committed); + size_t size = heap_segment_committed (seg) - page_start; + if (size > 0) + { + bool decommit_succeeded_p = virtual_decommit (page_start, size, heap_segment_oh (seg), heap_number); + if (decommit_succeeded_p) { - heap_segment_used (seg) = heap_segment_committed (seg); + dprintf (3, ("Decommitting heap segment [%Ix, %Ix[(%d)", + (size_t)page_start, + (size_t)(page_start + size), + size)); + heap_segment_committed (seg) = page_start; + if (heap_segment_used (seg) > heap_segment_committed (seg)) + { + heap_segment_used (seg) = heap_segment_committed (seg); + } + } + else + { + dprintf (3, ("Decommitting heap segment failed")); } } + return size; } //decommit all pages except one or 2 @@ -9272,13 +9341,16 @@ void gc_heap::decommit_heap_segment (heap_segment* seg) #endif //BACKGROUND_GC size_t size = heap_segment_committed (seg) - page_start; - virtual_decommit (page_start, size, heap_number); + bool decommit_succeeded_p = virtual_decommit (page_start, size, heap_segment_oh (seg), heap_number); - //re-init the segment object - heap_segment_committed (seg) = page_start; - if (heap_segment_used (seg) > heap_segment_committed (seg)) + if (decommit_succeeded_p) { - heap_segment_used (seg) = heap_segment_committed (seg); + //re-init the segment object + heap_segment_committed (seg) = page_start; + if (heap_segment_used (seg) > heap_segment_committed (seg)) + { + heap_segment_used (seg) = heap_segment_committed (seg); + } } } @@ -10026,6 +10098,14 @@ gc_heap::init_semi_shared() } #endif //MARK_LIST +#ifdef MULTIPLE_HEAPS + // gradual decommit: set size to some reasonable value per time interval + max_decommit_step_size = ((DECOMMIT_SIZE_PER_MILLISECOND * DECOMMIT_TIME_STEP_MILLISECONDS) / n_heaps); + + // but do at least MIN_DECOMMIT_SIZE per step to make the OS call worthwhile + max_decommit_step_size = max (max_decommit_step_size, MIN_DECOMMIT_SIZE); +#endif //MULTIPLE_HEAPS + #ifdef FEATURE_BASICFREEZE seg_table = sorted_table::make_sorted_table(); @@ -10896,7 +10976,7 @@ BOOL gc_heap::grow_heap_segment (heap_segment* seg, uint8_t* high_address, bool* "Growing heap_segment: %Ix high address: %Ix\n", (size_t)seg, (size_t)high_address); - bool ret = virtual_commit (heap_segment_committed (seg), c_size, heap_number, hard_limit_exceeded_p); + bool ret = virtual_commit (heap_segment_committed (seg), c_size, heap_segment_oh (seg), heap_number, hard_limit_exceeded_p); if (ret) { heap_segment_committed (seg) += c_size; @@ -16971,7 +17051,9 @@ BOOL gc_heap::expand_soh_with_minimal_gc() return TRUE; } else + { return FALSE; + } } // Only to be done on the thread that calls restart in a join for server GC @@ -19628,7 +19710,7 @@ void gc_heap::get_memory_info (uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { - GCToOSInterface::GetMemoryStatus(memory_load, available_physical, available_page_file); + GCToOSInterface::GetMemoryStatus(is_restricted_physical_mem ? total_physical_mem : 0, memory_load, available_physical, available_page_file); } void fire_mark_event (int heap_num, int root_type, size_t bytes_marked) @@ -25787,7 +25869,7 @@ BOOL gc_heap::commit_mark_array_by_range (uint8_t* begin, uint8_t* end, uint32_t size)); #endif //SIMPLE_DPRINTF - if (virtual_commit (commit_start, size)) + if (virtual_commit (commit_start, size, gc_oh_num::none)) { // We can only verify the mark array is cleared from begin to end, the first and the last // page aren't necessarily all cleared 'cause they could be used by other segments or @@ -26011,7 +26093,7 @@ void gc_heap::decommit_mark_array_by_seg (heap_segment* seg) if (decommit_start < decommit_end) { - if (!virtual_decommit (decommit_start, size)) + if (!virtual_decommit (decommit_start, size, gc_oh_num::none)) { dprintf (GC_TABLE_LOG, ("decommit on %Ix for %Id bytes failed", decommit_start, size)); @@ -31727,56 +31809,133 @@ void gc_heap::trim_youngest_desired_low_memory() void gc_heap::decommit_ephemeral_segment_pages() { - if (settings.concurrent) + if (settings.concurrent || use_large_pages_p) { return; } - size_t slack_space = heap_segment_committed (ephemeral_heap_segment) - heap_segment_allocated (ephemeral_heap_segment); + dynamic_data* dd0 = dynamic_data_of (0); - dynamic_data* dd = dynamic_data_of (0); + // this is how much we are going to allocate in gen 0 + ptrdiff_t desired_allocation = dd_desired_allocation (dd0) + loh_size_threshold; -#ifndef MULTIPLE_HEAPS - size_t extra_space = (g_low_memory_status ? 0 : (512 * 1024)); - size_t decommit_timeout = (g_low_memory_status ? 0 : GC_EPHEMERAL_DECOMMIT_TIMEOUT); - size_t ephemeral_elapsed = dd_time_clock(dd) - gc_last_ephemeral_decommit_time; - - if (dd_desired_allocation (dd) > gc_gen0_desired_high) + // estimate how we are going to need in gen 1 - estimate half the free list space gets used + dynamic_data* dd1 = dynamic_data_of (1); + ptrdiff_t desired_allocation_1 = dd_new_allocation (dd1) - (generation_free_list_space (generation_of (1)) / 2); + if (desired_allocation_1 > 0) { - gc_gen0_desired_high = dd_desired_allocation (dd) + extra_space; + desired_allocation += desired_allocation_1; } - if (ephemeral_elapsed >= decommit_timeout) - { - slack_space = min (slack_space, gc_gen0_desired_high); - - gc_last_ephemeral_decommit_time = dd_time_clock(dd); - gc_gen0_desired_high = 0; - } -#endif //!MULTIPLE_HEAPS - - if (settings.condemned_generation >= (max_generation-1)) - { - size_t new_slack_space = + size_t slack_space = #ifdef HOST_64BIT - max(min(min(soh_segment_size/32, dd_max_size(dd)), (generation_size (max_generation) / 10)), dd_desired_allocation(dd)); + max(min(min(soh_segment_size/32, dd_max_size (dd0)), (generation_size (max_generation) / 10)), (size_t)desired_allocation); #else #ifdef FEATURE_CORECLR - dd_desired_allocation (dd); + desired_allocation; #else - dd_max_size (dd); + dd_max_size (dd0); #endif //FEATURE_CORECLR #endif // HOST_64BIT - slack_space = min (slack_space, new_slack_space); + uint8_t *decommit_target = heap_segment_allocated (ephemeral_heap_segment) + slack_space; + if (decommit_target < heap_segment_decommit_target (ephemeral_heap_segment)) + { + // we used to have a higher target - do exponential smoothing by computing + // essentially decommit_target = 1/3*decommit_target + 2/3*previous_decommit_target + // computation below is slightly different to avoid overflow + ptrdiff_t target_decrease = heap_segment_decommit_target (ephemeral_heap_segment) - decommit_target; + decommit_target += target_decrease * 2 / 3; + } + + heap_segment_decommit_target(ephemeral_heap_segment) = decommit_target; + +#ifdef MULTIPLE_HEAPS + if (decommit_target < heap_segment_committed (ephemeral_heap_segment)) + { + gradual_decommit_in_progress_p = TRUE; } +#ifdef _DEBUG + // these are only for checking against logic errors + ephemeral_heap_segment->saved_committed = heap_segment_committed (ephemeral_heap_segment); + ephemeral_heap_segment->saved_desired_allocation = dd_desired_allocation (dd0); +#endif // _DEBUG +#endif // MULTIPLE_HEAPS +#ifndef MULTIPLE_HEAPS + // we want to limit the amount of decommit we do per time to indirectly + // limit the amount of time spent in recommit and page faults + size_t ephemeral_elapsed = dd_time_clock (dd0) - gc_last_ephemeral_decommit_time; + gc_last_ephemeral_decommit_time = dd_time_clock (dd0); + + // this is the amount we were planning to decommit + ptrdiff_t decommit_size = heap_segment_committed (ephemeral_heap_segment) - decommit_target; + + // we do a max of DECOMMIT_SIZE_PER_MILLISECOND per millisecond of elapsed time since the last GC + // we limit the elapsed time to 10 seconds to avoid spending too much time decommitting + ptrdiff_t max_decommit_size = min (ephemeral_elapsed, (10*1000)) * DECOMMIT_SIZE_PER_MILLISECOND; + decommit_size = min (decommit_size, max_decommit_size); + + slack_space = heap_segment_committed (ephemeral_heap_segment) - heap_segment_allocated (ephemeral_heap_segment) - decommit_size; decommit_heap_segment_pages (ephemeral_heap_segment, slack_space); +#endif // !MULTIPLE_HEAPS gc_history_per_heap* current_gc_data_per_heap = get_gc_data_per_heap(); current_gc_data_per_heap->extra_gen0_committed = heap_segment_committed (ephemeral_heap_segment) - heap_segment_allocated (ephemeral_heap_segment); } +#ifdef MULTIPLE_HEAPS +// return true if we actually decommitted anything +bool gc_heap::decommit_step () +{ + // should never get here for large pages because decommit_ephemeral_segment_pages + // will not do anything if use_large_pages_p is true + assert (!use_large_pages_p); + + size_t decommit_size = 0; + for (int i = 0; i < n_heaps; i++) + { + gc_heap* hp = gc_heap::g_heaps[i]; + decommit_size += hp->decommit_ephemeral_segment_pages_step (); + } + return (decommit_size != 0); +} + +// return the decommitted size +size_t gc_heap::decommit_ephemeral_segment_pages_step () +{ + // we rely on desired allocation not being changed outside of GC + assert (ephemeral_heap_segment->saved_desired_allocation == dd_desired_allocation (dynamic_data_of (0))); + + uint8_t* decommit_target = heap_segment_decommit_target (ephemeral_heap_segment); + size_t EXTRA_SPACE = 2 * OS_PAGE_SIZE; + decommit_target += EXTRA_SPACE; + uint8_t* committed = heap_segment_committed (ephemeral_heap_segment); + if (decommit_target < committed) + { + // we rely on other threads not messing with committed if we are about to trim it down + assert (ephemeral_heap_segment->saved_committed == heap_segment_committed (ephemeral_heap_segment)); + + // how much would we need to decommit to get to decommit_target in one step? + size_t full_decommit_size = (committed - decommit_target); + + // don't do more than max_decommit_step_size per step + size_t decommit_size = min (max_decommit_step_size, full_decommit_size); + + // figure out where the new committed should be + uint8_t* new_committed = (committed - decommit_size); + size_t size = decommit_heap_segment_pages_worker (ephemeral_heap_segment, new_committed); + +#ifdef _DEBUG + ephemeral_heap_segment->saved_committed = committed - size; +#endif // _DEBUG + + return size; + } + return 0; +} +#endif //MULTIPLE_HEAPS + //This is meant to be called by decide_on_compacting. size_t gc_heap::generation_fragmentation (generation* gen, @@ -34925,11 +35084,14 @@ HRESULT GCHeap::Initialize() g_num_processors = GCToOSInterface::GetTotalProcessorCount(); assert(g_num_processors != 0); - bool is_restricted; gc_heap::total_physical_mem = (size_t)GCConfig::GetGCTotalPhysicalMemory(); - if (!(gc_heap::total_physical_mem)) + if (gc_heap::total_physical_mem != 0) + { + gc_heap::is_restricted_physical_mem = true; + } + else { - gc_heap::total_physical_mem = GCToOSInterface::GetPhysicalMemoryLimit (&is_restricted); + gc_heap::total_physical_mem = GCToOSInterface::GetPhysicalMemoryLimit (&gc_heap::is_restricted_physical_mem); } #ifdef HOST_64BIT @@ -34948,7 +35110,7 @@ HRESULT GCHeap::Initialize() // running in a container, use this limit for the GC heap. if (!(gc_heap::heap_hard_limit)) { - if (is_restricted) + if (gc_heap::is_restricted_physical_mem) { uint64_t physical_mem_for_gc = gc_heap::total_physical_mem * (uint64_t)75 / (uint64_t)100; gc_heap::heap_hard_limit = (size_t)max ((20 * 1024 * 1024), physical_mem_for_gc); diff --git a/src/coreclr/src/gc/gchandletable.cpp b/src/coreclr/src/gc/gchandletable.cpp index b7c4bf2687233..d3f93b457521e 100644 --- a/src/coreclr/src/gc/gchandletable.cpp +++ b/src/coreclr/src/gc/gchandletable.cpp @@ -168,7 +168,7 @@ Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE h HandleType GCHandleManager::HandleFetchType(OBJECTHANDLE handle) { uint32_t type = ::HandleFetchType(handle); - assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT); + assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_NATIVE_COM); return static_cast(type); } diff --git a/src/coreclr/src/gc/gcinterface.h b/src/coreclr/src/gc/gcinterface.h index 122106c2ae273..e9bef6a502b45 100644 --- a/src/coreclr/src/gc/gcinterface.h +++ b/src/coreclr/src/gc/gcinterface.h @@ -422,18 +422,18 @@ typedef enum HNDTYPE_SIZEDREF = 8, /* - * WINRT WEAK HANDLES + * NATIVE WEAK HANDLES * - * WinRT weak reference handles hold two different types of weak handles to any + * Native weak reference handles hold two different types of weak handles to any * RCW with an underlying COM object that implements IWeakReferenceSource. The * object reference itself is a short weak handle to the RCW. In addition an * IWeakReference* to the underlying COM object is stored, allowing the handle * to create a new RCW if the existing RCW is collected. This ensures that any - * code holding onto a WinRT weak reference can always access an RCW to the + * code holding onto a native weak reference can always access an RCW to the * underlying COM object as long as it has not been released by all of its strong * references. */ - HNDTYPE_WEAK_WINRT = 9 + HNDTYPE_WEAK_NATIVE_COM = 9 } HandleType; typedef enum diff --git a/src/coreclr/src/gc/gcpriv.h b/src/coreclr/src/gc/gcpriv.h index 3bcb383870773..ac6e746317889 100644 --- a/src/coreclr/src/gc/gcpriv.h +++ b/src/coreclr/src/gc/gcpriv.h @@ -223,6 +223,7 @@ const int policy_expand = 2; #define JOIN_LOG (MIN_CUSTOM_LOG_LEVEL + 6) #define SPINLOCK_LOG (MIN_CUSTOM_LOG_LEVEL + 7) #define SNOOP_LOG (MIN_CUSTOM_LOG_LEVEL + 8) +#define COMMIT_ACCOUNTING_LOG (MIN_CUSTOM_LOG_LEVEL + 9) // NOTE! This is for HEAP_BALANCE_INSTRUMENTATION // This particular one is special and needs to be well formatted because we @@ -398,6 +399,17 @@ enum gc_tuning_point tuning_deciding_short_on_seg = 5 }; +enum gc_oh_num +{ + soh = 0, + loh = 1, + poh = 2, + none = 3, + total_oh_count = 4 +}; + +gc_oh_num gen_to_oh (int gen); + #if defined(TRACE_GC) && defined(BACKGROUND_GC) static const char * const str_bgc_state[] = { @@ -1138,6 +1150,7 @@ class gc_heap static heap_segment* make_heap_segment (uint8_t* new_pages, size_t size, + gc_oh_num oh, int h_number); static @@ -1269,6 +1282,11 @@ class gc_heap #endif // FEATURE_BASICFREEZE protected: + PER_HEAP_ISOLATED + BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinned_size, int num_heaps, bool use_large_pages_p); + + PER_HEAP_ISOLATED + void destroy_initial_memory(); PER_HEAP_ISOLATED void walk_heap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p); @@ -1631,7 +1649,9 @@ class gc_heap PER_HEAP heap_segment* soh_get_segment_to_expand(); PER_HEAP - heap_segment* get_segment (size_t size, BOOL loh_p); + heap_segment* get_segment (size_t size, gc_oh_num oh); + PER_HEAP_ISOLATED + void release_segment (heap_segment* sg); PER_HEAP_ISOLATED void seg_mapping_table_add_segment (heap_segment* seg, gc_heap* hp); PER_HEAP_ISOLATED @@ -1651,13 +1671,21 @@ class gc_heap PER_HEAP void decommit_heap_segment_pages (heap_segment* seg, size_t extra_space); PER_HEAP + size_t decommit_ephemeral_segment_pages_step (); + PER_HEAP + size_t decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t *new_committed); + PER_HEAP_ISOLATED + bool decommit_step (); + PER_HEAP void decommit_heap_segment (heap_segment* seg); PER_HEAP_ISOLATED bool virtual_alloc_commit_for_heap (void* addr, size_t size, int h_number); PER_HEAP_ISOLATED - bool virtual_commit (void* address, size_t size, int h_number=-1, bool* hard_limit_exceeded_p=NULL); + bool virtual_commit (void* address, size_t size, gc_oh_num oh, int h_number=-1, bool* hard_limit_exceeded_p=NULL); + PER_HEAP_ISOLATED + bool virtual_decommit (void* address, size_t size, gc_oh_num oh, int h_number=-1); PER_HEAP_ISOLATED - bool virtual_decommit (void* address, size_t size, int h_number=-1); + void virtual_free (void* add, size_t size, heap_segment* sg=NULL); PER_HEAP void clear_gen0_bricks(); #ifdef BACKGROUND_GC @@ -2446,8 +2474,6 @@ class gc_heap void check_loh_compact_mode (BOOL all_heaps_compacted_p); #endif //FEATURE_LOH_COMPACTION - PER_HEAP - void decommit_ephemeral_segment_pages (int condemned_gen_number); PER_HEAP void fix_generation_bounds (int condemned_gen_number, generation* consing_gen); @@ -3255,9 +3281,6 @@ class gc_heap PER_HEAP_ISOLATED size_t gc_last_ephemeral_decommit_time; - PER_HEAP_ISOLATED - size_t gc_gen0_desired_high; - PER_HEAP size_t gen0_big_free_spaces; @@ -3289,6 +3312,9 @@ class gc_heap PER_HEAP_ISOLATED uint32_t v_high_memory_load_th; + PER_HEAP_ISOLATED + bool is_restricted_physical_mem; + PER_HEAP_ISOLATED uint64_t mem_one_percent; @@ -3363,6 +3389,9 @@ class gc_heap PER_HEAP_ISOLATED size_t current_total_committed; + PER_HEAP_ISOLATED + size_t committed_by_oh[total_oh_count]; + // This is what GC uses for its own bookkeeping. PER_HEAP_ISOLATED size_t current_total_committed_bookkeeping; @@ -3782,6 +3811,14 @@ class gc_heap PER_HEAP_ISOLATED BOOL proceed_with_gc_p; +#ifdef MULTIPLE_HEAPS + PER_HEAP_ISOLATED + BOOL gradual_decommit_in_progress_p; + + PER_HEAP_ISOLATED + size_t max_decommit_step_size; +#endif //MULTIPLE_HEAPS + #define youngest_generation (generation_of (0)) #define large_object_generation (generation_of (loh_generation)) #define pinned_object_generation (generation_of (poh_generation)) @@ -4695,7 +4732,12 @@ class heap_segment uint8_t* background_allocated; #ifdef MULTIPLE_HEAPS gc_heap* heap; +#ifdef _DEBUG + uint8_t* saved_committed; + size_t saved_desired_allocation; +#endif // _DEBUG #endif //MULTIPLE_HEAPS + uint8_t* decommit_target; uint8_t* plan_allocated; uint8_t* saved_bg_allocated; @@ -4732,6 +4774,11 @@ uint8_t*& heap_segment_committed (heap_segment* inst) return inst->committed; } inline +uint8_t*& heap_segment_decommit_target (heap_segment* inst) +{ + return inst->decommit_target; +} +inline uint8_t*& heap_segment_used (heap_segment* inst) { return inst->used; @@ -4768,6 +4815,22 @@ BOOL heap_segment_uoh_p (heap_segment * inst) return !!(inst->flags & (heap_segment_flags_loh | heap_segment_flags_poh)); } +inline gc_oh_num heap_segment_oh (heap_segment * inst) +{ + if ((inst->flags & heap_segment_flags_loh) != 0) + { + return gc_oh_num::loh; + } + else if ((inst->flags & heap_segment_flags_poh) != 0) + { + return gc_oh_num::poh; + } + else + { + return gc_oh_num::soh; + } +} + #ifdef BACKGROUND_GC inline BOOL heap_segment_decommitted_p (heap_segment * inst) diff --git a/src/coreclr/src/gc/handletable.cpp b/src/coreclr/src/gc/handletable.cpp index 898e843419341..1b56c74c791cf 100644 --- a/src/coreclr/src/gc/handletable.cpp +++ b/src/coreclr/src/gc/handletable.cpp @@ -409,10 +409,10 @@ void HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle) _ASSERTE(handle); #ifdef FEATURE_COMINTEROP - // If we're being asked to destroy a WinRT weak handle, that will cause a leak + // If we're being asked to destroy a native COM weak handle, that will cause a leak // of the IWeakReference* that it holds in its extra data. Instead of using this - // API use DestroyWinRTWeakHandle instead. - _ASSERTE(HandleFetchType(handle) != HNDTYPE_WEAK_WINRT); + // API use DestroyNativeComWeakHandle instead. + _ASSERTE(HandleFetchType(handle) != HNDTYPE_WEAK_NATIVE_COM); #endif // FEATURE_COMINTEROP // fetch the type and then free normally diff --git a/src/coreclr/src/gc/objecthandle.cpp b/src/coreclr/src/gc/objecthandle.cpp index 4a4f201ca03bd..e6a5160d7ee54 100644 --- a/src/coreclr/src/gc/objecthandle.cpp +++ b/src/coreclr/src/gc/objecthandle.cpp @@ -426,7 +426,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt case HNDTYPE_WEAK_SHORT: case HNDTYPE_WEAK_LONG: #ifdef FEATURE_COMINTEROP - case HNDTYPE_WEAK_WINRT: + case HNDTYPE_WEAK_NATIVE_COM: #endif // FEATURE_COMINTEROP rootFlags |= kEtwGCRootFlagsWeakRef; break; @@ -520,7 +520,7 @@ static const uint32_t s_rgTypeFlags[] = HNDF_EXTRAINFO, // HNDTYPE_DEPENDENT HNDF_NORMAL, // HNDTYPE_ASYNCPINNED HNDF_EXTRAINFO, // HNDTYPE_SIZEDREF - HNDF_EXTRAINFO, // HNDTYPE_WEAK_WINRT + HNDF_EXTRAINFO, // HNDTYPE_WEAK_NATIVE_COM }; int getNumberOfSlots() @@ -1380,7 +1380,7 @@ void Ref_CheckAlive(uint32_t condemned, uint32_t maxgen, uintptr_t lp1) { HNDTYPE_WEAK_SHORT #ifdef FEATURE_COMINTEROP - , HNDTYPE_WEAK_WINRT + , HNDTYPE_WEAK_NATIVE_COM #endif // FEATURE_COMINTEROP }; uint32_t flags = (((ScanContext*) lp1)->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL; @@ -1439,7 +1439,7 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK #ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, + HNDTYPE_WEAK_NATIVE_COM, #endif // FEATURE_COMINTEROP HNDTYPE_SIZEDREF, }; @@ -1485,7 +1485,7 @@ void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_sca HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK #ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, + HNDTYPE_WEAK_NATIVE_COM, #endif // FEATURE_COMINTEROP HNDTYPE_PINNED, // HNDTYPE_VARIABLE, @@ -1631,7 +1631,7 @@ void Ref_AgeHandles(uint32_t condemned, uint32_t maxgen, uintptr_t lp1) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK #ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, + HNDTYPE_WEAK_NATIVE_COM, #endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, @@ -1674,7 +1674,7 @@ void Ref_RejuvenateHandles(uint32_t condemned, uint32_t maxgen, uintptr_t lp1) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK #ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, + HNDTYPE_WEAK_NATIVE_COM, #endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, @@ -1716,7 +1716,7 @@ void Ref_VerifyHandleTable(uint32_t condemned, uint32_t maxgen, ScanContext* sc) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK #ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, + HNDTYPE_WEAK_NATIVE_COM, #endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, diff --git a/src/coreclr/src/gc/unix/cgroup.cpp b/src/coreclr/src/gc/unix/cgroup.cpp index c2c1b2b588449..9cdc5b14df021 100644 --- a/src/coreclr/src/gc/unix/cgroup.cpp +++ b/src/coreclr/src/gc/unix/cgroup.cpp @@ -54,6 +54,8 @@ Module Name: #define CGROUP1_CFS_PERIOD_FILENAME "/cpu.cfs_period_us" #define CGROUP2_CPU_MAX_FILENAME "/cpu.max" +extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val); + class CGroup { // the cgroup version number or 0 to indicate cgroups are not found or not enabled @@ -420,52 +422,6 @@ class CGroup return result; } - static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) - { - bool result = false; - char *line = nullptr; - size_t lineLen = 0; - char* endptr = nullptr; - uint64_t num = 0, l, multiplier; - FILE* file = nullptr; - - if (val == nullptr) - goto done; - - file = fopen(filename, "r"); - if (file == nullptr) - goto done; - - if (getline(&line, &lineLen, file) == -1) - goto done; - - errno = 0; - num = strtoull(line, &endptr, 0); - if (line == endptr || errno != 0) - goto done; - - multiplier = 1; - switch(*endptr) - { - case 'g': - case 'G': multiplier = 1024; - case 'm': - case 'M': multiplier = multiplier*1024; - case 'k': - case 'K': multiplier = multiplier*1024; - } - - *val = num * multiplier; - result = true; - if (*val/multiplier != num) - result = false; - done: - if (file) - fclose(file); - free(line); - return result; - } - static bool GetCGroup1CpuLimit(uint32_t *val) { long long quota; diff --git a/src/coreclr/src/gc/unix/gcenv.unix.cpp b/src/coreclr/src/gc/unix/gcenv.unix.cpp index fd3cd5ec91b6d..9b78b70f53abb 100644 --- a/src/coreclr/src/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/src/gc/unix/gcenv.unix.cpp @@ -772,6 +772,52 @@ bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, return false; } +bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) +{ + bool result = false; + char* line = nullptr; + size_t lineLen = 0; + char* endptr = nullptr; + uint64_t num = 0, l, multiplier; + FILE* file = nullptr; + + if (val == nullptr) + goto done; + + file = fopen(filename, "r"); + if (file == nullptr) + goto done; + + if (getline(&line, &lineLen, file) == -1) + goto done; + + errno = 0; + num = strtoull(line, &endptr, 0); + if (line == endptr || errno != 0) + goto done; + + multiplier = 1; + switch (*endptr) + { + case 'g': + case 'G': multiplier = 1024; + case 'm': + case 'M': multiplier = multiplier * 1024; + case 'k': + case 'K': multiplier = multiplier * 1024; + } + + *val = num * multiplier; + result = true; + if (*val / multiplier != num) + result = false; +done: + if (file) + fclose(file); + free(line); + return result; +} + static size_t GetLogicalProcessorCacheSizeFromOS() { size_t cacheSize = 0; @@ -789,6 +835,49 @@ static size_t GetLogicalProcessorCacheSizeFromOS() cacheSize = std::max(cacheSize, ( size_t) sysconf(_SC_LEVEL4_CACHE_SIZE)); #endif +#if defined(HOST_ARM64) + if (cacheSize == 0) + { + size_t size; + + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index1/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index2/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index3/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size)) + cacheSize = std::max(cacheSize, size); + } + + if (cacheSize == 0) + { + // It is currently expected to be missing cache size info + // + // _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64 + // + // /sys/devices/system/cpu/cpu*/cache/index*/ is also not yet present in most systems. + // Arm64 patch is in Linux kernel tip. + // + // midr_el1 is available in "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1", + // but without an exhaustive list of ARM64 processors any decode of midr_el1 + // Would likely be incomplete + + // Published information on ARM64 architectures is limited. + // If we use recent high core count chips as a guide for state of the art, we find + // total L3 cache to be 1-2MB/core. As always, there are exceptions. + + // Estimate cache size based on CPU count + // Assume lower core count are lighter weight parts which are likely to have smaller caches + // Assume L3$/CPU grows linearly from 256K to 1.5M/CPU as logicalCPUs grows from 2 to 12 CPUs + DWORD logicalCPUs = g_totalCpuCount; + + cacheSize = logicalCPUs * std::min(1536, std::max(256, (int)logicalCPUs * 128)) * 1024; + } +#endif + #if HAVE_SYSCTLBYNAME if (cacheSize == 0) { @@ -957,7 +1046,7 @@ uint32_t GCToOSInterface::GetCurrentProcessCpuCount() // Return the size of the user-mode portion of the virtual address space of this process. // Return: -// non zero if it has succeeded, 0 if it has failed +// non zero if it has succeeded, (size_t)-1 if not available size_t GCToOSInterface::GetVirtualMemoryLimit() { #ifdef HOST_64BIT @@ -1143,11 +1232,13 @@ uint64_t GetAvailablePageFile() // Get memory status // Parameters: +// restricted_limit - The amount of physical memory in bytes that the current process is being restricted to. If non-zero, it used to calculate +// memory_load and available_physical. If zero, memory_load and available_physical is calculate based on all available memory. // memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. -void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) +void GCToOSInterface::GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { uint64_t available = 0; uint32_t load = 0; @@ -1155,16 +1246,14 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available if (memory_load != nullptr || available_physical != nullptr) { size_t used; - bool isRestricted; - uint64_t total = GetPhysicalMemoryLimit(&isRestricted); - if (isRestricted) + if (restricted_limit != 0) { // Get the physical memory in use - from it, we can get the physical memory available. // We do this only when we have the total physical memory available. if (GetPhysicalMemoryUsed(&used)) { - available = total > used ? total-used : 0; - load = (uint32_t)(((float)used * 100) / (float)total); + available = restricted_limit > used ? restricted_limit - used : 0; + load = (uint32_t)(((float)used * 100) / (float)restricted_limit); } } else @@ -1173,7 +1262,9 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available if (memory_load != NULL) { - uint32_t load = 0; + bool isRestricted; + uint64_t total = GetPhysicalMemoryLimit(&isRestricted); + if (total > available) { used = total - available; @@ -1191,7 +1282,6 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available if (available_page_file != nullptr) *available_page_file = GetAvailablePageFile(); - } // Get a high precision performance counter diff --git a/src/coreclr/src/gc/windows/gcenv.windows.cpp b/src/coreclr/src/gc/windows/gcenv.windows.cpp index 2aaf7ba19aa5e..a9504bd4b69ad 100644 --- a/src/coreclr/src/gc/windows/gcenv.windows.cpp +++ b/src/coreclr/src/gc/windows/gcenv.windows.cpp @@ -18,22 +18,12 @@ GCSystemInfo g_SystemInfo; -typedef BOOL (WINAPI *PGET_PROCESS_MEMORY_INFO)(HANDLE handle, PROCESS_MEMORY_COUNTERS* memCounters, uint32_t cb); -static PGET_PROCESS_MEMORY_INFO GCGetProcessMemoryInfo = 0; - static size_t g_RestrictedPhysicalMemoryLimit = (size_t)UINTPTR_MAX; -// For 32-bit processes the virtual address range could be smaller than the amount of physical -// memory on the machine/in the container, we need to restrict by the VM. -static bool g_UseRestrictedVirtualMemory = false; - static bool g_SeLockMemoryPrivilegeAcquired = false; static AffinitySet g_processAffinitySet; -typedef BOOL (WINAPI *PIS_PROCESS_IN_JOB)(HANDLE processHandle, HANDLE jobHandle, BOOL* result); -typedef BOOL (WINAPI *PQUERY_INFORMATION_JOB_OBJECT)(HANDLE jobHandle, JOBOBJECTINFOCLASS jobObjectInfoClass, void* lpJobObjectInfo, DWORD cbJobObjectInfoLength, LPDWORD lpReturnLength); - namespace { static bool g_fEnableGCNumaAware; @@ -297,36 +287,14 @@ static size_t GetRestrictedPhysicalMemoryLimit() uint64_t total_virtual = 0; uint64_t total_physical = 0; BOOL in_job_p = FALSE; - HINSTANCE hinstKernel32 = 0; - - PIS_PROCESS_IN_JOB GCIsProcessInJob = 0; - PQUERY_INFORMATION_JOB_OBJECT GCQueryInformationJobObject = 0; - - hinstKernel32 = LoadLibraryEx(L"kernel32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - if (!hinstKernel32) - goto exit; - GCIsProcessInJob = (PIS_PROCESS_IN_JOB)GetProcAddress(hinstKernel32, "IsProcessInJob"); - if (!GCIsProcessInJob) - goto exit; - - if (!GCIsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) + if (!IsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) goto exit; if (in_job_p) { - GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstKernel32, "K32GetProcessMemoryInfo"); - - if (!GCGetProcessMemoryInfo) - goto exit; - - GCQueryInformationJobObject = (PQUERY_INFORMATION_JOB_OBJECT)GetProcAddress(hinstKernel32, "QueryInformationJobObject"); - - if (!GCQueryInformationJobObject) - goto exit; - JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info; - if (GCQueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, &limit_info, + if (QueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info), NULL)) { size_t job_memory_limit = (size_t)UINTPTR_MAX; @@ -373,13 +341,6 @@ static size_t GetRestrictedPhysicalMemoryLimit() if (job_physical_memory_limit == (size_t)UINTPTR_MAX) { job_physical_memory_limit = 0; - - if (hinstKernel32 != 0) - { - FreeLibrary(hinstKernel32); - hinstKernel32 = 0; - GCGetProcessMemoryInfo = 0; - } } // Check to see if we are limited by VM. @@ -399,15 +360,8 @@ static size_t GetRestrictedPhysicalMemoryLimit() if (total_virtual < total_physical) { - if (hinstKernel32 != 0) - { - // We can also free the lib here - if we are limited by VM we will not be calling - // GetProcessMemoryInfo. - FreeLibrary(hinstKernel32); - GCGetProcessMemoryInfo = 0; - } - g_UseRestrictedVirtualMemory = true; - job_physical_memory_limit = (size_t)total_virtual; + // Limited by virtual address space + job_physical_memory_limit = 0; } VolatileStore(&g_RestrictedPhysicalMemoryLimit, job_physical_memory_limit); @@ -1044,7 +998,7 @@ uint32_t GCToOSInterface::GetCurrentProcessCpuCount() // Return the size of the user-mode portion of the virtual address space of this process. // Return: -// non zero if it has succeeded, 0 if it has failed +// non zero if it has succeeded, (size_t)-1 if not available size_t GCToOSInterface::GetVirtualMemoryLimit() { MEMORYSTATUSEX memStatus; @@ -1067,7 +1021,7 @@ uint64_t GCToOSInterface::GetPhysicalMemoryLimit(bool* is_restricted) size_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) { - if (is_restricted && !g_UseRestrictedVirtualMemory) + if (is_restricted) *is_restricted = true; return restricted_limit; @@ -1081,23 +1035,22 @@ uint64_t GCToOSInterface::GetPhysicalMemoryLimit(bool* is_restricted) // Get memory status // Parameters: +// restricted_limit - The amount of physical memory in bytes that the current process is being restricted to. If non-zero, it used to calculate +// memory_load and available_physical. If zero, memory_load and available_physical is calculate based on all available memory. // memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. -void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) +void GCToOSInterface::GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { - uint64_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) { size_t workingSetSize; BOOL status = FALSE; - if (!g_UseRestrictedVirtualMemory) - { - PROCESS_MEMORY_COUNTERS pmc; - status = GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); - workingSetSize = pmc.WorkingSetSize; - } + + PROCESS_MEMORY_COUNTERS pmc; + status = GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); + workingSetSize = pmc.WorkingSetSize; if(status) { @@ -1123,9 +1076,10 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available MEMORYSTATUSEX ms; ::GetProcessMemoryLoad(&ms); - if (g_UseRestrictedVirtualMemory) + // For 32-bit processes the virtual address range could be smaller than the amount of physical + // memory on the machine/in the container, we need to restrict by the VM. + if (ms.ullTotalVirtual < ms.ullTotalPhys) { - _ASSERTE (ms.ullTotalVirtual == restricted_limit); if (memory_load != NULL) *memory_load = (uint32_t)((float)(ms.ullTotalVirtual - ms.ullAvailVirtual) * 100.0 / (float)ms.ullTotalVirtual); if (available_physical != NULL) diff --git a/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp index aac6e24ecea11..1b6e1fa820410 100644 --- a/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp +++ b/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp @@ -116,6 +116,34 @@ bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutable) { result = false; } +#elif defined(__sun) + const char *path; + if ((path = getexecname()) == NULL) + { + result = false; + } + else if (*path != '/') + { + char *cwd; + if ((cwd = getcwd(NULL, PATH_MAX)) == NULL) + { + result = false; + } + else + { + entrypointExecutable + .assign(cwd) + .append("/") + .append(path); + result = true; + free(cwd); + } + } + else + { + entrypointExecutable.assign(path); + result = true; + } #else #if HAVE_GETAUXVAL && defined(AT_EXECFN) diff --git a/src/coreclr/src/inc/CrstTypes.def b/src/coreclr/src/inc/CrstTypes.def index 06f900a79be90..1cd949cbe97ff 100644 --- a/src/coreclr/src/inc/CrstTypes.def +++ b/src/coreclr/src/inc/CrstTypes.def @@ -283,9 +283,6 @@ Crst GCCover AcquiredBefore LoaderHeap CodeVersioning End -Crst GCMemoryPressure -End - Crst GlobalStrLiteralMap AcquiredBefore HandleTable IbcProfile SyncBlockCache SystemDomainDelayedUnloadList ThreadStore UniqueStack End diff --git a/src/coreclr/src/inc/appxutil.h b/src/coreclr/src/inc/appxutil.h index c5fce6967eed7..644d3b9fce04a 100644 --- a/src/coreclr/src/inc/appxutil.h +++ b/src/coreclr/src/inc/appxutil.h @@ -14,8 +14,6 @@ //--------------------------------------------------------------------------------------------- // Forward declarations -template -class NewArrayHolder; BOOL WinRTSupported(); diff --git a/src/coreclr/src/inc/bundle.h b/src/coreclr/src/inc/bundle.h new file mode 100644 index 0000000000000..00fc186ab9ff0 --- /dev/null +++ b/src/coreclr/src/inc/bundle.h @@ -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. + +/***************************************************************************** + ** ** + ** bundle.h - Information about applications bundled as a single-file ** + ** ** + *****************************************************************************/ + +#ifndef _BUNDLE_H_ +#define _BUNDLE_H_ + +#include + +class Bundle; + +struct BundleFileLocation +{ + INT64 Size; + INT64 Offset; + + BundleFileLocation() + { + LIMITED_METHOD_CONTRACT; + + Size = 0; + Offset = 0; + } + + static BundleFileLocation Invalid() { LIMITED_METHOD_CONTRACT; return BundleFileLocation(); } + + const SString &Path() const; + + bool IsValid() const { LIMITED_METHOD_CONTRACT; return Offset != 0; } +}; + +typedef bool(__stdcall BundleProbe)(LPCWSTR, INT64*, INT64*); + +class Bundle +{ +public: + Bundle(LPCWSTR bundlePath, BundleProbe *probe); + BundleFileLocation Probe(LPCWSTR path, bool pathIsBundleRelative = false) const; + + const SString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; } + const SString &BasePath() const { LIMITED_METHOD_CONTRACT; return m_basePath; } + + static Bundle* AppBundle; // The BundleInfo for the current app, initialized by coreclr_initialize. + static bool AppIsBundle() { LIMITED_METHOD_CONTRACT; return AppBundle != nullptr; } + static BundleFileLocation ProbeAppBundle(LPCWSTR path, bool pathIsBundleRelative = false); + +private: + + SString m_path; // The path to single-file executable + BundleProbe *m_probe; + + SString m_basePath; // The prefix to denote a path within the bundle +}; + +#endif // _BUNDLE_H_ +// EOF ======================================================================= diff --git a/src/coreclr/src/inc/clrconfigvalues.h b/src/coreclr/src/inc/clrconfigvalues.h index 51b47e4f7ec19..109c3c8355301 100644 --- a/src/coreclr/src/inc/clrconfigvalues.h +++ b/src/coreclr/src/inc/clrconfigvalues.h @@ -253,7 +253,6 @@ CONFIG_DWORD_INFO(INTERNAL_SuppressLockViolationsOnReentryFromOS, W("SuppressLoc CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), "") RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behavior", CLRConfig::EEConfig_default) CONFIG_DWORD_INFO_EX(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "", CLRConfig::EEConfig_default) -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_FailFastOnCorruptedStateException, W("FailFastOnCorruptedStateException"), 0, "Failfast if a CSE is encountered", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "", CLRConfig::EEConfig_default) RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "", CLRConfig::EEConfig_default) @@ -620,6 +619,16 @@ CONFIG_DWORD_INFO(INTERNAL_OSR_LowId, W("OSR_LowId"), (DWORD)-1, "Low end of ena CONFIG_DWORD_INFO(INTERNAL_OSR_HighId, W("OSR_HighId"), 10000000, "High end of enabled patchpoint range (inclusive)"); #endif +/// +/// Profile Guided Opts +/// +#ifdef FEATURE_PGO +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_PGODataPath, W("PGODataPath"), "Read/Write PGO data from/to the indicated file.", CLRConfig::EEConfig_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ReadPGOData, W("ReadPGOData"), 0, "Read PGO data") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_WritePGOData, W("WritePGOData"), 0, "Write PGO data") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TieredPGO, W("TieredPGO"), 0, "Instrument Tier0 code and make counts available to Tier1") +#endif + /// /// Entry point slot backpatch /// @@ -706,7 +715,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers" // // Diagnostics Server // -RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_DiagnosticsServerAddress, W("DOTNET_DiagnosticsServerAddress"), "The full path including filename for the OS transport (NamedPipe on Windows; Unix Domain Socket on Linux) to be used by the Diagnostics Server", CLRConfig::DontPrependCOMPlus_); +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_DiagnosticsMonitorAddress, W("DOTNET_DiagnosticsMonitorAddress"), "NamedPipe path without '\\\\.\\pipe\\' on Windows; Full path of Unix Domain Socket on Linux/Unix. Used for Diagnostics Monitoring Agents.", CLRConfig::DontPrependCOMPlus_); // // LTTng diff --git a/src/coreclr/src/inc/cordebug.idl b/src/coreclr/src/inc/cordebug.idl index 87e1458cfc91d..be745368f2bb3 100644 --- a/src/coreclr/src/inc/cordebug.idl +++ b/src/coreclr/src/inc/cordebug.idl @@ -2567,7 +2567,8 @@ typedef enum CorGCReferenceType CorHandleStrongDependent = 1<<6, CorHandleStrongAsyncPinned = 1<<7, CorHandleStrongSizedByref = 1<<8, - CorHandleWeakWinRT = 1<<9, + CorHandleWeakNativeCom = 1<<9, + CorHandleWeakWinRT = CorHandleWeakNativeCom, CorReferenceStack = 0x80000001, CorReferenceFinalizer = 80000002, diff --git a/src/coreclr/src/inc/corhlprpriv.h b/src/coreclr/src/inc/corhlprpriv.h index 8fcafd08d93c3..7b9e5f1f88567 100644 --- a/src/coreclr/src/inc/corhlprpriv.h +++ b/src/coreclr/src/inc/corhlprpriv.h @@ -507,6 +507,7 @@ class CQuickArrayList : protected CQuickArray using CQuickArray::AllocNoThrow; using CQuickArray::ReSizeNoThrow; using CQuickArray::MaxSize; + using CQuickArray::Ptr; CQuickArrayList() : m_curSize(0) diff --git a/src/coreclr/src/inc/corinfoinstructionset.h b/src/coreclr/src/inc/corinfoinstructionset.h index 8040819439a00..8e667bc29b07b 100644 --- a/src/coreclr/src/inc/corinfoinstructionset.h +++ b/src/coreclr/src/inc/corinfoinstructionset.h @@ -274,6 +274,8 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_POPCNT); + if (resultflags.HasInstructionSet(InstructionSet_Vector256) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_Vector256); #endif // TARGET_AMD64 #ifdef TARGET_X86 if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) @@ -304,6 +306,8 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_POPCNT); + if (resultflags.HasInstructionSet(InstructionSet_Vector256) && !resultflags.HasInstructionSet(InstructionSet_AVX)) + resultflags.RemoveInstructionSet(InstructionSet_Vector256); #endif // TARGET_X86 } while (!oldflags.Equals(resultflags)); diff --git a/src/coreclr/src/inc/corpriv.h b/src/coreclr/src/inc/corpriv.h index f0261b3381cc4..6b92458ec40f1 100644 --- a/src/coreclr/src/inc/corpriv.h +++ b/src/coreclr/src/inc/corpriv.h @@ -25,9 +25,6 @@ interface IAssemblyName; -// PE images loaded through the runtime. -typedef struct _dummyCOR { BYTE b; } *HCORMODULE; - class UTSemReadWrite; // Helper function to get a pointer to the Dispenser interface. @@ -70,11 +67,6 @@ STDAPI GetAssemblyMDInternalImport( // Return code. REFIID riid, // [IN] The interface desired. IUnknown **ppIUnk); // [OUT] Return interface on success. -HRESULT GetAssemblyMDInternalImportFromImage( - HCORMODULE hImage, //[IN] pointer to module handle to get the metadata from. - REFIID riid, //[IN] The interface desired. - IUnknown **ppIUnk); //[OUT] Return Interface on success. - STDAPI GetAssemblyMDInternalImportByStream( // Return code. IStream *pIStream, // [IN] The IStream for the file UINT64 AssemblyId, // [IN] Unique Id for the assembly @@ -303,60 +295,6 @@ typedef enum CorOpenFlagsInternal #define COR_MODULE_CLASS "" #define COR_WMODULE_CLASS W("") -STDAPI RuntimeOpenImage(LPCWSTR pszFileName, HCORMODULE* hHandle); -STDAPI RuntimeOpenImageInternal(LPCWSTR pszFileName, HCORMODULE* hHandle, - DWORD *pdwLength, MDInternalImportFlags flags, HANDLE hFile = INVALID_HANDLE_VALUE); -STDAPI RuntimeOpenImageByStream(IStream* pIStream, UINT64 AssemblyId, DWORD dwModuleId, - HCORMODULE* hHandle, DWORD *pdwLength, MDInternalImportFlags flags); - -void RuntimeAddRefHandle(HCORMODULE hHandle); -STDAPI RuntimeReleaseHandle(HCORMODULE hHandle); -STDAPI RuntimeGetImageBase(HCORMODULE hHandle, LPVOID* base, BOOL bMapped, COUNT_T* dwSize); -STDAPI RuntimeGetImageKind(HCORMODULE hHandle, DWORD* pdwKind, DWORD* pdwMachine); -STDAPI RuntimeOSHandle(HCORMODULE hHandle, HMODULE* hModule); -STDAPI RuntimeGetAssemblyStrongNameHashForModule(HCORMODULE hModule, - IMetaDataImport *pMDimport, - BYTE *pbSNHash, - DWORD *pcbSNHash); -STDAPI RuntimeGetMDInternalImport(HCORMODULE hHandle, - MDInternalImportFlags flags, - IMDInternalImport** ppMDImport); - -FORCEINLINE -void ReleaseHCorModule(HCORMODULE hModule) -{ - HRESULT hr = RuntimeReleaseHandle(hModule); - _ASSERTE(SUCCEEDED(hr)); -} - -typedef Wrapper, ReleaseHCorModule, (UINT_PTR) NULL> HCORMODULEHolder; - - -// =========================================================================== -// ISNAssemblySignature (similar to IAssemblySignature in V1) -// -// This is a private interface that allows querying of the strong name -// signature. -// This can be used for (strong-named) assemblies added to the GAC as -// a unique identifier. -// - -// {848845BC-0C4A-42e3-8915-DC850112443D} -EXTERN_GUID(IID_ISNAssemblySignature, 0x848845BC, 0x0C4A, 0x42e3, 0x89, 0x15, 0xDC, 0x85, 0x01, 0x12, 0x44, 0x3D); - -#undef INTERFACE -#define INTERFACE ISNAssemblySignature -DECLARE_INTERFACE_(ISNAssemblySignature, IUnknown) -{ - // Returns the strong-name signature if the assembly is strong-name-signed - // Returns the MVID if the assembly is delay-signed. - // Fails if the assembly is not signed at all. - STDMETHOD(GetSNAssemblySignature) ( - BYTE *pbSig, // [IN, OUT] Buffer to write signature - DWORD *pcbSig // [IN, OUT] Size of buffer, bytes written - ) PURE; -}; - //------------------------------------- //--- ICeeGenInternal //------------------------------------- diff --git a/src/coreclr/src/inc/crsttypes.h b/src/coreclr/src/inc/crsttypes.h index 98d24c2efafca..dc8e5a94296d2 100644 --- a/src/coreclr/src/inc/crsttypes.h +++ b/src/coreclr/src/inc/crsttypes.h @@ -69,109 +69,108 @@ enum CrstType CrstFuncPtrStubs = 50, CrstFusionAppCtx = 51, CrstGCCover = 52, - CrstGCMemoryPressure = 53, - CrstGlobalStrLiteralMap = 54, - CrstHandleTable = 55, - CrstHostAssemblyMap = 56, - CrstHostAssemblyMapAdd = 57, - CrstIbcProfile = 58, - CrstIJWFixupData = 59, - CrstIJWHash = 60, - CrstILStubGen = 61, - CrstInlineTrackingMap = 62, - CrstInstMethodHashTable = 63, - CrstInterfaceVTableMap = 64, - CrstInterop = 65, - CrstInteropData = 66, - CrstIOThreadpoolWorker = 67, - CrstIsJMCMethod = 68, - CrstISymUnmanagedReader = 69, - CrstJit = 70, - CrstJitGenericHandleCache = 71, - CrstJitInlineTrackingMap = 72, - CrstJitPatchpoint = 73, - CrstJitPerf = 74, - CrstJumpStubCache = 75, - CrstLeafLock = 76, - CrstListLock = 77, - CrstLoaderAllocator = 78, - CrstLoaderAllocatorReferences = 79, - CrstLoaderHeap = 80, - CrstMda = 81, - CrstMetadataTracker = 82, - CrstMethodDescBackpatchInfoTracker = 83, - CrstModIntPairList = 84, - CrstModule = 85, - CrstModuleFixup = 86, - CrstModuleLookupTable = 87, - CrstMulticoreJitHash = 88, - CrstMulticoreJitManager = 89, - CrstMUThunkHash = 90, - CrstNativeBinderInit = 91, - CrstNativeImageCache = 92, - CrstNativeImageEagerFixups = 93, - CrstNls = 94, - CrstNotifyGdb = 95, - CrstObjectList = 96, - CrstOnEventManager = 97, - CrstPatchEntryPoint = 98, - CrstPEImage = 99, - CrstPEImagePDBStream = 100, - CrstPendingTypeLoadEntry = 101, - CrstPinHandle = 102, - CrstPinnedByrefValidation = 103, - CrstProfilerGCRefDataFreeList = 104, - CrstProfilingAPIStatus = 105, - CrstPublisherCertificate = 106, - CrstRCWCache = 107, - CrstRCWCleanupList = 108, - CrstRCWRefCache = 109, - CrstReadyToRunEntryPointToMethodDescMap = 110, - CrstReDacl = 111, - CrstReflection = 112, - CrstReJITGlobalRequest = 113, - CrstRemoting = 114, - CrstRetThunkCache = 115, - CrstRWLock = 116, - CrstSavedExceptionInfo = 117, - CrstSaveModuleProfileData = 118, - CrstSecurityStackwalkCache = 119, - CrstSharedAssemblyCreate = 120, - CrstSigConvert = 121, - CrstSingleUseLock = 122, - CrstSpecialStatics = 123, - CrstSqmManager = 124, - CrstStackSampler = 125, - CrstStressLog = 126, - CrstStrongName = 127, - CrstStubCache = 128, - CrstStubDispatchCache = 129, - CrstStubUnwindInfoHeapSegments = 130, - CrstSyncBlockCache = 131, - CrstSyncHashLock = 132, - CrstSystemBaseDomain = 133, - CrstSystemDomain = 134, - CrstSystemDomainDelayedUnloadList = 135, - CrstThreadIdDispenser = 136, - CrstThreadpoolEventCache = 137, - CrstThreadpoolTimerQueue = 138, - CrstThreadpoolWaitThreads = 139, - CrstThreadpoolWorker = 140, - CrstThreadStaticDataHashTable = 141, - CrstThreadStore = 142, - CrstTieredCompilation = 143, - CrstTPMethodTable = 144, - CrstTypeEquivalenceMap = 145, - CrstTypeIDMap = 146, - CrstUMEntryThunkCache = 147, - CrstUMThunkHash = 148, - CrstUniqueStack = 149, - CrstUnresolvedClassLock = 150, - CrstUnwindInfoTableLock = 151, - CrstVSDIndirectionCellLock = 152, - CrstWinRTFactoryCache = 153, - CrstWrapperTemplate = 154, - kNumberOfCrstTypes = 155 + CrstGlobalStrLiteralMap = 53, + CrstHandleTable = 54, + CrstHostAssemblyMap = 55, + CrstHostAssemblyMapAdd = 56, + CrstIbcProfile = 57, + CrstIJWFixupData = 58, + CrstIJWHash = 59, + CrstILStubGen = 60, + CrstInlineTrackingMap = 61, + CrstInstMethodHashTable = 62, + CrstInterfaceVTableMap = 63, + CrstInterop = 64, + CrstInteropData = 65, + CrstIOThreadpoolWorker = 66, + CrstIsJMCMethod = 67, + CrstISymUnmanagedReader = 68, + CrstJit = 69, + CrstJitGenericHandleCache = 70, + CrstJitInlineTrackingMap = 71, + CrstJitPatchpoint = 72, + CrstJitPerf = 73, + CrstJumpStubCache = 74, + CrstLeafLock = 75, + CrstListLock = 76, + CrstLoaderAllocator = 77, + CrstLoaderAllocatorReferences = 78, + CrstLoaderHeap = 79, + CrstMda = 80, + CrstMetadataTracker = 81, + CrstMethodDescBackpatchInfoTracker = 82, + CrstModIntPairList = 83, + CrstModule = 84, + CrstModuleFixup = 85, + CrstModuleLookupTable = 86, + CrstMulticoreJitHash = 87, + CrstMulticoreJitManager = 88, + CrstMUThunkHash = 89, + CrstNativeBinderInit = 90, + CrstNativeImageCache = 91, + CrstNativeImageEagerFixups = 92, + CrstNls = 93, + CrstNotifyGdb = 94, + CrstObjectList = 95, + CrstOnEventManager = 96, + CrstPatchEntryPoint = 97, + CrstPEImage = 98, + CrstPEImagePDBStream = 99, + CrstPendingTypeLoadEntry = 100, + CrstPinHandle = 101, + CrstPinnedByrefValidation = 102, + CrstProfilerGCRefDataFreeList = 103, + CrstProfilingAPIStatus = 104, + CrstPublisherCertificate = 105, + CrstRCWCache = 106, + CrstRCWCleanupList = 107, + CrstRCWRefCache = 108, + CrstReadyToRunEntryPointToMethodDescMap = 109, + CrstReDacl = 110, + CrstReflection = 111, + CrstReJITGlobalRequest = 112, + CrstRemoting = 113, + CrstRetThunkCache = 114, + CrstRWLock = 115, + CrstSavedExceptionInfo = 116, + CrstSaveModuleProfileData = 117, + CrstSecurityStackwalkCache = 118, + CrstSharedAssemblyCreate = 119, + CrstSigConvert = 120, + CrstSingleUseLock = 121, + CrstSpecialStatics = 122, + CrstSqmManager = 123, + CrstStackSampler = 124, + CrstStressLog = 125, + CrstStrongName = 126, + CrstStubCache = 127, + CrstStubDispatchCache = 128, + CrstStubUnwindInfoHeapSegments = 129, + CrstSyncBlockCache = 130, + CrstSyncHashLock = 131, + CrstSystemBaseDomain = 132, + CrstSystemDomain = 133, + CrstSystemDomainDelayedUnloadList = 134, + CrstThreadIdDispenser = 135, + CrstThreadpoolEventCache = 136, + CrstThreadpoolTimerQueue = 137, + CrstThreadpoolWaitThreads = 138, + CrstThreadpoolWorker = 139, + CrstThreadStaticDataHashTable = 140, + CrstThreadStore = 141, + CrstTieredCompilation = 142, + CrstTPMethodTable = 143, + CrstTypeEquivalenceMap = 144, + CrstTypeIDMap = 145, + CrstUMEntryThunkCache = 146, + CrstUMThunkHash = 147, + CrstUniqueStack = 148, + CrstUnresolvedClassLock = 149, + CrstUnwindInfoTableLock = 150, + CrstVSDIndirectionCellLock = 151, + CrstWinRTFactoryCache = 152, + CrstWrapperTemplate = 153, + kNumberOfCrstTypes = 154 }; #endif // __CRST_TYPES_INCLUDED @@ -235,7 +234,6 @@ int g_rgCrstLevelMap[] = 7, // CrstFuncPtrStubs 5, // CrstFusionAppCtx 11, // CrstGCCover - 0, // CrstGCMemoryPressure 13, // CrstGlobalStrLiteralMap 1, // CrstHandleTable 0, // CrstHostAssemblyMap @@ -395,7 +393,6 @@ LPCSTR g_rgCrstNameMap[] = "CrstFuncPtrStubs", "CrstFusionAppCtx", "CrstGCCover", - "CrstGCMemoryPressure", "CrstGlobalStrLiteralMap", "CrstHandleTable", "CrstHostAssemblyMap", diff --git a/src/coreclr/src/inc/daccess.h b/src/coreclr/src/inc/daccess.h index 2c68abff92c18..f2b37c32db749 100644 --- a/src/coreclr/src/inc/daccess.h +++ b/src/coreclr/src/inc/daccess.h @@ -629,6 +629,9 @@ typedef struct _DacGlobals ULONG fn__Unknown_AddRefSpecial; ULONG fn__Unknown_AddRefInner; #endif +#ifdef FEATURE_COMWRAPPERS + ULONG fn__ManagedObjectWrapper_QueryInterface; +#endif // Vtable pointer values for all classes that must // be instanted using vtable pointers as the identity. diff --git a/src/coreclr/src/inc/ex.h b/src/coreclr/src/inc/ex.h index 21ce9d3d4b0ec..6d008c6febecf 100644 --- a/src/coreclr/src/inc/ex.h +++ b/src/coreclr/src/inc/ex.h @@ -278,17 +278,13 @@ class Exception }; #if 1 -template -inline void Exception__Delete(T* pvMemory); -template <> -inline void Exception__Delete(Exception* pvMemory) +inline void Exception__Delete(Exception* pvMemory) { Exception::Delete(pvMemory); } -NEW_WRAPPER_TEMPLATE1(ExceptionHolderTemplate, Exception__Delete<_TYPE>); -typedef ExceptionHolderTemplate ExceptionHolder; +using ExceptionHolder = SpecializedWrapper; #else //------------------------------------------------------------------------------ @@ -710,93 +706,17 @@ class CAutoTryCleanup EX_RETHROW; \ } \ -// Don't use this - use RethrowCorruptingExceptions (see below) instead. #define SwallowAllExceptions ; -////////////////////////////////////////////////////////////////////// -// -// Corrupted State Exception Support -// -///////////////////////////////////////////////////////////////////// - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - -#define CORRUPTING_EXCEPTIONS_ONLY(expr) expr -#define COMMA_CORRUPTING_EXCEPTIONS_ONLY(expr) ,expr - -// EX_END_CATCH has been modified to not swallow Corrupting Exceptions (CE) when one of the -// following arguments are passed to it: -// -// 1) RethrowTerminalExceptions - rethrows both terminal and corrupting exceptions -// 2) RethrowCorruptingExceptions - swallows all exceptions exception corrupting exceptions. This SHOULD BE USED instead of SwallowAllExceptions. -// 3) RethrowTerminalExceptionsEx - same as (1) but rethrow of CE can be controlled via a condition. -// 4) RethrowCorruptingExceptionsEx - same as (2) but rethrow of CE can be controlled via a condition. -// -// By default, if a CE is encountered when one of the above policies are applied, the runtime will -// ensure that the CE propagates up the stack and not get swallowed unless the developer chooses to override the behaviour. -// This can be done by using the "Ex" versions above that take a conditional which evaluates to a BOOL. In such a case, -// the CE will *only* be rethrown if the conditional evalutes to TRUE. For examples, refer to COMToCLRWorker or -// DispatchInfo::InvokeMember implementations. -// -// SET_CE_RETHROW_FLAG_FOR_EX_CATCH macros helps evaluate if the CE is to be rethrown or not. This has been redefined in -// Clrex.h to add the condition of evaluating the throwable as well (which is not available outside the VM folder). -// -// Passing FALSE as the second argument to IsProcessCorruptedStateException implies that SET_CE_RETHROW_FLAG_FOR_EX_CATCH -// will ensure that we dont rethrow SO and allow EX_ENDTRY to SO specific processing. If none is done, then EX_ENDTRY will -// rethrow SO. By that time stack has been reclaimed and thus, throwing SO will be safe. -// -// We also check the global override flag incase it has been set to force pre-V4 beahviour. "0" implies it has not -// been overriden. -#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) ((((expr) == TRUE) && \ - (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy) == 0) && \ - IsProcessCorruptedStateException(GetCurrentExceptionCode(), FALSE))) - -// This rethrow policy can be used in EX_END_CATCH to swallow all exceptions except the corrupting ones. -// This macro can be used to rethrow the CE based upon a BOOL condition. -#define RethrowCorruptingExceptionsEx(expr) \ - if (SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr)) \ - { \ - STATIC_CONTRACT_THROWS_TERMINAL; \ - EX_RETHROW; \ - } - -#define RethrowCorruptingExceptionsExAndHookRethrow(shouldRethrowExpr, aboutToRethrowExpr) \ - if (SET_CE_RETHROW_FLAG_FOR_EX_CATCH(shouldRethrowExpr)) \ - { \ - STATIC_CONTRACT_THROWS_TERMINAL; \ - aboutToRethrowExpr; \ - EX_RETHROW; \ - } - -#else // !FEATURE_CORRUPTING_EXCEPTIONS - -#define CORRUPTING_EXCEPTIONS_ONLY(expr) -#define COMMA_CORRUPTING_EXCEPTIONS_ONLY(expr) - -// When we dont have support for CE, just map it to SwallowAllExceptions -#define RethrowCorruptingExceptionsEx(expr) SwallowAllExceptions -#define RethrowCorruptingExceptionsExAndHookRethrow(shouldRethrowExpr, aboutToRethrowExpr) SwallowAllExceptions -#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) !TRUE -#endif // FEATURE_CORRUPTING_EXCEPTIONS - -// Map to RethrowCorruptingExceptionsEx so that it does the "right" thing -#define RethrowCorruptingExceptions RethrowCorruptingExceptionsEx(TRUE) - -// This macro can be used to rethrow the CE based upon a BOOL condition. It will continue to rethrow terminal -// exceptions unconditionally. -#define RethrowTerminalExceptionsEx(expr) \ - if (GET_EXCEPTION()->IsTerminal() || \ - SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr)) \ +// When applied to EX_END_CATCH, this policy will always rethrow Terminal exceptions if they are +// encountered. +#define RethrowTerminalExceptions \ + if (GET_EXCEPTION()->IsTerminal()) \ { \ STATIC_CONTRACT_THROWS_TERMINAL; \ EX_RETHROW; \ } \ - -// When applied to EX_END_CATCH, this policy will always rethrow Terminal and Corrupting exceptions if they are -// encountered. -#define RethrowTerminalExceptions RethrowTerminalExceptionsEx(TRUE) - // Special define to be used in EEStartup that will also check for VM initialization before // commencing on a path that may use the managed thread object. #define RethrowTerminalExceptionsWithInitCheck \ diff --git a/src/coreclr/src/inc/holder.h b/src/coreclr/src/inc/holder.h index c1f86b1ee0ff8..a5781d5570dde 100644 --- a/src/coreclr/src/inc/holder.h +++ b/src/coreclr/src/inc/holder.h @@ -824,84 +824,68 @@ class Wrapper : public BaseWrapper, #define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) #endif -//--------------------------------------------------------------------------------------- -// -// New template wrapper type macros. These save some effort when specializing -// existing holder templates. (We would rather use a construct like: -// -// template -// typedef Holder<...> NewHolder; -// -// But this construct doesn't exist in C++. These macros ease some of the cruft necessary -// to get similar functionality out of class templates. -//----------------------------------------------------------------------------- +template +class SpecializedWrapper : public Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> +{ + using BaseT = Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL>; +public: + FORCEINLINE SpecializedWrapper() : BaseT(NULL, FALSE) + { + STATIC_CONTRACT_WRAPPER; + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) + } + FORCEINLINE SpecializedWrapper(_TYPE* value) : BaseT(value) + { + STATIC_CONTRACT_WRAPPER; + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) + } + FORCEINLINE SpecializedWrapper(_TYPE* value, BOOL takeOwnership) : BaseT(value, takeOwnership) + { + STATIC_CONTRACT_WRAPPER; + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) + } + FORCEINLINE ~SpecializedWrapper() + { + } -// Dev10 VC++ has some of the new C++0x language extensions. Of particular interest here: -// rvalue references, which enables differentiation between named (lvalue) and -// temporary (rvalue) object references, enabling move semantics and perfect forwarding. -// See http://msdn.microsoft.com/en-us/library/dd293668.aspx for more information. - -// Enable copy construction and assignment from temporary objects. This permits Wrapper objects -// to be returned from methods, and for move assignment. -#define NEW_WRAPPER_TEMPLATE_RVALREF_METHODS(_NAME) \ - public: \ - FORCEINLINE _NAME(_NAME && other) \ - : BaseT(NULL, FALSE) \ - { \ - STATIC_CONTRACT_WRAPPER; \ - INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ - *this = std::move(other); \ - } \ - FORCEINLINE _NAME& operator=(_NAME && other) \ - { \ - std::swap(BaseT::m_value, other.BaseT::m_value); \ - std::swap(BaseT::m_acquired, other.BaseT::m_acquired); \ - return *this; \ - } + SpecializedWrapper(SpecializedWrapper const &) = delete; + SpecializedWrapper & operator=(SpecializedWrapper const &) = delete; -#define NEW_WRAPPER_TEMPLATE1(_NAME, _RELEASEF) \ - template \ - class _NAME : public Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> \ - { \ - typedef Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> BaseT; \ - public: \ - FORCEINLINE _NAME() : BaseT(NULL, FALSE) \ - { \ - STATIC_CONTRACT_WRAPPER; \ - INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ - } \ - FORCEINLINE _NAME(_TYPE* value) : BaseT(value) \ - { \ - STATIC_CONTRACT_WRAPPER; \ - INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ - } \ - FORCEINLINE _NAME(_TYPE* value, BOOL takeOwnership) : BaseT(value, takeOwnership) \ - { \ - STATIC_CONTRACT_WRAPPER; \ - INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ - } \ - FORCEINLINE ~_NAME() \ - { \ - } \ - FORCEINLINE _NAME& operator=(_TYPE * value) \ - { \ - STATIC_CONTRACT_WRAPPER; \ - BaseT::operator=(value); \ - return *this; \ - } \ - /* Since operator& is overloaded we need a way to get a type safe this pointer. */ \ - FORCEINLINE _NAME* GetAddr() \ - { \ - STATIC_CONTRACT_LEAF; \ - return this; \ - } \ - NEW_WRAPPER_TEMPLATE_RVALREF_METHODS(_NAME) \ - HIDE_GENERATED_METHODS(_NAME) \ - private: \ - /* m_ppValue: Do not use from source code: Only for convenient use from debugger */ \ - /* watch windows - saves five mouseclicks when inspecting holders. */ \ - INDEBUG_AND_WINDOWS_FOR_HOLDERS(_TYPE ** m_pvalue;) \ - }; + FORCEINLINE SpecializedWrapper& operator=(_TYPE * value) + { + STATIC_CONTRACT_WRAPPER; + BaseT::operator=(value); + return *this; + } + + FORCEINLINE SpecializedWrapper(SpecializedWrapper && other) + : BaseT(NULL, FALSE) + { + STATIC_CONTRACT_WRAPPER; + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) + *this = std::move(other); + } + + FORCEINLINE SpecializedWrapper& operator=(SpecializedWrapper && other) + { + BaseT::m_value = std::move(other.BaseT::m_value); + BaseT::m_acquired = std::move(other.BaseT::m_acquired); + other.BaseT::m_value = nullptr; + other.BaseT::m_acquired = FALSE; + return *this; + } + + /* Since operator& is overloaded we need a way to get a type safe this pointer. */ + FORCEINLINE SpecializedWrapper* GetAddr() + { + STATIC_CONTRACT_LEAF; + return this; + } + private: + /* m_ppValue: Do not use from source code: Only for convenient use from debugger */ + /* watch windows - saves five mouseclicks when inspecting holders. */ + INDEBUG_AND_WINDOWS_FOR_HOLDERS(_TYPE ** m_pvalue;) +}; //----------------------------------------------------------------------------- // NOTE: THIS IS UNSAFE TO USE IN THE VM for interop COM objects!! @@ -930,11 +914,14 @@ FORCEINLINE void DoTheRelease(TYPE *value) } } -NEW_WRAPPER_TEMPLATE1(DoNothingHolder, DoNothing<_TYPE*>); +template +using DoNothingHolder = SpecializedWrapper<_TYPE, DoNothing<_TYPE*>>; -NEW_WRAPPER_TEMPLATE1(ReleaseHolder, DoTheRelease<_TYPE>); +template +using ReleaseHolder = SpecializedWrapper<_TYPE, DoTheRelease<_TYPE>>; -NEW_WRAPPER_TEMPLATE1(NonVMComHolder, DoTheRelease<_TYPE>); +template +using NonVMComHolder = SpecializedWrapper<_TYPE, DoTheRelease<_TYPE>>; //----------------------------------------------------------------------------- @@ -957,7 +944,8 @@ FORCEINLINE void StubRelease(TYPE* value) value->DecRef(); } -NEW_WRAPPER_TEMPLATE1(StubHolder, StubRelease<_TYPE>); +template +using StubHolder = SpecializedWrapper<_TYPE, StubRelease<_TYPE>>; //----------------------------------------------------------------------------- // CoTaskMemHolder : CoTaskMemAlloc allocated memory holder @@ -974,7 +962,8 @@ FORCEINLINE void DeleteCoTaskMem(TYPE *value) CoTaskMemFree(value); } -NEW_WRAPPER_TEMPLATE1(CoTaskMemHolder, DeleteCoTaskMem<_TYPE>); +template +using CoTaskMemHolder = SpecializedWrapper<_TYPE, DeleteCoTaskMem<_TYPE>>; //----------------------------------------------------------------------------- // NewHolder : New'ed memory holder @@ -997,7 +986,8 @@ FORCEINLINE void Delete(TYPE *value) delete value; } -NEW_WRAPPER_TEMPLATE1(NewHolder, Delete<_TYPE>); +template +using NewHolder = SpecializedWrapper<_TYPE, Delete<_TYPE>>; //----------------------------------------------------------------------------- // NewExecutableHolder : New'ed memory holder for executable memory. @@ -1009,7 +999,8 @@ NEW_WRAPPER_TEMPLATE1(NewHolder, Delete<_TYPE>); // IJW template void DeleteExecutable(T *p); -NEW_WRAPPER_TEMPLATE1(NewExecutableHolder, DeleteExecutable<_TYPE>); +template +using NewExecutableHolder = SpecializedWrapper<_TYPE, DeleteExecutable<_TYPE>>; //----------------------------------------------------------------------------- // NewArrayHolder : New []'ed pointer holder @@ -1026,7 +1017,8 @@ FORCEINLINE void DeleteArray(TYPE *value) value = NULL; } -NEW_WRAPPER_TEMPLATE1(NewArrayHolder, DeleteArray<_TYPE>); +template +using NewArrayHolder = SpecializedWrapper<_TYPE, DeleteArray<_TYPE>>; typedef NewArrayHolder AStringHolder; typedef NewArrayHolder WStringHolder; @@ -1113,8 +1105,10 @@ namespace detail } #undef VISIBLE -NEW_WRAPPER_TEMPLATE1(ResetPointerHolder, detail::ZeroMem<_TYPE>::Invoke); -NEW_WRAPPER_TEMPLATE1(FieldNuller, detail::ZeroMem<_TYPE>::Invoke); +template +using ResetPointerHolder = SpecializedWrapper<_TYPE, detail::ZeroMem<_TYPE>::Invoke>; +template +using FieldNuller = SpecializedWrapper<_TYPE, detail::ZeroMem<_TYPE>::Invoke>; //----------------------------------------------------------------------------- // Wrap win32 functions using HANDLE @@ -1157,7 +1151,8 @@ typedef Wrapper, HolderFreeLibrary, NULL> HModuleHol template FORCEINLINE void DoLocalFree(T* pMem) { (LocalFree)((HLOCAL)pMem); } -NEW_WRAPPER_TEMPLATE1(LocalAllocHolder, DoLocalFree<_TYPE>); +template +using LocalAllocHolder = SpecializedWrapper<_TYPE, DoLocalFree<_TYPE>>; inline void BoolSet( _Out_ bool * val ) { *val = true; } inline void BoolUnset( _Out_ bool * val ) { *val = false; } diff --git a/src/coreclr/src/inc/pedecoder.h b/src/coreclr/src/inc/pedecoder.h index ad0e77e532c15..c4f4e92b6b613 100644 --- a/src/coreclr/src/inc/pedecoder.h +++ b/src/coreclr/src/inc/pedecoder.h @@ -95,6 +95,8 @@ inline CHECK CheckOverflow(RVA value1, COUNT_T value2) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x7B79 #elif defined(__NetBSD__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1993 +#elif defined(__sun) +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1992 #else #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0 #endif diff --git a/src/coreclr/src/inc/sstring.h b/src/coreclr/src/inc/sstring.h index ec2eb0cf17525..8de0cd3d4277a 100644 --- a/src/coreclr/src/inc/sstring.h +++ b/src/coreclr/src/inc/sstring.h @@ -809,6 +809,7 @@ template class EMPTY_BASES_DECL InlineSString : public SString { private: + DAC_ALIGNAS(SString) BYTE m_inline[SBUFFER_PADDED_SIZE(MEMSIZE)]; public: @@ -991,6 +992,7 @@ template class EMPTY_BASES_DECL ScratchBuffer : public SString::AbstractScratchBuffer { private: + DAC_ALIGNAS(::SString::AbstractScratchBuffer) BYTE m_inline[MEMSIZE]; public: diff --git a/src/coreclr/src/inc/strongnameholders.h b/src/coreclr/src/inc/strongnameholders.h index ecec99432af1b..d684e9d3a032a 100644 --- a/src/coreclr/src/inc/strongnameholders.h +++ b/src/coreclr/src/inc/strongnameholders.h @@ -18,6 +18,7 @@ void VoidStrongNameFreeBuffer(__in T *pBuffer) { StrongNameFreeBuffer(reinterpret_cast(pBuffer)); } -NEW_WRAPPER_TEMPLATE1(StrongNameBufferHolder, VoidStrongNameFreeBuffer<_TYPE>); +template +using StrongNameBufferHolder = SpecializedWrapper<_TYPE, VoidStrongNameFreeBuffer<_TYPE>>; #endif // !__STRONGNAME_HOLDERS_H__ diff --git a/src/coreclr/src/inc/utilcode.h b/src/coreclr/src/inc/utilcode.h index 1721db03dc01f..15902ef99e976 100644 --- a/src/coreclr/src/inc/utilcode.h +++ b/src/coreclr/src/inc/utilcode.h @@ -2573,6 +2573,7 @@ template class CHashTableAndData : public CHashTable { public: + DAC_ALIGNAS(CHashTable) ULONG m_iFree; // Index into m_pcEntries[] of next available slot ULONG m_iEntries; // size of m_pcEntries[] @@ -4715,13 +4716,6 @@ BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip); extern HINSTANCE g_hmodCoreCLR; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - -// Corrupting Exception limited support for outside the VM folder -BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE); - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - namespace UtilCode { // These are type-safe versions of Interlocked[Compare]Exchange diff --git a/src/coreclr/src/interop/comwrappers.cpp b/src/coreclr/src/interop/comwrappers.cpp index 60d80910a5078..3fb1b7941ed75 100644 --- a/src/coreclr/src/interop/comwrappers.cpp +++ b/src/coreclr/src/interop/comwrappers.cpp @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. #include "comwrappers.hpp" +#include #include #include // placement new @@ -47,8 +48,8 @@ namespace ABI }; ABI_ASSERT(sizeof(ComInterfaceDispatch) == sizeof(void*)); - const size_t DispatchAlignmentThisPtr = 16; // Should be a power of 2. - const intptr_t DispatchThisPtrMask = ~(DispatchAlignmentThisPtr - 1); + using InteropLib::ABI::DispatchAlignmentThisPtr; + using InteropLib::ABI::DispatchThisPtrMask; ABI_ASSERT(sizeof(void*) < DispatchAlignmentThisPtr); const intptr_t AlignmentThisPtrMaxPadding = DispatchAlignmentThisPtr - sizeof(void*); @@ -179,17 +180,20 @@ namespace ABI } } -namespace +// ManagedObjectWrapper_QueryInterface needs to be visible outside of this compilation unit +// to support the DAC. See code:ClrDataAccess::DACTryGetComWrappersObjectFromCCW for the +// usage in the DAC (look for the GetEEFuncEntryPoint call). +HRESULT STDMETHODCALLTYPE ManagedObjectWrapper_QueryInterface( + _In_ ABI::ComInterfaceDispatch* disp, + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) { - HRESULT STDMETHODCALLTYPE ManagedObjectWrapper_QueryInterface( - _In_ ABI::ComInterfaceDispatch* disp, - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) - { - ManagedObjectWrapper* wrapper = ABI::ToManagedObjectWrapper(disp); - return wrapper->QueryInterface(riid, ppvObject); - } + ManagedObjectWrapper* wrapper = ABI::ToManagedObjectWrapper(disp); + return wrapper->QueryInterface(riid, ppvObject); +} +namespace +{ ULONG STDMETHODCALLTYPE ManagedObjectWrapper_AddRef(_In_ ABI::ComInterfaceDispatch* disp) { ManagedObjectWrapper* wrapper = ABI::ToManagedObjectWrapper(disp); @@ -310,6 +314,7 @@ void ManagedObjectWrapper::GetIUnknownImpl( *fpRelease = ManagedObjectWrapper_IUnknownImpl.Release; } +// The logic here should match code:ClrDataAccess::DACTryGetComWrappersObjectFromCCW in daccess/request.cpp ManagedObjectWrapper* ManagedObjectWrapper::MapFromIUnknown(_In_ IUnknown* pUnk) { _ASSERTE(pUnk != nullptr); diff --git a/src/coreclr/src/interop/inc/interoplibabi.h b/src/coreclr/src/interop/inc/interoplibabi.h new file mode 100644 index 0000000000000..19a1e0c01e755 --- /dev/null +++ b/src/coreclr/src/interop/inc/interoplibabi.h @@ -0,0 +1,14 @@ +// 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. + +#include + +namespace InteropLib +{ + namespace ABI + { + const size_t DispatchAlignmentThisPtr = 16; // Should be a power of 2. + const intptr_t DispatchThisPtrMask = ~(DispatchAlignmentThisPtr - 1); + } +} diff --git a/src/coreclr/src/jit/CMakeLists.txt b/src/coreclr/src/jit/CMakeLists.txt index 8ba2c47973fde..a3f0b1aeb2e0d 100644 --- a/src/coreclr/src/jit/CMakeLists.txt +++ b/src/coreclr/src/jit/CMakeLists.txt @@ -318,16 +318,17 @@ else() set(JIT_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/clrjit.exports) generate_exports_file(${CLRJIT_EXPORTS} ${JIT_EXPORTS_FILE}) - if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) + if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD OR CLR_CMAKE_TARGET_SUNOS) # This is required to force using our own PAL, not one that we are loaded with. set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic") - set(JIT_EXPORTS_LINKER_OPTION -Wl,--version-script=${JIT_EXPORTS_FILE}) + if(CLR_CMAKE_TARGET_SUNOS) + set(JIT_EXPORTS_LINKER_OPTION -Wl,-M,${JIT_EXPORTS_FILE}) + else(CLR_CMAKE_TARGET_SUNOS) + set(JIT_EXPORTS_LINKER_OPTION -Wl,--version-script=${JIT_EXPORTS_FILE}) + endif(CLR_CMAKE_TARGET_SUNOS) elseif(CLR_CMAKE_TARGET_OSX) set(JIT_EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${JIT_EXPORTS_FILE}) - elseif(CLR_CMAKE_HOST_SUNOS) - # Add linker exports file option - set(JIT_EXPORTS_LINKER_OPTION -Wl,-M,${JIT_EXPORTS_FILE}) endif() set(SHARED_LIB_SOURCES ${SOURCES}) diff --git a/src/coreclr/src/jit/codegen.h b/src/coreclr/src/jit/codegen.h index 93227bc7f6c1f..d6b53ef475d7a 100644 --- a/src/coreclr/src/jit/codegen.h +++ b/src/coreclr/src/jit/codegen.h @@ -342,12 +342,12 @@ class CodeGen final : public CodeGenInterface void genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowestCalleeSavedOffset, int spDelta); void genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, int lowestCalleeSavedOffset, int spDelta); - void genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroed); + void genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegModified); #else void genPushCalleeSavedRegisters(); #endif - void genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn); + void genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegModified, regMaskTP maskArgRegsLiveIn); #if defined(TARGET_ARM) @@ -435,18 +435,18 @@ class CodeGen final : public CodeGenInterface void genZeroInitFltRegs(const regMaskTP& initFltRegs, const regMaskTP& initDblRegs, const regNumber& initReg); - regNumber genGetZeroReg(regNumber initReg, bool* pInitRegZeroed); + regNumber genGetZeroReg(regNumber initReg, bool* pInitRegModified); - void genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, bool* pInitRegZeroed); + void genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, bool* pInitRegModified); - void genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed); + void genReportGenericContextArg(regNumber initReg, bool* pInitRegModified); - void genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed); + void genSetGSSecurityCookie(regNumber initReg, bool* pInitRegModified); void genFinalizeFrame(); #ifdef PROFILING_SUPPORTED - void genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed); + void genProfilingEnterCallback(regNumber initReg, bool* pInitRegModified); void genProfilingLeaveCallback(unsigned helper); #endif // PROFILING_SUPPORTED @@ -512,7 +512,7 @@ class CodeGen final : public CodeGenInterface void genFuncletEpilog(); void genCaptureFuncletPrologEpilogInfo(); - void genSetPSPSym(regNumber initReg, bool* pInitRegZeroed); + void genSetPSPSym(regNumber initReg, bool* pInitRegModified); void genUpdateCurrentFunclet(BasicBlock* block); #if defined(TARGET_ARM) @@ -978,7 +978,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genSIMDIntrinsicInit(GenTreeSIMD* simdNode); void genSIMDIntrinsicInitN(GenTreeSIMD* simdNode); void genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode); - void genSIMDIntrinsicUnOpWithImm(GenTreeSIMD* simdNode); void genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode); void genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode); void genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode); @@ -1061,7 +1060,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Returns true after the last call to EmitCaseEnd() (i.e. this signals that code generation is done). bool Done() const { - return immValue == immUpperBound; + return (immValue > immUpperBound); } // Returns a value of the immediate operand that should be used for a case. @@ -1082,7 +1081,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX bool TestImmOpZeroOrOne() const { assert(NonConstImmOp()); - return immUpperBound == 2; + return (immLowerBound == 0) && (immUpperBound == 1); } emitter* GetEmitter() const @@ -1094,6 +1093,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX BasicBlock* endLabel; BasicBlock* nonZeroLabel; int immValue; + int immLowerBound; int immUpperBound; regNumber nonConstImmReg; regNumber branchTargetReg; @@ -1113,6 +1113,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Do liveness update for register produced by the current node in codegen after // code has been emitted for it. void genProduceReg(GenTree* tree); + void genSpillLocal(unsigned varNum, var_types type, GenTreeLclVar* lclNode, regNumber regNum); + void genUnspillLocal( + unsigned varNum, var_types type, GenTreeLclVar* lclNode, regNumber regNum, bool reSpill, bool isLastUse); void genUnspillRegIfNeeded(GenTree* tree); regNumber genConsumeReg(GenTree* tree); void genCopyRegIfNeeded(GenTree* tree, regNumber needReg); @@ -1275,10 +1278,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genEHFinallyOrFilterRet(BasicBlock* block); #endif // !FEATURE_EH_FUNCLETS - void genMultiRegCallStoreToLocal(GenTree* treeNode); + void genMultiRegStoreToLocal(GenTree* treeNode); - // Deals with codegen for muti-register struct returns. + // Codegen for multi-register struct returns. bool isStructReturn(GenTree* treeNode); +#ifdef FEATURE_SIMD + void genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc); +#endif void genStructReturn(GenTree* treeNode); #if defined(TARGET_X86) || defined(TARGET_ARM) diff --git a/src/coreclr/src/jit/codegenarm.cpp b/src/coreclr/src/jit/codegenarm.cpp index 7a3c5fac26f5e..015ac03a68b01 100644 --- a/src/coreclr/src/jit/codegenarm.cpp +++ b/src/coreclr/src/jit/codegenarm.cpp @@ -961,7 +961,7 @@ void CodeGen::genCodeForLclVar(GenTreeLclVar* tree) // If this is a register candidate that has been spilled, genConsumeReg() will // reload it at the point of use. Otherwise, if it's not in a register, we load it here. - if (!isRegCandidate && !(tree->gtFlags & GTF_SPILLED)) + if (!isRegCandidate && !tree->IsMultiReg() && !(tree->gtFlags & GTF_SPILLED)) { const LclVarDsc* varDsc = compiler->lvaGetDesc(tree); var_types type = varDsc->GetRegisterType(tree); @@ -1050,7 +1050,7 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) // case is handled separately. if (data->gtSkipReloadOrCopy()->IsMultiRegCall()) { - genMultiRegCallStoreToLocal(tree); + genMultiRegStoreToLocal(tree); } else { @@ -1648,14 +1648,14 @@ void CodeGen::genCodeForMulLong(GenTreeMultiRegOp* node) // genProfilingEnterCallback: Generate the profiling function enter callback. // // Arguments: -// initReg - register to use as scratch register -// pInitRegZeroed - OUT parameter. *pInitRegZeroed set to 'false' if 'initReg' is -// not zero after this call. +// initReg - register to use as scratch register +// pInitRegModified - OUT parameter. *pInitRegModified set to 'true' if and only if +// this call sets 'initReg' to a non-zero value. // // Return Value: // None // -void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -1688,7 +1688,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) if (initReg == argReg) { - *pInitRegZeroed = false; + *pInitRegModified = true; } } @@ -1818,14 +1818,17 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper) // Arguments: // frameSize - the size of the stack frame being allocated. // initReg - register to use as a scratch register. -// pInitRegZeroed - OUT parameter. *pInitRegZeroed is set to 'false' if and only if +// pInitRegModified - OUT parameter. *pInitRegModified is set to 'true' if and only if // this call sets 'initReg' to a non-zero value. // maskArgRegsLiveIn - incoming argument registers that are currently live. // // Return value: // None // -void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn) +void CodeGen::genAllocLclFrame(unsigned frameSize, + regNumber initReg, + bool* pInitRegModified, + regMaskTP maskArgRegsLiveIn) { assert(compiler->compGeneratingProlog); @@ -1855,7 +1858,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni } regSet.verifyRegUsed(initReg); - *pInitRegZeroed = false; // The initReg does not contain zero + *pInitRegModified = true; instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, frameSize); compiler->unwindPadding(); @@ -1875,7 +1878,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni if ((genRegMask(initReg) & (RBM_STACK_PROBE_HELPER_ARG | RBM_STACK_PROBE_HELPER_CALL_TARGET | RBM_STACK_PROBE_HELPER_TRASH)) != RBM_NONE) { - *pInitRegZeroed = false; + *pInitRegModified = true; } } diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp index 26c7411b71e13..91b5885f17463 100644 --- a/src/coreclr/src/jit/codegenarm64.cpp +++ b/src/coreclr/src/jit/codegenarm64.cpp @@ -1839,7 +1839,7 @@ void CodeGen::genCodeForLclVar(GenTreeLclVar* tree) // If this is a register candidate that has been spilled, genConsumeReg() will // reload it at the point of use. Otherwise, if it's not in a register, we load it here. - if (!isRegCandidate && !(tree->gtFlags & GTF_SPILLED)) + if (!isRegCandidate && !tree->IsMultiReg() && !(tree->gtFlags & GTF_SPILLED)) { // targetType must be a normal scalar type and not a TYP_STRUCT assert(targetType != TYP_STRUCT); @@ -1929,7 +1929,7 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) // case is handled separately. if (data->gtSkipReloadOrCopy()->IsMultiRegCall()) { - genMultiRegCallStoreToLocal(tree); + genMultiRegStoreToLocal(tree); } else { @@ -1953,17 +1953,31 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) genConsumeRegs(data); regNumber dataReg = REG_NA; - if (data->isContainedIntOrIImmed()) + if (data->isContained()) { // This is only possible for a zero-init. - assert(data->IsIntegralConst(0)); + assert(data->IsIntegralConst(0) || data->IsSIMDZero()); if (varTypeIsSIMD(targetType)) { - assert(targetType == TYP_SIMD16); - assert(targetReg != REG_NA); - emit->emitIns_R_I(INS_movi, EA_16BYTE, targetReg, 0x00, INS_OPTS_16B); - genProduceReg(tree); + if (targetReg != REG_NA) + { + emit->emitIns_R_I(INS_movi, emitActualTypeSize(targetType), targetReg, 0x00, INS_OPTS_16B); + genProduceReg(tree); + } + else + { + if (targetType == TYP_SIMD16) + { + GetEmitter()->emitIns_S_S_R_R(INS_stp, EA_8BYTE, EA_8BYTE, REG_ZR, REG_ZR, varNum, 0); + } + else + { + assert(targetType == TYP_SIMD8); + GetEmitter()->emitIns_S_R(INS_str, EA_8BYTE, REG_ZR, varNum, 0); + } + genUpdateLife(tree); + } return; } @@ -3807,15 +3821,11 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) genSIMDIntrinsicInitN(simdNode); break; - case SIMDIntrinsicSqrt: - case SIMDIntrinsicAbs: case SIMDIntrinsicCast: case SIMDIntrinsicConvertToSingle: case SIMDIntrinsicConvertToInt32: case SIMDIntrinsicConvertToDouble: case SIMDIntrinsicConvertToInt64: - case SIMDIntrinsicCeil: - case SIMDIntrinsicFloor: genSIMDIntrinsicUnOp(simdNode); break; @@ -3833,24 +3843,11 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) case SIMDIntrinsicMul: case SIMDIntrinsicDiv: case SIMDIntrinsicBitwiseAnd: - case SIMDIntrinsicBitwiseAndNot: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: - case SIMDIntrinsicMin: - case SIMDIntrinsicMax: case SIMDIntrinsicEqual: - case SIMDIntrinsicLessThan: - case SIMDIntrinsicGreaterThan: - case SIMDIntrinsicLessThanOrEqual: - case SIMDIntrinsicGreaterThanOrEqual: genSIMDIntrinsicBinOp(simdNode); break; - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: - genSIMDIntrinsicRelOp(simdNode); - break; - case SIMDIntrinsicDotProduct: genSIMDIntrinsicDotProduct(simdNode); break; @@ -3874,10 +3871,6 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) genSIMDIntrinsicUpperRestore(simdNode); break; - case SIMDIntrinsicSelect: - NYI("SIMDIntrinsicSelect lowered during import to (a & sel) | (b & ~sel)"); - break; - default: noway_assert(!"Unimplemented SIMD intrinsic."); unreached(); @@ -3935,24 +3928,15 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type { switch (intrinsicId) { - case SIMDIntrinsicAbs: - result = INS_fabs; - break; case SIMDIntrinsicAdd: result = INS_fadd; break; case SIMDIntrinsicBitwiseAnd: result = INS_and; break; - case SIMDIntrinsicBitwiseAndNot: - result = INS_bic; - break; case SIMDIntrinsicBitwiseOr: result = INS_orr; break; - case SIMDIntrinsicBitwiseXor: - result = INS_eor; - break; case SIMDIntrinsicCast: result = INS_mov; break; @@ -3966,24 +3950,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type case SIMDIntrinsicEqual: result = INS_fcmeq; break; - case SIMDIntrinsicGreaterThan: - result = INS_fcmgt; - break; - case SIMDIntrinsicGreaterThanOrEqual: - result = INS_fcmge; - break; - case SIMDIntrinsicLessThan: - result = INS_fcmlt; - break; - case SIMDIntrinsicLessThanOrEqual: - result = INS_fcmle; - break; - case SIMDIntrinsicMax: - result = INS_fmax; - break; - case SIMDIntrinsicMin: - result = INS_fmin; - break; case SIMDIntrinsicMul: result = INS_fmul; break; @@ -3992,12 +3958,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type // Return lower bytes instruction here result = INS_fcvtn; break; - case SIMDIntrinsicSelect: - result = INS_bsl; - break; - case SIMDIntrinsicSqrt: - result = INS_fsqrt; - break; case SIMDIntrinsicSub: result = INS_fsub; break; @@ -4007,12 +3967,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type case SIMDIntrinsicWidenHi: result = INS_fcvtl2; break; - case SIMDIntrinsicCeil: - result = INS_frintp; - break; - case SIMDIntrinsicFloor: - result = INS_frintm; - break; default: assert(!"Unsupported SIMD intrinsic"); unreached(); @@ -4024,25 +3978,15 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type switch (intrinsicId) { - case SIMDIntrinsicAbs: - assert(!isUnsigned); - result = INS_abs; - break; case SIMDIntrinsicAdd: result = INS_add; break; case SIMDIntrinsicBitwiseAnd: result = INS_and; break; - case SIMDIntrinsicBitwiseAndNot: - result = INS_bic; - break; case SIMDIntrinsicBitwiseOr: result = INS_orr; break; - case SIMDIntrinsicBitwiseXor: - result = INS_eor; - break; case SIMDIntrinsicCast: result = INS_mov; break; @@ -4053,26 +3997,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type case SIMDIntrinsicEqual: result = INS_cmeq; break; - case SIMDIntrinsicGreaterThan: - result = isUnsigned ? INS_cmhi : INS_cmgt; - break; - case SIMDIntrinsicGreaterThanOrEqual: - result = isUnsigned ? INS_cmhs : INS_cmge; - break; - case SIMDIntrinsicLessThan: - assert(!isUnsigned); - result = INS_cmlt; - break; - case SIMDIntrinsicLessThanOrEqual: - assert(!isUnsigned); - result = INS_cmle; - break; - case SIMDIntrinsicMax: - result = isUnsigned ? INS_umax : INS_smax; - break; - case SIMDIntrinsicMin: - result = isUnsigned ? INS_umin : INS_smin; - break; case SIMDIntrinsicMul: result = INS_mul; break; @@ -4081,9 +4005,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type // Return lower bytes instruction here result = INS_xtn; break; - case SIMDIntrinsicSelect: - result = INS_bsl; - break; case SIMDIntrinsicSub: result = INS_sub; break; @@ -4242,13 +4163,11 @@ void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode) // void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode) { - assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicSqrt || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicCast || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicAbs || + assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicCast || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicConvertToSingle || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicConvertToInt32 || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicConvertToDouble || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicConvertToInt64 || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicCeil || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicFloor); + simdNode->gtSIMDIntrinsicID == SIMDIntrinsicConvertToInt64); GenTree* op1 = simdNode->gtGetOp1(); var_types baseType = simdNode->gtSIMDBaseType; @@ -4298,17 +4217,10 @@ void CodeGen::genSIMDIntrinsicWiden(GenTreeSIMD* simdNode) instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType); - if (varTypeIsFloating(baseType)) - { - GetEmitter()->emitIns_R_R(ins, EA_8BYTE, targetReg, op1Reg); - } - else - { - emitAttr attr = (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicWidenHi) ? EA_16BYTE : EA_8BYTE; - insOpts opt = genGetSimdInsOpt(attr, baseType); + emitAttr attr = (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicWidenHi) ? EA_16BYTE : EA_8BYTE; + insOpts opt = genGetSimdInsOpt(attr, baseType); - GetEmitter()->emitIns_R_R(ins, attr, targetReg, op1Reg, opt); - } + GetEmitter()->emitIns_R_R(ins, attr, targetReg, op1Reg, opt); genProduceReg(simdNode); } @@ -4348,43 +4260,39 @@ void CodeGen::genSIMDIntrinsicNarrow(GenTreeSIMD* simdNode) instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType); assert((ins == INS_fcvtn) || (ins == INS_xtn)); - if (ins == INS_fcvtn) + instruction ins2 = (ins == INS_fcvtn) ? INS_fcvtn2 : INS_xtn2; + + insOpts opt = INS_OPTS_NONE; + insOpts opt2 = INS_OPTS_NONE; + + // This is not the same as genGetSimdInsOpt() + // Basetype is the soure operand type + // However encoding is based on the destination operand type which is 1/2 the basetype. + switch (baseType) { - GetEmitter()->emitIns_R_R(INS_fcvtn, EA_8BYTE, targetReg, op1Reg); - GetEmitter()->emitIns_R_R(INS_fcvtn2, EA_8BYTE, targetReg, op2Reg); + case TYP_ULONG: + case TYP_LONG: + case TYP_DOUBLE: + opt = INS_OPTS_2S; + opt2 = INS_OPTS_4S; + break; + case TYP_UINT: + case TYP_INT: + opt = INS_OPTS_4H; + opt2 = INS_OPTS_8H; + break; + case TYP_USHORT: + case TYP_SHORT: + opt = INS_OPTS_8B; + opt2 = INS_OPTS_16B; + break; + default: + assert(!"Unsupported narrowing element type"); + unreached(); } - else - { - insOpts opt = INS_OPTS_NONE; - insOpts opt2 = INS_OPTS_NONE; - // This is not the same as genGetSimdInsOpt() - // Basetype is the soure operand type - // However encoding is based on the destination operand type which is 1/2 the basetype. - switch (baseType) - { - case TYP_ULONG: - case TYP_LONG: - opt = INS_OPTS_2S; - opt2 = INS_OPTS_4S; - break; - case TYP_UINT: - case TYP_INT: - opt = INS_OPTS_4H; - opt2 = INS_OPTS_8H; - break; - case TYP_USHORT: - case TYP_SHORT: - opt = INS_OPTS_8B; - opt2 = INS_OPTS_16B; - break; - default: - assert(!"Unsupported narrowing element type"); - unreached(); - } - GetEmitter()->emitIns_R_R(INS_xtn, EA_8BYTE, targetReg, op1Reg, opt); - GetEmitter()->emitIns_R_R(INS_xtn2, EA_16BYTE, targetReg, op2Reg, opt2); - } + GetEmitter()->emitIns_R_R(ins, EA_8BYTE, targetReg, op1Reg, opt); + GetEmitter()->emitIns_R_R(ins2, EA_16BYTE, targetReg, op2Reg, opt2); genProduceReg(simdNode); } @@ -4404,14 +4312,7 @@ void CodeGen::genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode) assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicAdd || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicSub || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicMul || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicDiv || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseAnd || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseAndNot || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseOr || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseXor || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicMin || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicMax || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicEqual || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicLessThan || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicGreaterThan || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicLessThanOrEqual || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicGreaterThanOrEqual); + simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseOr || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicEqual); GenTree* op1 = simdNode->gtGetOp1(); GenTree* op2 = simdNode->gtGetOp2(); @@ -4439,65 +4340,6 @@ void CodeGen::genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode) genProduceReg(simdNode); } -//-------------------------------------------------------------------------------- -// genSIMDIntrinsicRelOp: Generate code for a SIMD Intrinsic relational operater -// == and != -// -// Arguments: -// simdNode - The GT_SIMD node -// -// Return Value: -// None. -// -void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) -{ - assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpInEquality); - - GenTree* op1 = simdNode->gtGetOp1(); - GenTree* op2 = simdNode->gtGetOp2(); - var_types baseType = simdNode->gtSIMDBaseType; - regNumber targetReg = simdNode->GetRegNum(); - var_types targetType = simdNode->TypeGet(); - - genConsumeOperands(simdNode); - regNumber op1Reg = op1->GetRegNum(); - regNumber op2Reg = op2->GetRegNum(); - regNumber otherReg = op2Reg; - - instruction ins = getOpForSIMDIntrinsic(SIMDIntrinsicEqual, baseType); - emitAttr attr = (simdNode->gtSIMDSize > 8) ? EA_16BYTE : EA_8BYTE; - insOpts opt = genGetSimdInsOpt(attr, baseType); - - // TODO-ARM64-CQ Contain integer constants where possible - - regNumber tmpFloatReg = simdNode->GetSingleTempReg(RBM_ALLFLOAT); - - GetEmitter()->emitIns_R_R_R(ins, attr, tmpFloatReg, op1Reg, op2Reg, opt); - - if ((simdNode->gtFlags & GTF_SIMD12_OP) != 0) - { - // For 12Byte vectors we must set upper bits to get correct comparison - // We do not assume upper bits are zero. - instGen_Set_Reg_To_Imm(EA_4BYTE, targetReg, -1); - GetEmitter()->emitIns_R_R_I(INS_ins, EA_4BYTE, tmpFloatReg, targetReg, 3); - } - - GetEmitter()->emitIns_R_R(INS_uminv, attr, tmpFloatReg, tmpFloatReg, - (simdNode->gtSIMDSize > 8) ? INS_OPTS_16B : INS_OPTS_8B); - - GetEmitter()->emitIns_R_R_I(INS_mov, EA_1BYTE, targetReg, tmpFloatReg, 0); - - if (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpInEquality) - { - GetEmitter()->emitIns_R_R_I(INS_eor, EA_4BYTE, targetReg, targetReg, 0x1); - } - - GetEmitter()->emitIns_R_R_I(INS_and, EA_4BYTE, targetReg, targetReg, 0x1); - - genProduceReg(simdNode); -} - //-------------------------------------------------------------------------------- // genSIMDIntrinsicDotProduct: Generate code for SIMD Intrinsic Dot Product. // @@ -5019,7 +4861,20 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode) } GenTree* op1 = treeNode->AsOp()->gtOp1; - assert(!op1->isContained()); + + if (op1->isContained()) + { + // This is only possible for a zero-init. + assert(op1->IsIntegralConst(0) || op1->IsSIMDZero()); + + // store lower 8 bytes + GetEmitter()->emitIns_S_R(ins_Store(TYP_DOUBLE), EA_8BYTE, REG_ZR, varNum, offs); + + // Store upper 4 bytes + GetEmitter()->emitIns_S_R(ins_Store(TYP_FLOAT), EA_4BYTE, REG_ZR, varNum, offs + 8); + + return; + } regNumber operandReg = genConsumeReg(op1); // Need an addtional integer register to extract upper 4 bytes from data. @@ -5043,14 +4898,14 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode) // genProfilingEnterCallback: Generate the profiling function enter callback. // // Arguments: -// initReg - register to use as scratch register -// pInitRegZeroed - OUT parameter. *pInitRegZeroed set to 'false' if 'initReg' is -// not zero after this call. +// initReg - register to use as scratch register +// pInitRegModified - OUT parameter. *pInitRegModified set to 'true' if 'initReg' is +// not zero after this call. // // Return Value: // None // -void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -5078,7 +4933,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) if ((genRegMask(initReg) & RBM_PROFILER_ENTER_TRASH) != RBM_NONE) { - *pInitRegZeroed = false; + *pInitRegModified = true; } } @@ -5436,35 +5291,35 @@ void CodeGen::genArm64EmitterUnitTests() // tbl Vd, {Vt}, Vm theEmitter->emitIns_R_R_R(INS_tbl, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbl, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbl, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbx Vd, {Vt}, Vm theEmitter->emitIns_R_R_R(INS_tbx, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbx, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbx, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbl Vd, {Vt, Vt2}, Vm theEmitter->emitIns_R_R_R(INS_tbl_2regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbl_2regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbl_2regs, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbx Vd, {Vt, Vt2}, Vm theEmitter->emitIns_R_R_R(INS_tbx_2regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbx_2regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbx_2regs, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbl Vd, {Vt, Vt2, Vt3}, Vm theEmitter->emitIns_R_R_R(INS_tbl_3regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbl_3regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbl_3regs, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbx Vd, {Vt, Vt2, Vt3}, Vm theEmitter->emitIns_R_R_R(INS_tbx_3regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbx_3regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbx_3regs, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbl Vd, {Vt, Vt2, Vt3, Vt4}, Vm theEmitter->emitIns_R_R_R(INS_tbl_4regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbl_4regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbl_4regs, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); // tbx Vd, {Vt, Vt2, Vt3, Vt4}, Vm theEmitter->emitIns_R_R_R(INS_tbx_4regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_8B); - theEmitter->emitIns_R_R_R(INS_tbx_4regs, EA_8BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_tbx_4regs, EA_16BYTE, REG_V0, REG_V1, REG_V6, INS_OPTS_16B); #endif // ALL_ARM64_EMITTER_UNIT_TESTS @@ -7911,17 +7766,18 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R(INS_ursqrte, EA_8BYTE, REG_V0, REG_V1, INS_OPTS_2S); theEmitter->emitIns_R_R(INS_ursqrte, EA_16BYTE, REG_V2, REG_V3, INS_OPTS_4S); - // INS_fcvtl - theEmitter->emitIns_R_R(INS_fcvtl, EA_4BYTE, REG_V0, REG_V1); - - // INS_fcvtl2 - theEmitter->emitIns_R_R(INS_fcvtl2, EA_4BYTE, REG_V0, REG_V1); + // fcvtl{2} vector + theEmitter->emitIns_R_R(INS_fcvtl, EA_8BYTE, REG_V0, REG_V1, INS_OPTS_4H); + theEmitter->emitIns_R_R(INS_fcvtl2, EA_16BYTE, REG_V2, REG_V3, INS_OPTS_8H); + theEmitter->emitIns_R_R(INS_fcvtl, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_2S); + theEmitter->emitIns_R_R(INS_fcvtl2, EA_16BYTE, REG_V5, REG_V6, INS_OPTS_4S); - // INS_fcvtn - theEmitter->emitIns_R_R(INS_fcvtn, EA_8BYTE, REG_V0, REG_V1); + // fcvtn{2} vector + theEmitter->emitIns_R_R(INS_fcvtn, EA_8BYTE, REG_V0, REG_V1, INS_OPTS_4H); + theEmitter->emitIns_R_R(INS_fcvtn2, EA_16BYTE, REG_V2, REG_V3, INS_OPTS_8H); + theEmitter->emitIns_R_R(INS_fcvtn, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_2S); + theEmitter->emitIns_R_R(INS_fcvtn2, EA_16BYTE, REG_V5, REG_V6, INS_OPTS_4S); - // INS_fcvtn2 - theEmitter->emitIns_R_R(INS_fcvtn2, EA_8BYTE, REG_V0, REG_V1); #endif #ifdef ALL_ARM64_EMITTER_UNIT_TESTS @@ -8161,196 +8017,200 @@ void CodeGen::genArm64EmitterUnitTests() // R_R_I vector operations, one dest, one source reg, one immed // + // Some of the tests cases below might appear redundant since they emit same combinations of instruction x size x + // vector arrangements. However, these are added to verify that the split constant encoding works with both - small + // and large constants. + genDefineTempLabel(genCreateTempLabel()); - // 'sshr' scalar + // sshr scalar theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V8, REG_V9, 64); - // 'sshr' vector + // sshr vector theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_sshr, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_sshr, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'ssra' scalar + // ssra scalar theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V8, REG_V9, 64); - // 'ssra' vector + // ssra vector theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_ssra, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_ssra, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'srshr' scalar + // srshr scalar theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V8, REG_V9, 64); - // 'srshr' vector + // srshr vector theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_srshr, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_srshr, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'srsra' scalar + // srsra scalar theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V8, REG_V9, 64); - // 'srsra' vector + // srsra vector theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_srsra, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_srsra, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'shl' scalar - theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V0, REG_V1, 1); + // shl scalar + theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V0, REG_V1, 0); theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V6, REG_V7, 40); theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V8, REG_V9, 63); - // 'shl' vector - theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + // shl vector + theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V0, REG_V1, 0, INS_OPTS_8B); theEmitter->emitIns_R_R_I(INS_shl, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); - theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V4, REG_V5, 8, INS_OPTS_4H); theEmitter->emitIns_R_R_I(INS_shl, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); - theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_shl, EA_8BYTE, REG_V8, REG_V9, 16, INS_OPTS_2S); theEmitter->emitIns_R_R_I(INS_shl, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); - theEmitter->emitIns_R_R_I(INS_shl, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_shl, EA_16BYTE, REG_V12, REG_V13, 32, INS_OPTS_2D); theEmitter->emitIns_R_R_I(INS_shl, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); - // 'ushr' scalar + // ushr scalar theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V8, REG_V9, 64); - // 'ushr' vector + // ushr vector theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_ushr, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_ushr, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'usra' scalar + // usra scalar theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V8, REG_V9, 64); - // 'usra' vector + // usra vector theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_usra, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_usra, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'urshr' scalar + // urshr scalar theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V8, REG_V9, 64); - // 'urshr' vector + // urshr vector theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_urshr, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_urshr, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'ursra' scalar + // ursra scalar theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V8, REG_V9, 64); - // 'srsra' vector + // ursra vector theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_ursra, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_ursra, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'sri' scalar + // sri scalar theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V0, REG_V1, 1); theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V6, REG_V7, 40); - theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V8, REG_V9, 63); + theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V8, REG_V9, 64); - // 'sri' vector + // sri vector theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_sri, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); - theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_sri, EA_16BYTE, REG_V14, REG_V15, 64, INS_OPTS_2D); - // 'sli' scalar - theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V0, REG_V1, 1); + // sli scalar + theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V0, REG_V1, 0); theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V2, REG_V3, 14); theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V4, REG_V5, 27); theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V6, REG_V7, 40); theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V8, REG_V9, 63); - // 'sli' vector - theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + // sli vector + theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V0, REG_V1, 0, INS_OPTS_8B); theEmitter->emitIns_R_R_I(INS_sli, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); - theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V4, REG_V5, 8, INS_OPTS_4H); theEmitter->emitIns_R_R_I(INS_sli, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); - theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sli, EA_8BYTE, REG_V8, REG_V9, 16, INS_OPTS_2S); theEmitter->emitIns_R_R_I(INS_sli, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); - theEmitter->emitIns_R_R_I(INS_sli, EA_16BYTE, REG_V12, REG_V13, 33, INS_OPTS_2D); + theEmitter->emitIns_R_R_I(INS_sli, EA_16BYTE, REG_V12, REG_V13, 32, INS_OPTS_2D); theEmitter->emitIns_R_R_I(INS_sli, EA_16BYTE, REG_V14, REG_V15, 63, INS_OPTS_2D); - // 'sshll' vector + // sshll{2} vector theEmitter->emitIns_R_R_I(INS_sshll, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); theEmitter->emitIns_R_R_I(INS_sshll2, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_sshll, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); @@ -8358,7 +8218,7 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R_I(INS_sshll, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); theEmitter->emitIns_R_R_I(INS_sshll2, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); - // 'ushll' vector + // ushll{2} vector theEmitter->emitIns_R_R_I(INS_ushll, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); theEmitter->emitIns_R_R_I(INS_ushll2, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_ushll, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); @@ -8366,23 +8226,23 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R_I(INS_ushll, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); theEmitter->emitIns_R_R_I(INS_ushll2, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); - // 'shrn' vector + // shrn{2} vector theEmitter->emitIns_R_R_I(INS_shrn, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_shrn2, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_shrn2, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_shrn, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_shrn2, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_shrn2, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_shrn, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_shrn2, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_shrn2, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); - // 'rshrn' vector + // rshrn{2} vector theEmitter->emitIns_R_R_I(INS_rshrn, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); - theEmitter->emitIns_R_R_I(INS_rshrn2, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_rshrn2, EA_16BYTE, REG_V2, REG_V3, 8, INS_OPTS_16B); theEmitter->emitIns_R_R_I(INS_rshrn, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); - theEmitter->emitIns_R_R_I(INS_rshrn2, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_rshrn2, EA_16BYTE, REG_V6, REG_V7, 16, INS_OPTS_8H); theEmitter->emitIns_R_R_I(INS_rshrn, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); - theEmitter->emitIns_R_R_I(INS_rshrn2, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_rshrn2, EA_16BYTE, REG_V10, REG_V11, 32, INS_OPTS_4S); - // 'sxtl' vector + // sxtl{2} vector theEmitter->emitIns_R_R(INS_sxtl, EA_8BYTE, REG_V0, REG_V1, INS_OPTS_8B); theEmitter->emitIns_R_R(INS_sxtl2, EA_16BYTE, REG_V2, REG_V3, INS_OPTS_16B); theEmitter->emitIns_R_R(INS_sxtl, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_4H); @@ -8390,7 +8250,7 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R(INS_sxtl, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_2S); theEmitter->emitIns_R_R(INS_sxtl2, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_4S); - // 'uxtl' vector + // uxtl{2} vector theEmitter->emitIns_R_R(INS_uxtl, EA_8BYTE, REG_V0, REG_V1, INS_OPTS_8B); theEmitter->emitIns_R_R(INS_uxtl2, EA_16BYTE, REG_V2, REG_V3, INS_OPTS_16B); theEmitter->emitIns_R_R(INS_uxtl, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_4H); @@ -8398,6 +8258,195 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R(INS_uxtl, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_2S); theEmitter->emitIns_R_R(INS_uxtl2, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_4S); + // sqrshrn scalar + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_1BYTE, REG_V0, REG_V1, 1, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_1BYTE, REG_V2, REG_V3, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_2BYTE, REG_V4, REG_V5, 9, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_2BYTE, REG_V6, REG_V7, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_4BYTE, REG_V8, REG_V9, 17, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_4BYTE, REG_V10, REG_V11, 32, INS_OPTS_NONE); + + // sqrshrn{2} vector + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_8BYTE, REG_V2, REG_V3, 8, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqrshrn2, EA_16BYTE, REG_V4, REG_V5, 1, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqrshrn2, EA_16BYTE, REG_V6, REG_V7, 8, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_8BYTE, REG_V8, REG_V9, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_8BYTE, REG_V10, REG_V11, 16, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqrshrn2, EA_16BYTE, REG_V12, REG_V13, 9, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqrshrn2, EA_16BYTE, REG_V14, REG_V15, 16, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_8BYTE, REG_V16, REG_V17, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqrshrn, EA_8BYTE, REG_V18, REG_V18, 32, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqrshrn2, EA_16BYTE, REG_V20, REG_V21, 17, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sqrshrn2, EA_16BYTE, REG_V22, REG_V23, 32, INS_OPTS_4S); + + // sqrshrun scalar + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_1BYTE, REG_V0, REG_V1, 1, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_1BYTE, REG_V0, REG_V1, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_2BYTE, REG_V2, REG_V3, 9, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_2BYTE, REG_V2, REG_V3, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_4BYTE, REG_V4, REG_V5, 17, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_4BYTE, REG_V4, REG_V5, 32, INS_OPTS_NONE); + + // sqrshrun{2} vector + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_8BYTE, REG_V2, REG_V3, 8, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqrshrun2, EA_16BYTE, REG_V4, REG_V5, 1, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqrshrun2, EA_16BYTE, REG_V6, REG_V7, 8, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_8BYTE, REG_V8, REG_V9, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_8BYTE, REG_V10, REG_V11, 16, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqrshrun2, EA_16BYTE, REG_V12, REG_V13, 9, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqrshrun2, EA_16BYTE, REG_V14, REG_V15, 16, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_8BYTE, REG_V16, REG_V17, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqrshrun, EA_8BYTE, REG_V18, REG_V18, 32, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqrshrun2, EA_16BYTE, REG_V20, REG_V21, 17, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sqrshrun2, EA_16BYTE, REG_V22, REG_V23, 32, INS_OPTS_4S); + + // sqshl scalar + theEmitter->emitIns_R_R_I(INS_sqshl, EA_1BYTE, REG_V0, REG_V1, 0, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_1BYTE, REG_V2, REG_V3, 7, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_2BYTE, REG_V4, REG_V5, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_2BYTE, REG_V6, REG_V7, 15, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_4BYTE, REG_V8, REG_V9, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_4BYTE, REG_V10, REG_V11, 31, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_8BYTE, REG_V12, REG_V13, 32, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_8BYTE, REG_V14, REG_V15, 63, INS_OPTS_NONE); + + // sqshl vector + theEmitter->emitIns_R_R_I(INS_sqshl, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sqshl, EA_16BYTE, REG_V12, REG_V13, 63, INS_OPTS_2D); + + // sqshlu scalar + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_1BYTE, REG_V0, REG_V1, 0, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_1BYTE, REG_V2, REG_V3, 7, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_2BYTE, REG_V4, REG_V5, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_2BYTE, REG_V6, REG_V7, 15, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_4BYTE, REG_V8, REG_V9, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_4BYTE, REG_V10, REG_V11, 31, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_8BYTE, REG_V12, REG_V13, 32, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_8BYTE, REG_V14, REG_V15, 63, INS_OPTS_NONE); + + // sqshlu vector + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sqshlu, EA_16BYTE, REG_V12, REG_V13, 63, INS_OPTS_2D); + + // sqshrn scalar + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_1BYTE, REG_V0, REG_V1, 1, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_1BYTE, REG_V2, REG_V3, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_2BYTE, REG_V4, REG_V5, 9, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_2BYTE, REG_V6, REG_V7, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_4BYTE, REG_V8, REG_V9, 17, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_4BYTE, REG_V10, REG_V11, 32, INS_OPTS_NONE); + + // sqshrn{2} vector + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_8BYTE, REG_V2, REG_V3, 8, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqshrn2, EA_16BYTE, REG_V4, REG_V5, 1, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqshrn2, EA_16BYTE, REG_V6, REG_V7, 8, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_8BYTE, REG_V8, REG_V9, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_8BYTE, REG_V10, REG_V11, 16, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqshrn2, EA_16BYTE, REG_V12, REG_V13, 9, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqshrn2, EA_16BYTE, REG_V14, REG_V15, 16, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_8BYTE, REG_V16, REG_V17, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqshrn, EA_8BYTE, REG_V18, REG_V18, 32, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqshrn2, EA_16BYTE, REG_V20, REG_V21, 17, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sqshrn2, EA_16BYTE, REG_V22, REG_V23, 32, INS_OPTS_4S); + + // sqshrun scalar + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_1BYTE, REG_V0, REG_V1, 1, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_1BYTE, REG_V2, REG_V3, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_2BYTE, REG_V4, REG_V5, 9, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_2BYTE, REG_V6, REG_V7, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_4BYTE, REG_V8, REG_V9, 17, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_4BYTE, REG_V10, REG_V11, 32, INS_OPTS_NONE); + + // sqshrun{2} vector + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_8BYTE, REG_V2, REG_V3, 8, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_sqshrun2, EA_16BYTE, REG_V4, REG_V5, 1, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqshrun2, EA_16BYTE, REG_V6, REG_V7, 8, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_8BYTE, REG_V8, REG_V9, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_8BYTE, REG_V10, REG_V11, 16, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_sqshrun2, EA_16BYTE, REG_V12, REG_V13, 9, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqshrun2, EA_16BYTE, REG_V14, REG_V15, 16, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_8BYTE, REG_V16, REG_V17, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqshrun, EA_8BYTE, REG_V18, REG_V18, 32, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_sqshrun2, EA_16BYTE, REG_V20, REG_V21, 17, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_sqshrun2, EA_16BYTE, REG_V22, REG_V23, 32, INS_OPTS_4S); + + // uqrshrn scalar + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_1BYTE, REG_V0, REG_V1, 1, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_1BYTE, REG_V2, REG_V3, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_2BYTE, REG_V4, REG_V5, 9, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_2BYTE, REG_V6, REG_V7, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_4BYTE, REG_V8, REG_V9, 17, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_4BYTE, REG_V10, REG_V11, 32, INS_OPTS_NONE); + + // uqrshrn{2} vector + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_8BYTE, REG_V2, REG_V3, 8, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_uqrshrn2, EA_16BYTE, REG_V4, REG_V5, 1, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_uqrshrn2, EA_16BYTE, REG_V6, REG_V7, 8, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_8BYTE, REG_V8, REG_V9, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_8BYTE, REG_V10, REG_V11, 16, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_uqrshrn2, EA_16BYTE, REG_V12, REG_V13, 9, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_uqrshrn2, EA_16BYTE, REG_V14, REG_V15, 16, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_8BYTE, REG_V16, REG_V17, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_uqrshrn, EA_8BYTE, REG_V18, REG_V18, 32, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_uqrshrn2, EA_16BYTE, REG_V20, REG_V21, 17, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_uqrshrn2, EA_16BYTE, REG_V22, REG_V23, 32, INS_OPTS_4S); + + // uqshl scalar + theEmitter->emitIns_R_R_I(INS_uqshl, EA_1BYTE, REG_V0, REG_V1, 0, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_1BYTE, REG_V2, REG_V3, 7, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_2BYTE, REG_V4, REG_V5, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_2BYTE, REG_V6, REG_V7, 15, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_4BYTE, REG_V8, REG_V9, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_4BYTE, REG_V10, REG_V11, 31, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_8BYTE, REG_V12, REG_V13, 32, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_8BYTE, REG_V14, REG_V15, 63, INS_OPTS_NONE); + + // uqshl vector + theEmitter->emitIns_R_R_I(INS_uqshl, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_16BYTE, REG_V2, REG_V3, 7, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_8BYTE, REG_V4, REG_V5, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_16BYTE, REG_V6, REG_V7, 15, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_8BYTE, REG_V8, REG_V9, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_16BYTE, REG_V10, REG_V11, 31, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_uqshl, EA_16BYTE, REG_V12, REG_V13, 63, INS_OPTS_2D); + + // uqshrn scalar + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_1BYTE, REG_V0, REG_V1, 1, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_1BYTE, REG_V2, REG_V3, 8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_2BYTE, REG_V4, REG_V5, 9, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_2BYTE, REG_V6, REG_V7, 16, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_4BYTE, REG_V8, REG_V9, 17, INS_OPTS_NONE); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_4BYTE, REG_V10, REG_V11, 32, INS_OPTS_NONE); + + // uqshrn{2} vector + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_8BYTE, REG_V0, REG_V1, 1, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_8BYTE, REG_V2, REG_V3, 8, INS_OPTS_8B); + theEmitter->emitIns_R_R_I(INS_uqshrn2, EA_16BYTE, REG_V4, REG_V5, 1, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_uqshrn2, EA_16BYTE, REG_V6, REG_V7, 8, INS_OPTS_16B); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_8BYTE, REG_V8, REG_V9, 9, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_8BYTE, REG_V10, REG_V11, 16, INS_OPTS_4H); + theEmitter->emitIns_R_R_I(INS_uqshrn2, EA_16BYTE, REG_V12, REG_V13, 9, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_uqshrn2, EA_16BYTE, REG_V14, REG_V15, 16, INS_OPTS_8H); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_8BYTE, REG_V16, REG_V17, 17, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_uqshrn, EA_8BYTE, REG_V18, REG_V18, 32, INS_OPTS_2S); + theEmitter->emitIns_R_R_I(INS_uqshrn2, EA_16BYTE, REG_V20, REG_V21, 17, INS_OPTS_4S); + theEmitter->emitIns_R_R_I(INS_uqshrn2, EA_16BYTE, REG_V22, REG_V23, 32, INS_OPTS_4S); + #endif // ALL_ARM64_EMITTER_UNIT_TESTS #ifdef ALL_ARM64_EMITTER_UNIT_TESTS @@ -8711,6 +8760,54 @@ void CodeGen::genArm64EmitterUnitTests() #endif // ALL_ARM64_EMITTER_UNIT_TESTS #ifdef ALL_ARM64_EMITTER_UNIT_TESTS + // srshl scalar + theEmitter->emitIns_R_R_R(INS_srshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + + // srshl vector + theEmitter->emitIns_R_R_R(INS_srshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_srshl, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_srshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_srshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_srshl, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_srshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_srshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + + // sshl scalar + theEmitter->emitIns_R_R_R(INS_sshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + + // sshl vector + theEmitter->emitIns_R_R_R(INS_sshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_sshl, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_sshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_sshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_sshl, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_sshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_sshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + + // urshl scalar + theEmitter->emitIns_R_R_R(INS_urshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + + // urshl vector + theEmitter->emitIns_R_R_R(INS_urshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_urshl, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_urshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_urshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_urshl, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_urshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_urshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + + // ushl scalar + theEmitter->emitIns_R_R_R(INS_ushl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + + // ushl vector + theEmitter->emitIns_R_R_R(INS_ushl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_ushl, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_ushl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_ushl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_ushl, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_ushl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_ushl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + // addhn vector theEmitter->emitIns_R_R_R(INS_addhn, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); theEmitter->emitIns_R_R_R(INS_addhn, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4H); @@ -8811,6 +8908,36 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R_R(INS_sqadd, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_8H); theEmitter->emitIns_R_R_R(INS_sqadd, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + // sqrshl scalar + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_1BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_2BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_4BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_8BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_NONE); + + // sqrshl vector + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_sqrshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + + // sqshl scalar + theEmitter->emitIns_R_R_R(INS_sqshl, EA_1BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_2BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_4BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_8BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_NONE); + + // sqshl vector + theEmitter->emitIns_R_R_R(INS_sqshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_sqshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + // sqsub scalar theEmitter->emitIns_R_R_R(INS_sqsub, EA_1BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); theEmitter->emitIns_R_R_R(INS_sqsub, EA_2BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_NONE); @@ -8933,6 +9060,36 @@ void CodeGen::genArm64EmitterUnitTests() theEmitter->emitIns_R_R_R(INS_uqadd, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_8H); theEmitter->emitIns_R_R_R(INS_uqadd, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + // uqrshl scalar + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_1BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_2BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_4BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_8BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_NONE); + + // uqrshl vector + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_uqrshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + + // uqshl scalar + theEmitter->emitIns_R_R_R(INS_uqshl, EA_1BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_2BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_4BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_NONE); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_8BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_NONE); + + // uqshl vector + theEmitter->emitIns_R_R_R(INS_uqshl, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4H); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_16B); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_8H); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S); + theEmitter->emitIns_R_R_R(INS_uqshl, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D); + // uqsub scalar theEmitter->emitIns_R_R_R(INS_uqsub, EA_1BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_NONE); theEmitter->emitIns_R_R_R(INS_uqsub, EA_2BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_NONE); @@ -9220,16 +9377,19 @@ void CodeGen::genArm64EmitterUnitTests() // on Windows as well just to be consistent, even though it should not be necessary. // // Arguments: -// frameSize - the size of the stack frame being allocated. -// initReg - register to use as a scratch register. -// pInitRegZeroed - OUT parameter. *pInitRegZeroed is set to 'false' if and only if -// this call sets 'initReg' to a non-zero value. -// maskArgRegsLiveIn - incoming argument registers that are currently live. +// frameSize - the size of the stack frame being allocated. +// initReg - register to use as a scratch register. +// pInitRegModified - OUT parameter. *pInitRegModified is set to 'true' if and only if +// this call sets 'initReg' to a non-zero value. +// maskArgRegsLiveIn - incoming argument registers that are currently live. // // Return value: // None // -void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn) +void CodeGen::genAllocLclFrame(unsigned frameSize, + regNumber initReg, + bool* pInitRegModified, + regMaskTP maskArgRegsLiveIn) { assert(compiler->compGeneratingProlog); @@ -9266,7 +9426,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, -(ssize_t)probeOffset); GetEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, REG_ZR, REG_SPBASE, initReg); regSet.verifyRegUsed(initReg); - *pInitRegZeroed = false; // The initReg does not contain zero + *pInitRegModified = true; lastTouchDelta -= pageSize; } @@ -9326,7 +9486,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni GetEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, rLimit, rOffset); // If equal, we need to probe again GetEmitter()->emitIns_J(INS_bls, NULL, -4); - *pInitRegZeroed = false; // The initReg does not contain zero + *pInitRegModified = true; compiler->unwindPadding(); @@ -9341,7 +9501,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni compiler->unwindPadding(); regSet.verifyRegUsed(initReg); - *pInitRegZeroed = false; // The initReg does not contain zero + *pInitRegModified = true; } } diff --git a/src/coreclr/src/jit/codegenarmarch.cpp b/src/coreclr/src/jit/codegenarmarch.cpp index 6e55a28da2cf7..cacfb1a6182db 100644 --- a/src/coreclr/src/jit/codegenarmarch.cpp +++ b/src/coreclr/src/jit/codegenarmarch.cpp @@ -562,14 +562,14 @@ void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFla // genSetGSSecurityCookie: Set the "GS" security cookie in the prolog. // // Arguments: -// initReg - register to use as a scratch register -// pInitRegZeroed - OUT parameter. *pInitRegZeroed is set to 'false' if and only if -// this call sets 'initReg' to a non-zero value. +// initReg - register to use as a scratch register +// pInitRegModified - OUT parameter. *pInitRegModified is set to 'true' if and only if +// this call sets 'initReg' to a non-zero value. // // Return Value: // None // -void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -593,7 +593,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) GetEmitter()->emitIns_S_R(INS_str, EA_PTRSIZE, initReg, compiler->lvaGSSecurityCookie, 0); } - *pInitRegZeroed = false; + *pInitRegModified = true; } //--------------------------------------------------------------------- @@ -1355,7 +1355,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) #endif // FEATURE_ARG_SPLIT //---------------------------------------------------------------------------------- -// genMultiRegCallStoreToLocal: store multi-reg return value of a call node to a local +// genMultiRegStoreToLocal: store multi-reg return value of a call node to a local // // Arguments: // treeNode - Gentree of GT_STORE_LCL_VAR @@ -1364,42 +1364,35 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) // None // // Assumption: -// The child of store is a multi-reg call node. -// genProduceReg() on treeNode is made by caller of this routine. +// The child of store is a multi-reg node. // -void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode) +void CodeGen::genMultiRegStoreToLocal(GenTree* treeNode) { assert(treeNode->OperGet() == GT_STORE_LCL_VAR); - -#if defined(TARGET_ARM) - // Longs are returned in two return registers on Arm32. - // Structs are returned in four registers on ARM32 and HFAs. - assert(varTypeIsLong(treeNode) || varTypeIsStruct(treeNode)); -#elif defined(TARGET_ARM64) - // Structs of size >=9 and <=16 are returned in two return registers on ARM64 and HFAs. - assert(varTypeIsStruct(treeNode)); -#endif // TARGET* + assert(varTypeIsStruct(treeNode) || varTypeIsMultiReg(treeNode)); + GenTree* op1 = treeNode->gtGetOp1(); + GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + assert(op1->IsMultiRegNode()); + unsigned regCount = actualOp1->GetMultiRegCount(); // Assumption: current implementation requires that a multi-reg // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from // being promoted. unsigned lclNum = treeNode->AsLclVarCommon()->GetLclNum(); - LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - noway_assert(varDsc->lvIsMultiRegRet); - - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - assert(call->HasMultiRegRetVal()); + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); + if (op1->OperIs(GT_CALL)) + { + assert(regCount <= MAX_RET_REG_COUNT); + noway_assert(varDsc->lvIsMultiRegRet); + } genConsumeRegs(op1); - ReturnTypeDesc* pRetTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = pRetTypeDesc->GetReturnRegCount(); + int offset = 0; - if (treeNode->GetRegNum() != REG_NA) + // Check for the case of an enregistered SIMD type that's returned in multiple registers. + if (varDsc->lvIsRegCandidate() && treeNode->GetRegNum() != REG_NA) { - // Right now the only enregistrable multi-reg return types supported are SIMD types. assert(varTypeIsSIMD(treeNode)); assert(regCount != 0); @@ -1409,8 +1402,8 @@ void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode) // Insert pieces in reverse order for (int i = regCount - 1; i >= 0; --i) { - var_types type = pRetTypeDesc->GetReturnRegType(i); - regNumber reg = call->GetRegNumByIdx(i); + var_types type = op1->gtSkipReloadOrCopy()->GetRegTypeByIndex(i); + regNumber reg = op1->GetRegByIndex(i); if (op1->IsCopyOrReload()) { // GT_COPY/GT_RELOAD will have valid reg for those positions @@ -1449,21 +1442,16 @@ void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode) } else { - // Stack store - int offset = 0; for (unsigned i = 0; i < regCount; ++i) { - var_types type = pRetTypeDesc->GetReturnRegType(i); - regNumber reg = call->GetRegNumByIdx(i); - if (op1->IsCopyOrReload()) + var_types type = actualOp1->GetRegTypeByIndex(i); + regNumber reg = op1->GetRegByIndex(i); + if (reg == REG_NA) { - // GT_COPY/GT_RELOAD will have valid reg for those positions + // GT_COPY/GT_RELOAD will have valid reg only for those positions // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); - if (reloadReg != REG_NA) - { - reg = reloadReg; - } + assert(op1->IsCopyOrReload()); + reg = actualOp1->GetRegByIndex(i); } assert(reg != REG_NA); @@ -1471,7 +1459,7 @@ void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode) offset += genTypeSize(type); } - // Updating variable liveness after instruction was emitted + // Update variable liveness. genUpdateLife(treeNode); varDsc->SetRegNum(REG_STK); } @@ -2333,132 +2321,6 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); } -//------------------------------------------------------------------------ -// genRegCopy: Produce code for a GT_COPY node. -// -// Arguments: -// tree - the GT_COPY node -// -// Notes: -// This will copy the register(s) produced by this node's source, to -// the register(s) allocated to this GT_COPY node. -// It has some special handling for these cases: -// - when the source and target registers are in different register files -// (note that this is *not* a conversion). -// - when the source is a lclVar whose home location is being moved to a new -// register (rather than just being copied for temporary use). -// -void CodeGen::genRegCopy(GenTree* treeNode) -{ - assert(treeNode->OperGet() == GT_COPY); - GenTree* op1 = treeNode->AsOp()->gtOp1; - - regNumber sourceReg = genConsumeReg(op1); - - if (op1->IsMultiRegNode()) - { - noway_assert(!op1->IsCopyOrReload()); - unsigned regCount = op1->GetMultiRegCount(); - for (unsigned i = 0; i < regCount; i++) - { - regNumber srcReg = op1->GetRegByIndex(i); - regNumber tgtReg = treeNode->AsCopyOrReload()->GetRegNumByIdx(i); - var_types regType = op1->GetRegTypeByIndex(i); - inst_RV_RV(ins_Copy(regType), tgtReg, srcReg, regType); - } - } - else - { - var_types targetType = treeNode->TypeGet(); - regNumber targetReg = treeNode->GetRegNum(); - assert(targetReg != REG_NA); - assert(targetType != TYP_STRUCT); - - // Check whether this node and the node from which we're copying the value have the same - // register type. - // This can happen if (currently iff) we have a SIMD vector type that fits in an integer - // register, in which case it is passed as an argument, or returned from a call, - // in an integer register and must be copied if it's in a floating point register. - - bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1)); - bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode)); - if (srcFltReg != tgtFltReg) - { -#ifdef TARGET_ARM64 - inst_RV_RV(INS_fmov, targetReg, sourceReg, targetType); -#else // !TARGET_ARM64 - if (varTypeIsFloating(treeNode)) - { - // GT_COPY from 'int' to 'float' currently can't happen. Maybe if ARM SIMD is implemented - // it will happen, according to the comment above? - NYI_ARM("genRegCopy from 'int' to 'float'"); - } - else - { - assert(varTypeIsFloating(op1)); - - if (op1->TypeGet() == TYP_FLOAT) - { - inst_RV_RV(INS_vmov_f2i, targetReg, genConsumeReg(op1), targetType); - } - else - { - regNumber otherReg = (regNumber)treeNode->AsCopyOrReload()->gtOtherRegs[0]; - assert(otherReg != REG_NA); - inst_RV_RV_RV(INS_vmov_d2i, targetReg, otherReg, genConsumeReg(op1), EA_8BYTE); - } - } -#endif // !TARGET_ARM64 - } - else - { - inst_RV_RV(ins_Copy(targetType), targetReg, sourceReg, targetType); - } - } - - if (op1->IsLocal()) - { - // The lclVar will never be a def. - // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will - // appropriately set the gcInfo for the copied value. - // If not, there are two cases we need to handle: - // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable - // will remain live in its original register. - // genProduceReg() will appropriately set the gcInfo for the copied value, - // and genConsumeReg will reset it. - // - Otherwise, we need to update register info for the lclVar. - - GenTreeLclVarCommon* lcl = op1->AsLclVarCommon(); - assert((lcl->gtFlags & GTF_VAR_DEF) == 0); - - if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0) - { - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - - // If we didn't just spill it (in genConsumeReg, above), then update the register info - if (varDsc->GetRegNum() != REG_STK) - { - // The old location is dying - genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1)); - - gcInfo.gcMarkRegSetNpt(genRegMask(op1->GetRegNum())); - - genUpdateVarReg(varDsc, treeNode); - -#ifdef USING_VARIABLE_LIVE_RANGE - // Report the home change for this variable - varLiveKeeper->siUpdateVariableLiveRange(varDsc, lcl->GetLclNum()) -#endif // USING_VARIABLE_LIVE_RANGE - - // The new location is going live - genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode)); - } - } - } - - genProduceReg(treeNode); -} - //------------------------------------------------------------------------ // genCallInstruction: Produce code for a GT_CALL node // @@ -2610,9 +2472,9 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } // Determine return value size(s). - ReturnTypeDesc* pRetTypeDesc = call->GetReturnTypeDesc(); - emitAttr retSize = EA_PTRSIZE; - emitAttr secondRetSize = EA_UNKNOWN; + const ReturnTypeDesc* pRetTypeDesc = call->GetReturnTypeDesc(); + emitAttr retSize = EA_PTRSIZE; + emitAttr secondRetSize = EA_UNKNOWN; if (call->HasMultiRegRetVal()) { @@ -2658,6 +2520,27 @@ void CodeGen::genCallInstruction(GenTreeCall* call) INDEBUG_LDISASM_COMMA(sigInfo) nullptr, // addr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), ilOffset, target->GetRegNum()); } +#if defined(FEATURE_READYTORUN_COMPILER) && defined(TARGET_ARMARCH) + else if (call->IsR2RRelativeIndir()) + { + // Generate a direct call to a non-virtual user defined or helper method + assert(callType == CT_HELPER || callType == CT_USER_FUNC); + assert(call->gtEntryPoint.accessType == IAT_PVALUE); + assert(call->gtControlExpr == nullptr); + + regNumber tmpReg = call->GetSingleTempReg(); + GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, REG_R2R_INDIRECT_PARAM); + + // We have now generated code for gtControlExpr evaluating it into `tmpReg`. + // We just need to emit "call tmpReg" in this case. + // + assert(genIsValidIntReg(tmpReg)); + + genEmitCall(emitter::EC_INDIR_R, methHnd, + INDEBUG_LDISASM_COMMA(sigInfo) nullptr, // addr + retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), ilOffset, tmpReg); + } +#endif // FEATURE_READYTORUN_COMPILER && TARGET_ARMARCH else { // Generate a direct call to a non-virtual user defined or helper method @@ -3759,264 +3642,49 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) genProduceReg(lea); } +#ifdef FEATURE_SIMD //------------------------------------------------------------------------ -// isStructReturn: Returns whether the 'treeNode' is returning a struct. -// -// Arguments: -// treeNode - The tree node to evaluate whether is a struct return. -// -// Return Value: -// Returns true if the 'treeNode" is a GT_RETURN node of type struct. -// Otherwise returns false. -// -bool CodeGen::isStructReturn(GenTree* treeNode) -{ - // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN. - // For the GT_RET_FILT, the return is always - // a bool or a void, for the end of a finally block. - noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - var_types returnType = treeNode->TypeGet(); - -#ifdef TARGET_ARM64 - return varTypeIsStruct(returnType) && (compiler->info.compRetNativeType == TYP_STRUCT); -#else - return varTypeIsStruct(returnType); -#endif -} - -//------------------------------------------------------------------------ -// genStructReturn: Generates code for returning a struct. +// genSIMDSplitReturn: Generates code for returning a fixed-size SIMD type that lives +// in a single register, but is returned in multiple registers. // // Arguments: -// treeNode - The GT_RETURN tree node. -// -// Return Value: -// None +// src - The source of the return +// retTypeDesc - The return type descriptor. // -// Assumption: -// op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL -void CodeGen::genStructReturn(GenTree* treeNode) +void CodeGen::genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc) { - assert(treeNode->OperGet() == GT_RETURN); - assert(isStructReturn(treeNode)); - GenTree* op1 = treeNode->gtGetOp1(); - - if (op1->OperGet() == GT_LCL_VAR) - { - GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon(); - LclVarDsc* varDsc = &(compiler->lvaTable[lclVar->GetLclNum()]); - var_types lclType = genActualType(varDsc->TypeGet()); - - assert(varTypeIsStruct(lclType)); - assert(varDsc->lvIsMultiRegRet); - - ReturnTypeDesc retTypeDesc; - unsigned regCount; - - retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); - regCount = retTypeDesc.GetReturnRegCount(); - - assert(regCount >= 2); - - assert(varTypeIsSIMD(lclType) || op1->isContained()); - - if (op1->isContained()) - { - // Copy var on stack into ABI return registers - // TODO: It could be optimized by reducing two float loading to one double - int offset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc.GetReturnRegType(i); - regNumber reg = retTypeDesc.GetABIReturnReg(i); - GetEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), reg, lclVar->GetLclNum(), offset); - offset += genTypeSize(type); - } + assert(varTypeIsSIMD(src)); + assert(src->isUsedFromReg()); + regNumber srcReg = src->GetRegNum(); + + // Treat src register as a homogenous vector with element size equal to the reg size + // Insert pieces in order + unsigned regCount = retTypeDesc->GetReturnRegCount(); + for (unsigned i = 0; i < regCount; ++i) + { + var_types type = retTypeDesc->GetReturnRegType(i); + regNumber reg = retTypeDesc->GetABIReturnReg(i); + if (varTypeIsFloating(type)) + { + // If the register piece is to be passed in a floating point register + // Use a vector mov element instruction + // reg is not a vector, so it is in the first element reg[0] + // mov reg[0], src[i] + // This effectively moves from `src[i]` to `reg[0]`, upper bits of reg remain unchanged + // For the case where src == reg, since we are only writing reg[0], as long as we iterate + // so that src[0] is consumed before writing reg[0], we do not need a temporary. + GetEmitter()->emitIns_R_R_I_I(INS_mov, emitTypeSize(type), reg, srcReg, 0, i); } else { - // Handle SIMD genStructReturn case - NYI_ARM("SIMD genStructReturn"); - -#ifdef TARGET_ARM64 - genConsumeRegs(op1); - regNumber src = op1->GetRegNum(); - - // Treat src register as a homogenous vector with element size equal to the reg size - // Insert pieces in order - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc.GetReturnRegType(i); - regNumber reg = retTypeDesc.GetABIReturnReg(i); - if (varTypeIsFloating(type)) - { - // If the register piece is to be passed in a floating point register - // Use a vector mov element instruction - // reg is not a vector, so it is in the first element reg[0] - // mov reg[0], src[i] - // This effectively moves from `src[i]` to `reg[0]`, upper bits of reg remain unchanged - // For the case where src == reg, since we are only writing reg[0], as long as we iterate - // so that src[0] is consumed before writing reg[0], we do not need a temporary. - GetEmitter()->emitIns_R_R_I_I(INS_mov, emitTypeSize(type), reg, src, 0, i); - } - else - { - // If the register piece is to be passed in an integer register - // Use a vector mov to general purpose register instruction - // mov reg, src[i] - // This effectively moves from `src[i]` to `reg` - GetEmitter()->emitIns_R_R_I(INS_mov, emitTypeSize(type), reg, src, i); - } - } -#endif // TARGET_ARM64 + // If the register piece is to be passed in an integer register + // Use a vector mov to general purpose register instruction + // mov reg, src[i] + // This effectively moves from `src[i]` to `reg` + GetEmitter()->emitIns_R_R_I(INS_mov, emitTypeSize(type), reg, srcReg, i); } } - else // op1 must be multi-reg GT_CALL - { - assert(op1->IsMultiRegCall() || op1->IsCopyOrReloadOfMultiRegCall()); - - genConsumeRegs(op1); - - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - - ReturnTypeDesc* pRetTypeDesc; - unsigned regCount; - unsigned matchingCount = 0; - - pRetTypeDesc = call->GetReturnTypeDesc(); - regCount = pRetTypeDesc->GetReturnRegCount(); - - var_types regType[MAX_RET_REG_COUNT]; - regNumber returnReg[MAX_RET_REG_COUNT]; - regNumber allocatedReg[MAX_RET_REG_COUNT]; - regMaskTP srcRegsMask = 0; - regMaskTP dstRegsMask = 0; - bool needToShuffleRegs = false; // Set to true if we have to move any registers - - for (unsigned i = 0; i < regCount; ++i) - { - regType[i] = pRetTypeDesc->GetReturnRegType(i); - returnReg[i] = pRetTypeDesc->GetABIReturnReg(i); - - regNumber reloadReg = REG_NA; - if (op1->IsCopyOrReload()) - { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); - } - - if (reloadReg != REG_NA) - { - allocatedReg[i] = reloadReg; - } - else - { - allocatedReg[i] = call->GetRegNumByIdx(i); - } - - if (returnReg[i] == allocatedReg[i]) - { - matchingCount++; - } - else // We need to move this value - { - // We want to move the value from allocatedReg[i] into returnReg[i] - // so record these two registers in the src and dst masks - // - srcRegsMask |= genRegMask(allocatedReg[i]); - dstRegsMask |= genRegMask(returnReg[i]); - - needToShuffleRegs = true; - } - } - - if (needToShuffleRegs) - { - assert(matchingCount < regCount); - - unsigned remainingRegCount = regCount - matchingCount; - regMaskTP extraRegMask = treeNode->gtRsvdRegs; - - while (remainingRegCount > 0) - { - // set 'available' to the 'dst' registers that are not currently holding 'src' registers - // - regMaskTP availableMask = dstRegsMask & ~srcRegsMask; - - regMaskTP dstMask; - regNumber srcReg; - regNumber dstReg; - var_types curType = TYP_UNKNOWN; - regNumber freeUpReg = REG_NA; - - if (availableMask == 0) - { - // Circular register dependencies - // So just free up the lowest register in dstRegsMask by moving it to the 'extra' register - - assert(dstRegsMask == srcRegsMask); // this has to be true for us to reach here - assert(extraRegMask != 0); // we require an 'extra' register - assert((extraRegMask & ~dstRegsMask) != 0); // it can't be part of dstRegsMask - - availableMask = extraRegMask & ~dstRegsMask; - - regMaskTP srcMask = genFindLowestBit(srcRegsMask); - freeUpReg = genRegNumFromMask(srcMask); - } - - dstMask = genFindLowestBit(availableMask); - dstReg = genRegNumFromMask(dstMask); - srcReg = REG_NA; - - if (freeUpReg != REG_NA) - { - // We will free up the srcReg by moving it to dstReg which is an extra register - // - srcReg = freeUpReg; - - // Find the 'srcReg' and set 'curType', change allocatedReg[] to dstReg - // and add the new register mask bit to srcRegsMask - // - for (unsigned i = 0; i < regCount; ++i) - { - if (allocatedReg[i] == srcReg) - { - curType = regType[i]; - allocatedReg[i] = dstReg; - srcRegsMask |= genRegMask(dstReg); - } - } - } - else // The normal case - { - // Find the 'srcReg' and set 'curType' - // - for (unsigned i = 0; i < regCount; ++i) - { - if (returnReg[i] == dstReg) - { - srcReg = allocatedReg[i]; - curType = regType[i]; - } - } - // After we perform this move we will have one less registers to setup - remainingRegCount--; - } - assert(curType != TYP_UNKNOWN); - - inst_RV_RV(ins_Copy(curType), dstReg, srcReg, curType); - - // Clear the appropriate bits in srcRegsMask and dstRegsMask - srcRegsMask &= ~genRegMask(srcReg); - dstRegsMask &= ~genRegMask(dstReg); - - } // while (remainingRegCount > 0) - - } // (needToShuffleRegs) - - } // op1 must be multi-reg GT_CALL } +#endif // FEATURE_SIMD #endif // TARGET_ARMARCH diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 452d4f47a6fc6..3c4f9efc947af 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -4596,8 +4596,9 @@ void CodeGen::genCheckUseBlockInit() // double-counting the initialization impact of any locals. bool counted = false; - if (varDsc->lvIsParam) + if (!varDsc->lvIsInReg() && !varDsc->lvOnFrame) { + noway_assert(varDsc->lvRefCnt() == 0); continue; } @@ -4608,44 +4609,10 @@ void CodeGen::genCheckUseBlockInit() continue; } - // Likewise, initialization of the GS cookie is handled specially for OSR. - // Could do this for non-OSR too.. (likewise for the dummy) - if (compiler->opts.IsOSR() && varNum == compiler->lvaGSSecurityCookie) - { - continue; - } - - if (!varDsc->lvIsInReg() && !varDsc->lvOnFrame) - { - noway_assert(varDsc->lvRefCnt() == 0); - continue; - } - - if (varNum == compiler->lvaInlinedPInvokeFrameVar || varNum == compiler->lvaStubArgumentVar || - varNum == compiler->lvaRetAddrVar) - { - continue; - } - -#if FEATURE_FIXED_OUT_ARGS - if (varNum == compiler->lvaPInvokeFrameRegSaveVar) - { - continue; - } - if (varNum == compiler->lvaOutgoingArgSpaceVar) - { - continue; - } -#endif - -#if defined(FEATURE_EH_FUNCLETS) - // There's no need to force 0-initialization of the PSPSym, it will be - // initialized with a real value in the prolog - if (varNum == compiler->lvaPSPSym) + if (compiler->fgVarIsNeverZeroInitializedInProlog(varNum)) { continue; } -#endif if (compiler->lvaIsFieldOfDependentlyPromotedStruct(varDsc)) { @@ -4655,6 +4622,12 @@ void CodeGen::genCheckUseBlockInit() continue; } + if (varDsc->lvHasExplicitInit) + { + varDsc->lvMustInit = 0; + continue; + } + if (compiler->info.compInitMem || varDsc->HasGCPtr() || varDsc->lvMustInit) { if (varDsc->lvTracked) @@ -4848,7 +4821,7 @@ void CodeGen::genCheckUseBlockInit() */ #if defined(TARGET_ARM64) -void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegModified) #else void CodeGen::genPushCalleeSavedRegisters() #endif @@ -5337,7 +5310,8 @@ void CodeGen::genPushCalleeSavedRegisters() JITDUMP(" spAdjustment2=%d\n", spAdjustment2); - genPrologSaveRegPair(REG_FP, REG_LR, alignmentAdjustment2, -spAdjustment2, false, initReg, pInitRegZeroed); + genPrologSaveRegPair(REG_FP, REG_LR, alignmentAdjustment2, -spAdjustment2, false, initReg, + pInitRegModified); offset += spAdjustment2; // Now subtract off the #outsz (or the rest of the #outsz if it was unaligned, and the above "sub" @@ -5357,13 +5331,13 @@ void CodeGen::genPushCalleeSavedRegisters() // We've already established the frame pointer, so no need to report the stack pointer change to unwind // info. - genStackPointerAdjustment(-spAdjustment3, initReg, pInitRegZeroed, /* reportUnwindData */ false); + genStackPointerAdjustment(-spAdjustment3, initReg, pInitRegModified, /* reportUnwindData */ false); offset += spAdjustment3; } else { genPrologSaveRegPair(REG_FP, REG_LR, compiler->lvaOutgoingArgSpaceSize, -remainingFrameSz, false, initReg, - pInitRegZeroed); + pInitRegModified); offset += remainingFrameSz; offsetSpToSavedFp = compiler->lvaOutgoingArgSpaceSize; @@ -5395,7 +5369,7 @@ void CodeGen::genPushCalleeSavedRegisters() JITDUMP(" remainingFrameSz=%d\n", remainingFrameSz); // We've already established the frame pointer, so no need to report the stack pointer change to unwind info. - genStackPointerAdjustment(-remainingFrameSz, initReg, pInitRegZeroed, /* reportUnwindData */ false); + genStackPointerAdjustment(-remainingFrameSz, initReg, pInitRegModified, /* reportUnwindData */ false); offset += remainingFrameSz; } else @@ -6124,17 +6098,17 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) #endif // TARGET* -// We need a register with value zero. Zero the initReg, if necessary, and set *pInitRegZeroed if so. +// We need a register with value zero. Zero the initReg, if necessary, and set *pInitRegModified if so. // Return the register to use. On ARM64, we never touch the initReg, and always just return REG_ZR. -regNumber CodeGen::genGetZeroReg(regNumber initReg, bool* pInitRegZeroed) +regNumber CodeGen::genGetZeroReg(regNumber initReg, bool* pInitRegModified) { #ifdef TARGET_ARM64 return REG_ZR; #else // !TARGET_ARM64 - if (*pInitRegZeroed == false) + if (*pInitRegModified) { instGen_Set_Reg_To_Zero(EA_PTRSIZE, initReg); - *pInitRegZeroed = true; + *pInitRegModified = false; } return initReg; #endif // !TARGET_ARM64 @@ -6144,14 +6118,14 @@ regNumber CodeGen::genGetZeroReg(regNumber initReg, bool* pInitRegZeroed) // genZeroInitFrame: Zero any untracked pointer locals and/or initialize memory for locspace // // Arguments: -// untrLclHi - (Untracked locals High-Offset) The upper bound offset at which the zero init -// code will end initializing memory (not inclusive). -// untrLclLo - (Untracked locals Low-Offset) The lower bound at which the zero init code will -// start zero initializing memory. -// initReg - A scratch register (that gets set to zero on some platforms). -// pInitRegZeroed - Sets a flag that tells the callee whether or not the initReg register got zeroed. +// untrLclHi - (Untracked locals High-Offset) The upper bound offset at which the zero init +// code will end initializing memory (not inclusive). +// untrLclLo - (Untracked locals Low-Offset) The lower bound at which the zero init code will +// start zero initializing memory. +// initReg - A scratch register (that gets set to zero on some platforms). +// pInitRegModified - Sets a flag that tells the callee whether or not the initReg register got zeroed. // -void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -6226,8 +6200,8 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, #else // !define(TARGET_ARM) - rAddr = initReg; - *pInitRegZeroed = false; + rAddr = initReg; + *pInitRegModified = true; #endif // !defined(TARGET_ARM) @@ -6268,7 +6242,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, // Load immediate into the InitReg register instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, (ssize_t)untrLclLo); GetEmitter()->emitIns_R_R_R(INS_add, EA_PTRSIZE, rAddr, genFramePointerReg(), initReg); - *pInitRegZeroed = false; + *pInitRegModified = true; } if (useLoop) @@ -6280,7 +6254,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, } #if defined(TARGET_ARM) - rZero1 = genGetZeroReg(initReg, pInitRegZeroed); + rZero1 = genGetZeroReg(initReg, pInitRegModified); instGen_Set_Reg_To_Zero(EA_PTRSIZE, rZero2); target_ssize_t stmImm = (target_ssize_t)(genRegMask(rZero1) | genRegMask(rZero2)); #endif // TARGET_ARM @@ -6369,7 +6343,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, #endif if (blkSize < minSimdSize) { - zeroReg = genGetZeroReg(initReg, pInitRegZeroed); + zeroReg = genGetZeroReg(initReg, pInitRegModified); int i = 0; for (; i + REGSIZE_BYTES <= blkSize; i += REGSIZE_BYTES) @@ -6431,7 +6405,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, assert(alignmentLoBlkSize < XMM_REGSIZE_BYTES); assert((alignedLclLo - alignmentLoBlkSize) == untrLclLo); - zeroReg = genGetZeroReg(initReg, pInitRegZeroed); + zeroReg = genGetZeroReg(initReg, pInitRegModified); int i = 0; for (; i + REGSIZE_BYTES <= alignmentLoBlkSize; i += REGSIZE_BYTES) @@ -6539,7 +6513,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, emit->emitIns_J(INS_jne, nullptr, -5); // initReg will be zero at end of the loop - *pInitRegZeroed = true; + *pInitRegModified = false; } if (untrLclHi != alignedLclHi) @@ -6548,7 +6522,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, assert(alignmentHiBlkSize < XMM_REGSIZE_BYTES); assert((alignedLclHi + alignmentHiBlkSize) == untrLclHi); - zeroReg = genGetZeroReg(initReg, pInitRegZeroed); + zeroReg = genGetZeroReg(initReg, pInitRegModified); int i = 0; for (; i + REGSIZE_BYTES <= alignmentHiBlkSize; i += REGSIZE_BYTES) @@ -6615,13 +6589,13 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, if (layout->IsGCPtr(i)) { GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, - genGetZeroReg(initReg, pInitRegZeroed), varNum, i * REGSIZE_BYTES); + genGetZeroReg(initReg, pInitRegModified), varNum, i * REGSIZE_BYTES); } } } else { - regNumber zeroReg = genGetZeroReg(initReg, pInitRegZeroed); + regNumber zeroReg = genGetZeroReg(initReg, pInitRegModified); // zero out the whole thing rounded up to a single stack slot size unsigned lclSize = roundUp(compiler->lvaLclSize(varNum), (unsigned)sizeof(int)); @@ -6653,7 +6627,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, // printf("initialize untracked spillTmp [EBP-%04X]\n", stkOffs); - inst_ST_RV(ins_Store(TYP_I_IMPL), tempThis, 0, genGetZeroReg(initReg, pInitRegZeroed), TYP_I_IMPL); + inst_ST_RV(ins_Store(TYP_I_IMPL), tempThis, 0, genGetZeroReg(initReg, pInitRegModified), TYP_I_IMPL); } } @@ -6788,7 +6762,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, * ICodeManager::GetParamTypeArg(). */ -void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegModified) { // For OSR the original method has set this up for us. if (compiler->opts.IsOSR()) @@ -6853,8 +6827,8 @@ void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed // We will just use the initReg since it is an available register // and we are probably done using it anyway... - reg = initReg; - *pInitRegZeroed = false; + reg = initReg; + *pInitRegModified = true; // mov reg, [compiler->info.compTypeCtxtArg] GetEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, reg, genFramePointerReg(), varDsc->lvStkOffs); @@ -7698,9 +7672,9 @@ void CodeGen::genFnProlog() /* Choose the register to use for zero initialization */ - regNumber initReg = REG_SCRATCH; // Unless we find a better register below - bool initRegZeroed = false; - regMaskTP excludeMask = intRegState.rsCalleeRegArgMaskLiveIn; + regNumber initReg = REG_SCRATCH; // Unless we find a better register below + bool initRegModified = true; + regMaskTP excludeMask = intRegState.rsCalleeRegArgMaskLiveIn; regMaskTP tempMask; // We should not use the special PINVOKE registers as the initReg @@ -7833,11 +7807,11 @@ void CodeGen::genFnProlog() // been calculated to be one of the callee-saved registers (say, if all the integer argument registers are // in use, and perhaps with other conditions being satisfied). This is ok in other cases, after the callee-saved // registers have been saved. So instead of letting genAllocLclFrame use initReg as a temporary register, - // always use REG_SCRATCH. We don't care if it trashes it, so ignore the initRegZeroed output argument. - bool ignoreInitRegZeroed = false; - genAllocLclFrame(compiler->compLclFrameSize, REG_SCRATCH, &ignoreInitRegZeroed, + // always use REG_SCRATCH. We don't care if it trashes it, so ignore the initRegModified output argument. + bool ignoreInitRegModified = true; + genAllocLclFrame(compiler->compLclFrameSize, REG_SCRATCH, &ignoreInitRegModified, intRegState.rsCalleeRegArgMaskLiveIn); - genPushCalleeSavedRegisters(initReg, &initRegZeroed); + genPushCalleeSavedRegisters(initReg, &initRegModified); #else // !TARGET_ARM64 genPushCalleeSavedRegisters(); #endif // !TARGET_ARM64 @@ -7881,7 +7855,7 @@ void CodeGen::genFnProlog() if (maskStackAlloc == RBM_NONE) { - genAllocLclFrame(compiler->compLclFrameSize, initReg, &initRegZeroed, intRegState.rsCalleeRegArgMaskLiveIn); + genAllocLclFrame(compiler->compLclFrameSize, initReg, &initRegModified, intRegState.rsCalleeRegArgMaskLiveIn); } #endif // !TARGET_ARM64 @@ -7944,11 +7918,11 @@ void CodeGen::genFnProlog() // Zero out the frame as needed // - genZeroInitFrame(untrLclHi, untrLclLo, initReg, &initRegZeroed); + genZeroInitFrame(untrLclHi, untrLclLo, initReg, &initRegModified); #if defined(FEATURE_EH_FUNCLETS) - genSetPSPSym(initReg, &initRegZeroed); + genSetPSPSym(initReg, &initRegModified); #else // !FEATURE_EH_FUNCLETS @@ -7961,10 +7935,10 @@ void CodeGen::genFnProlog() // Zero out the slot for nesting level 0 unsigned firstSlotOffs = filterEndOffsetSlotOffs - TARGET_POINTER_SIZE; - if (!initRegZeroed) + if (initRegModified) { instGen_Set_Reg_To_Zero(EA_PTRSIZE, initReg); - initRegZeroed = true; + initRegModified = false; } GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, initReg, compiler->lvaShadowSPslotsVar, @@ -7973,7 +7947,7 @@ void CodeGen::genFnProlog() #endif // !FEATURE_EH_FUNCLETS - genReportGenericContextArg(initReg, &initRegZeroed); + genReportGenericContextArg(initReg, &initRegModified); #ifdef JIT32_GCENCODER // Initialize the LocalAllocSP slot if there is localloc in the function. @@ -7985,7 +7959,7 @@ void CodeGen::genFnProlog() // Set up the GS security cookie - genSetGSSecurityCookie(initReg, &initRegZeroed); + genSetGSSecurityCookie(initReg, &initRegModified); #ifdef PROFILING_SUPPORTED @@ -7993,7 +7967,7 @@ void CodeGen::genFnProlog() // OSR methods aren't called, so don't have enter hooks. if (!compiler->opts.IsOSR()) { - genProfilingEnterCallback(initReg, &initRegZeroed); + genProfilingEnterCallback(initReg, &initRegModified); } #endif // PROFILING_SUPPORTED @@ -8055,15 +8029,15 @@ void CodeGen::genFnProlog() } else { - xtraReg = REG_SCRATCH; - initRegZeroed = false; + xtraReg = REG_SCRATCH; + initRegModified = true; } genFnPrologCalleeRegArgs(xtraReg, &xtraRegClobbered, regState); if (xtraRegClobbered) { - initRegZeroed = false; + initRegModified = true; } } } @@ -8083,7 +8057,7 @@ void CodeGen::genFnProlog() if (regMask & initRegs) { // Check if we have already zeroed this register - if ((reg == initReg) && initRegZeroed) + if ((reg == initReg) && !initRegModified) { continue; } @@ -8092,7 +8066,7 @@ void CodeGen::genFnProlog() instGen_Set_Reg_To_Zero(EA_PTRSIZE, reg); if (reg == initReg) { - initRegZeroed = true; + initRegModified = false; } } } @@ -8104,17 +8078,17 @@ void CodeGen::genFnProlog() // If initReg is not in initRegs then we will use REG_SCRATCH if ((genRegMask(initReg) & initRegs) == 0) { - initReg = REG_SCRATCH; - initRegZeroed = false; + initReg = REG_SCRATCH; + initRegModified = true; } #ifdef TARGET_ARM // This is needed only for Arm since it can use a zero initialized int register // to initialize vfp registers. - if (!initRegZeroed) + if (initRegModified) { instGen_Set_Reg_To_Zero(EA_PTRSIZE, initReg); - initRegZeroed = true; + initRegModified = false; } #endif // TARGET_ARM @@ -9121,12 +9095,12 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_R0; } - regNumber initReg = REG_R3; // R3 is never live on entry to a funclet, so it can be trashed - bool initRegZeroed = false; + regNumber initReg = REG_R3; // R3 is never live on entry to a funclet, so it can be trashed + bool initRegModified = true; if (maskStackAlloc == RBM_NONE) { - genAllocLclFrame(genFuncletInfo.fiSpDelta, initReg, &initRegZeroed, maskArgRegsLiveIn); + genAllocLclFrame(genFuncletInfo.fiSpDelta, initReg, &initRegModified, maskArgRegsLiveIn); } // This is the end of the OS-reported prolog for purposes of unwinding @@ -9423,10 +9397,10 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_ARG_0 | RBM_ARG_2; } - regNumber initReg = REG_EBP; // We already saved EBP, so it can be trashed - bool initRegZeroed = false; + regNumber initReg = REG_EBP; // We already saved EBP, so it can be trashed + bool initRegModified = true; - genAllocLclFrame(genFuncletInfo.fiSpDelta, initReg, &initRegZeroed, maskArgRegsLiveIn); + genAllocLclFrame(genFuncletInfo.fiSpDelta, initReg, &initRegModified, maskArgRegsLiveIn); // Callee saved float registers are copied to stack in their assigned stack slots // after allocating space for them as part of funclet frame. @@ -9765,7 +9739,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() * correctly reported, the PSPSym could be omitted in some cases.) *********************************** */ -void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -9811,8 +9785,8 @@ void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegZeroed) // We will just use the initReg since it is an available register // and we are probably done using it anyway... - regNumber regTmp = initReg; - *pInitRegZeroed = false; + regNumber regTmp = initReg; + *pInitRegModified = true; GetEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, regTmp, regBase, callerSPOffs); GetEmitter()->emitIns_S_R(INS_str, EA_PTRSIZE, regTmp, compiler->lvaPSPSym, 0); @@ -9823,8 +9797,8 @@ void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegZeroed) // We will just use the initReg since it is an available register // and we are probably done using it anyway... - regNumber regTmp = initReg; - *pInitRegZeroed = false; + regNumber regTmp = initReg; + *pInitRegModified = true; GetEmitter()->emitIns_R_R_Imm(INS_add, EA_PTRSIZE, regTmp, REG_SPBASE, SPtoCallerSPdelta); GetEmitter()->emitIns_S_R(INS_str, EA_PTRSIZE, regTmp, compiler->lvaPSPSym, 0); @@ -11554,7 +11528,7 @@ void CodeGen::genReturn(GenTree* treeNode) { if (varTypeIsLong(compiler->info.compRetNativeType)) { - retTypeDesc.InitializeLongReturnType(compiler); + retTypeDesc.InitializeLongReturnType(); } else // we must have a struct return type { @@ -11627,6 +11601,282 @@ void CodeGen::genReturn(GenTree* treeNode) #endif // defined(DEBUG) && defined(TARGET_XARCH) } +//------------------------------------------------------------------------ +// isStructReturn: Returns whether the 'treeNode' is returning a struct. +// +// Arguments: +// treeNode - The tree node to evaluate whether is a struct return. +// +// Return Value: +// Returns true if the 'treeNode" is a GT_RETURN node of type struct. +// Otherwise returns false. +// +bool CodeGen::isStructReturn(GenTree* treeNode) +{ + // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN. + // For the GT_RET_FILT, the return is always a bool or a void, for the end of a finally block. + noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); + if (treeNode->OperGet() != GT_RETURN) + { + return false; + } + +#if defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI) + assert(!varTypeIsStruct(treeNode)); + return false; +#elif defined(TARGET_ARM64) + return varTypeIsStruct(treeNode) && (compiler->info.compRetNativeType == TYP_STRUCT); +#else + return varTypeIsStruct(treeNode); +#endif +} + +//------------------------------------------------------------------------ +// genStructReturn: Generates code for returning a struct. +// +// Arguments: +// treeNode - The GT_RETURN tree node. +// +// Return Value: +// None +// +// Assumption: +// op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL +// +void CodeGen::genStructReturn(GenTree* treeNode) +{ + assert(treeNode->OperGet() == GT_RETURN); + GenTree* op1 = treeNode->gtGetOp1(); + genConsumeRegs(op1); + GenTree* actualOp1 = op1; + if (op1->IsCopyOrReload()) + { + actualOp1 = op1->gtGetOp1(); + } + + ReturnTypeDesc retTypeDesc; + LclVarDsc* varDsc = nullptr; + if (actualOp1->OperIs(GT_LCL_VAR)) + { + varDsc = compiler->lvaGetDesc(actualOp1->AsLclVar()->GetLclNum()); + retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); + } + else + { + assert(actualOp1->OperIs(GT_CALL)); + retTypeDesc = *(actualOp1->AsCall()->GetReturnTypeDesc()); + } + unsigned regCount = retTypeDesc.GetReturnRegCount(); + assert(regCount <= MAX_RET_REG_COUNT); + +#if FEATURE_MULTIREG_RET + if (actualOp1->OperIs(GT_LCL_VAR) && (varTypeIsEnregisterable(op1))) + { + // Right now the only enregisterable structs supported are SIMD vector types. + assert(varTypeIsSIMD(op1)); +#ifdef FEATURE_SIMD + genSIMDSplitReturn(op1, &retTypeDesc); +#endif // FEATURE_SIMD + } + else if (actualOp1->OperIs(GT_LCL_VAR)) + { + GenTreeLclVar* lclNode = actualOp1->AsLclVar(); + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNode->GetLclNum()); + assert(varDsc->lvIsMultiRegRet); + int offset = 0; + for (unsigned i = 0; i < regCount; ++i) + { + var_types type = retTypeDesc.GetReturnRegType(i); + regNumber toReg = retTypeDesc.GetABIReturnReg(i); + GetEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), toReg, lclNode->GetLclNum(), offset); + offset += genTypeSize(type); + } + } + else + { + assert(actualOp1->IsMultiRegCall()); + for (unsigned i = 0; i < regCount; ++i) + { + var_types type = retTypeDesc.GetReturnRegType(i); + regNumber toReg = retTypeDesc.GetABIReturnReg(i); + regNumber fromReg = op1->GetRegByIndex(i); + if (fromReg == REG_NA) + { + assert(op1->IsCopyOrReload()); + fromReg = actualOp1->GetRegByIndex(i); + } + if (fromReg != toReg) + { + inst_RV_RV(ins_Copy(type), toReg, fromReg, type); + } + } + } +#else // !FEATURE_MULTIREG_RET + unreached(); +#endif +} + +//------------------------------------------------------------------------ +// genRegCopy: Produce code for a GT_COPY node. +// +// Arguments: +// tree - the GT_COPY node +// +// Notes: +// This will copy the register(s) produced by this nodes source, to +// the register(s) allocated to this GT_COPY node. +// It has some special handling for these casess: +// - when the source and target registers are in different register files +// (note that this is *not* a conversion). +// - when the source is a lclVar whose home location is being moved to a new +// register (rather than just being copied for temporary use). +// +void CodeGen::genRegCopy(GenTree* treeNode) +{ + assert(treeNode->OperGet() == GT_COPY); + GenTree* op1 = treeNode->AsOp()->gtOp1; + + if (op1->IsMultiRegNode()) + { + // Register allocation assumes that any reload and copy are done in operand order. + // That is, we can have: + // (reg0, reg1) = COPY(V0,V1) where V0 is in reg1 and V1 is in memory + // The register allocation model assumes: + // First, V0 is moved to reg0 (v1 can't be in reg0 because it is still live, which would be a conflict). + // Then, V1 is moved to reg1 + // However, if we call genConsumeRegs on op1, it will do the reload of V1 before we do the copy of V0. + // So we need to handle that case first. + // + // There should never be any circular dependencies, and we will check that here. + + GenTreeCopyOrReload* copyNode = treeNode->AsCopyOrReload(); + unsigned regCount = copyNode->GetRegCount(); + // GenTreeCopyOrReload only reports the number of registers that are valid. + assert(regCount <= MAX_MULTIREG_COUNT); + + // First set the source registers as busy if they haven't been spilled. + // (Note that this is just for verification that we don't have circular dependencies.) + regMaskTP busyRegs = RBM_NONE; + for (unsigned i = 0; i < regCount; ++i) + { + if ((op1->GetRegSpillFlagByIdx(i) & GTF_SPILLED) == 0) + { + busyRegs |= genRegMask(op1->GetRegByIndex(i)); + } + } + // First do any copies - we'll do the reloads after all the copies are complete. + for (unsigned i = 0; i < regCount; ++i) + { + regNumber sourceReg = op1->GetRegByIndex(i); + regNumber targetReg = copyNode->GetRegNumByIdx(i); + regMaskTP targetRegMask = genRegMask(targetReg); + // GenTreeCopyOrReload only reports the number of registers that are valid. + if (targetReg != REG_NA) + { + // We shouldn't specify a no-op move. + assert(sourceReg != targetReg); + assert((busyRegs & targetRegMask) == 0); + // Clear sourceReg from the busyRegs, and add targetReg. + busyRegs &= ~genRegMask(sourceReg); + busyRegs |= genRegMask(targetReg); + var_types type; + if (op1->IsMultiRegLclVar()) + { + type = op1->AsLclVar()->GetFieldTypeByIndex(compiler, i); + } + else + { + type = op1->GetRegTypeByIndex(i); + } + inst_RV_RV(ins_Copy(type), targetReg, sourceReg, type); + } + } + // Now we can consume op1, which will perform any necessary reloads. + genConsumeReg(op1); + } + else + { + var_types targetType = treeNode->TypeGet(); + regNumber targetReg = treeNode->GetRegNum(); + assert(targetReg != REG_NA); + assert(targetType != TYP_STRUCT); + + // Check whether this node and the node from which we're copying the value have + // different register types. This can happen if (currently iff) we have a SIMD + // vector type that fits in an integer register, in which case it is passed as + // an argument, or returned from a call, in an integer register and must be + // copied if it's in an xmm register. + + bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1)); + bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode)); + if (srcFltReg != tgtFltReg) + { + instruction ins; + regNumber fpReg; + regNumber intReg; + if (tgtFltReg) + { + ins = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet()); + fpReg = targetReg; + intReg = op1->GetRegNum(); + } + else + { + ins = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet()); + intReg = targetReg; + fpReg = op1->GetRegNum(); + } + inst_RV_RV(ins, fpReg, intReg, targetType); + } + else + { + inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType); + } + + if (op1->IsLocal()) + { + // The lclVar will never be a def. + // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will + // appropriately set the gcInfo for the copied value. + // If not, there are two cases we need to handle: + // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable + // will remain live in its original register. + // genProduceReg() will appropriately set the gcInfo for the copied value, + // and genConsumeReg will reset it. + // - Otherwise, we need to update register info for the lclVar. + + GenTreeLclVarCommon* lcl = op1->AsLclVarCommon(); + assert((lcl->gtFlags & GTF_VAR_DEF) == 0); + + if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0) + { + LclVarDsc* varDsc = compiler->lvaGetDesc(lcl); + + // If we didn't just spill it (in genConsumeReg, above), then update the register info + if (varDsc->GetRegNum() != REG_STK) + { + // The old location is dying + genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1)); + + gcInfo.gcMarkRegSetNpt(genRegMask(op1->GetRegNum())); + + genUpdateVarReg(varDsc, treeNode); + +#ifdef USING_VARIABLE_LIVE_RANGE + // Report the home change for this variable + varLiveKeeper->siUpdateVariableLiveRange(varDsc, lcl->GetLclNum()); +#endif // USING_VARIABLE_LIVE_RANGE + + // The new location is going live + genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode)); + } + } + } + } + + genProduceReg(treeNode); +} + #if defined(DEBUG) && defined(TARGET_XARCH) //------------------------------------------------------------------------ diff --git a/src/coreclr/src/jit/codegenlinear.cpp b/src/coreclr/src/jit/codegenlinear.cpp index e3973ba565119..b9ed297495f64 100644 --- a/src/coreclr/src/jit/codegenlinear.cpp +++ b/src/coreclr/src/jit/codegenlinear.cpp @@ -938,6 +938,86 @@ GenTree* sameRegAsDst(GenTree* tree, GenTree*& other /*out*/) } } +//------------------------------------------------------------------------ +// genUnspillLocal: Reload a register candidate local into a register. +// +// Arguments: +// varNum - The variable number of the local to be reloaded (unspilled). +// It may be a local field. +// type - The type of the local. +// lclNode - The node being unspilled. Note that for a multi-reg local, +// the gtLclNum will be that of the parent struct. +// regNum - The register that 'varNum' should be loaded to. +// reSpill - True if it will be immediately spilled after use. +// isLastUse - True if this is a last use of 'varNum'. +// +// Notes: +// The caller must have determined that this local needs to be unspilled. +void CodeGen::genUnspillLocal( + unsigned varNum, var_types type, GenTreeLclVar* lclNode, regNumber regNum, bool reSpill, bool isLastUse) +{ + LclVarDsc* varDsc = compiler->lvaGetDesc(varNum); + inst_set_SV_var(lclNode); + instruction ins = ins_Load(type, compiler->isSIMDTypeLocalAligned(varNum)); + GetEmitter()->emitIns_R_S(ins, emitTypeSize(type), regNum, varNum, 0); + + // TODO-Review: We would like to call: + // genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree)); + // instead of the following code, but this ends up hitting this assert: + // assert((regSet.GetMaskVars() & regMask) == 0); + // due to issues with LSRA resolution moves. + // So, just force it for now. This probably indicates a condition that creates a GC hole! + // + // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove, + // because the variable is not really going live or dead, but that method is somewhat poorly + // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo. + // TODO-Cleanup: This code exists in other CodeGen*.cpp files, and should be moved to CodeGenCommon.cpp. + + // Don't update the variable's location if we are just re-spilling it again. + + if (!reSpill) + { + varDsc->SetRegNum(regNum); + +#ifdef USING_VARIABLE_LIVE_RANGE + // We want "VariableLiveRange" inclusive on the beginning and exclusive on the ending. + // For that we shouldn't report an update of the variable location if is becoming dead + // on the same native offset. + if (!isLastUse) + { + // Report the home change for this variable + varLiveKeeper->siUpdateVariableLiveRange(varDsc, varNum); + } +#endif // USING_VARIABLE_LIVE_RANGE + + if (!varDsc->lvLiveInOutOfHndlr) + { +#ifdef DEBUG + if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) + { + JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", varNum); + } +#endif // DEBUG + VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); + } + +#ifdef DEBUG + if (compiler->verbose) + { + printf("\t\t\t\t\t\t\tV%02u in reg ", varNum); + varDsc->PrintVarReg(); + printf(" is becoming live "); + compiler->printTreeID(lclNode); + printf("\n"); + } +#endif // DEBUG + + regSet.AddMaskVars(genGetRegMask(varDsc)); + } + + gcInfo.gcMarkRegPtrVal(regNum, type); +} + //------------------------------------------------------------------------ // genUnspillRegIfNeeded: Reload the value into a register, if needed // @@ -968,8 +1048,9 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) // Reset spilled flag, since we are going to load a local variable from its home location. unspillTree->gtFlags &= ~GTF_SPILLED; - GenTreeLclVarCommon* lcl = unspillTree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; + GenTreeLclVar* lcl = unspillTree->AsLclVar(); + LclVarDsc* varDsc = compiler->lvaGetDesc(lcl->GetLclNum()); + var_types spillType = unspillTree->TypeGet(); // TODO-Cleanup: The following code could probably be further merged and cleaned up. #ifdef TARGET_XARCH @@ -985,106 +1066,33 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) // In the normalizeOnLoad case ins_Load will return an appropriate sign- or zero- // extending load. - var_types treeType = unspillTree->TypeGet(); - if (treeType != genActualType(varDsc->lvType) && !varTypeIsGC(treeType) && !varDsc->lvNormalizeOnLoad()) + if (spillType != genActualType(varDsc->lvType) && !varTypeIsGC(spillType) && !varDsc->lvNormalizeOnLoad()) { assert(!varTypeIsGC(varDsc)); - var_types spillType = genActualType(varDsc->lvType); - unspillTree->gtType = spillType; - inst_RV_TT(ins_Load(spillType, compiler->isSIMDTypeLocalAligned(lcl->GetLclNum())), dstReg, - unspillTree); - unspillTree->gtType = treeType; - } - else - { - inst_RV_TT(ins_Load(treeType, compiler->isSIMDTypeLocalAligned(lcl->GetLclNum())), dstReg, unspillTree); + spillType = genActualType(varDsc->lvType); } #elif defined(TARGET_ARM64) var_types targetType = unspillTree->gtType; - if (targetType != genActualType(varDsc->lvType) && !varTypeIsGC(targetType) && !varDsc->lvNormalizeOnLoad()) + if (spillType != genActualType(varDsc->lvType) && !varTypeIsGC(spillType) && !varDsc->lvNormalizeOnLoad()) { assert(!varTypeIsGC(varDsc)); - targetType = genActualType(varDsc->lvType); + spillType = genActualType(varDsc->lvType); } - instruction ins = ins_Load(targetType, compiler->isSIMDTypeLocalAligned(lcl->GetLclNum())); - emitAttr attr = emitActualTypeSize(targetType); - emitter* emit = GetEmitter(); - - // Load local variable from its home location. - inst_RV_TT(ins, dstReg, unspillTree, 0, attr); #elif defined(TARGET_ARM) - var_types targetType = unspillTree->gtType; - instruction ins = ins_Load(targetType, compiler->isSIMDTypeLocalAligned(lcl->GetLclNum())); - emitAttr attr = emitTypeSize(targetType); - - // Load local variable from its home location. - inst_RV_TT(ins, dstReg, unspillTree, 0, attr); +// No normalizing for ARM #else NYI("Unspilling not implemented for this target architecture."); #endif - - // TODO-Review: We would like to call: - // genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree)); - // instead of the following code, but this ends up hitting this assert: - // assert((regSet.GetMaskVars() & regMask) == 0); - // due to issues with LSRA resolution moves. - // So, just force it for now. This probably indicates a condition that creates a GC hole! - // - // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove, - // because the variable is not really going live or dead, but that method is somewhat poorly - // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo. - // TODO-Cleanup: This code exists in other CodeGen*.cpp files, and should be moved to CodeGenCommon.cpp. - - // Don't update the variable's location if we are just re-spilling it again. - - if ((unspillTree->gtFlags & GTF_SPILL) == 0) - { - genUpdateVarReg(varDsc, tree); - -#ifdef USING_VARIABLE_LIVE_RANGE - // We want "VariableLiveRange" inclusive on the beginbing and exclusive on the ending. - // For that we shouldn't report an update of the variable location if is becoming dead - // on the same native offset. - if ((unspillTree->gtFlags & GTF_VAR_DEATH) == 0) - { - // Report the home change for this variable - varLiveKeeper->siUpdateVariableLiveRange(varDsc, lcl->GetLclNum()); - } -#endif // USING_VARIABLE_LIVE_RANGE - - if (!varDsc->lvLiveInOutOfHndlr) - { -#ifdef DEBUG - if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", lcl->GetLclNum()); - } -#endif // DEBUG - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\t\t\t\t\t\t\tV%02u in reg ", lcl->GetLclNum()); - varDsc->PrintVarReg(); - printf(" is becoming live "); - compiler->printTreeID(unspillTree); - printf("\n"); - } -#endif // DEBUG - - regSet.AddMaskVars(genGetRegMask(varDsc)); - } - - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); + bool reSpill = ((unspillTree->gtFlags & GTF_SPILL) != 0); + bool isLastUse = lcl->IsLastUse(0); + genUnspillLocal(lcl->GetLclNum(), spillType, lcl, dstReg, reSpill, isLastUse); } else if (unspillTree->IsMultiRegCall()) { - GenTreeCall* call = unspillTree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - GenTreeCopyOrReload* reloadTree = nullptr; + GenTreeCall* call = unspillTree->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + const unsigned regCount = retTypeDesc->GetReturnRegCount(); + GenTreeCopyOrReload* reloadTree = nullptr; if (tree->OperGet() == GT_RELOAD) { reloadTree = tree->AsCopyOrReload(); @@ -1447,7 +1455,7 @@ void CodeGen::genConsumeRegs(GenTree* tree) #ifdef FEATURE_SIMD // (In)Equality operation that produces bool result, when compared // against Vector zero, marks its Vector Zero operand as contained. - assert(tree->OperIsLeaf() || tree->IsIntegralConstVector(0)); + assert(tree->OperIsLeaf() || tree->IsSIMDZero()); #else assert(tree->OperIsLeaf()); #endif @@ -1849,6 +1857,41 @@ void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber genSetBlockSize(blkNode, sizeReg); } +//------------------------------------------------------------------------- +// genSpillLocal: Generate the actual spill of a local var. +// +// Arguments: +// varNum - The variable number of the local to be spilled. +// It may be a local field. +// type - The type of the local. +// lclNode - The node being spilled. Note that for a multi-reg local, +// the gtLclNum will be that of the parent struct. +// regNum - The register that 'varNum' is currently in. +// +// Return Value: +// None. +// +void CodeGen::genSpillLocal(unsigned varNum, var_types type, GenTreeLclVar* lclNode, regNumber regNum) +{ + LclVarDsc* varDsc = compiler->lvaGetDesc(varNum); + assert(!varDsc->lvNormalizeOnStore() || (type == genActualType(varDsc->TypeGet()))); + + // We have a register candidate local that is marked with GTF_SPILL. + // This flag generally means that we need to spill this local. + // The exception is the case of a use of an EH var use that is being "spilled" + // to the stack, indicated by GTF_SPILL (note that all EH lclVar defs are always + // spilled, i.e. write-thru). + // An EH var use is always valid on the stack (so we don't need to actually spill it), + // but the GTF_SPILL flag records the fact that the register value is going dead. + if (((lclNode->gtFlags & GTF_VAR_DEF) != 0) || !varDsc->lvLiveInOutOfHndlr) + { + // Store local variable to its home location. + // Ensure that lclVar stores are typed correctly. + GetEmitter()->emitIns_S_R(ins_Store(type, compiler->isSIMDTypeLocalAligned(varNum)), emitTypeSize(type), regNum, + varNum, 0); + } +} + //------------------------------------------------------------------------- // genProduceReg: do liveness update for register produced by the current // node in codegen after code has been emitted for it. @@ -1877,24 +1920,8 @@ void CodeGen::genProduceReg(GenTree* tree) if (genIsRegCandidateLocal(tree)) { - unsigned varNum = tree->AsLclVarCommon()->GetLclNum(); - LclVarDsc* varDsc = compiler->lvaGetDesc(varNum); - assert(!varDsc->lvNormalizeOnStore() || (tree->TypeGet() == genActualType(varDsc->TypeGet()))); - - // If we reach here, we have a register candidate local that is marked with GTF_SPILL. - // This flag generally means that we need to spill this local. - // The exception is the case of a use of an EH var use that is being "spilled" - // to the stack, indicated by GTF_SPILL (note that all EH lclVar defs are always - // spilled, i.e. write-thru). - // An EH var use is always valid on the stack (so we don't need to actually spill it), - // but the GTF_SPILL flag records the fact that the register value is going dead. - if (((tree->gtFlags & GTF_VAR_DEF) != 0) || !varDsc->lvLiveInOutOfHndlr) - { - // Store local variable to its home location. - // Ensure that lclVar stores are typed correctly. - inst_TT_RV(ins_Store(tree->gtType, compiler->isSIMDTypeLocalAligned(varNum)), - emitTypeSize(tree->TypeGet()), tree, tree->GetRegNum()); - } + unsigned varNum = tree->AsLclVarCommon()->GetLclNum(); + genSpillLocal(varNum, tree->TypeGet(), tree->AsLclVar(), tree->GetRegNum()); } else { @@ -1904,9 +1931,9 @@ void CodeGen::genProduceReg(GenTree* tree) // know which of its result regs needs to be spilled. if (tree->IsMultiRegCall()) { - GenTreeCall* call = tree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + GenTreeCall* call = tree->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + const unsigned regCount = retTypeDesc->GetReturnRegCount(); for (unsigned i = 0; i < regCount; ++i) { @@ -1983,13 +2010,13 @@ void CodeGen::genProduceReg(GenTree* tree) // the register as live, with a GC pointer, if the variable is dead. if (!genIsRegCandidateLocal(tree) || ((tree->gtFlags & GTF_VAR_DEATH) == 0)) { - // Multi-reg call node will produce more than one register result. - // Mark all the regs produced by call node. + // Multi-reg nodes will produce more than one register result. + // Mark all the regs produced by the node. if (tree->IsMultiRegCall()) { - GenTreeCall* call = tree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + const GenTreeCall* call = tree->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + const unsigned regCount = retTypeDesc->GetReturnRegCount(); for (unsigned i = 0; i < regCount; ++i) { @@ -2006,10 +2033,10 @@ void CodeGen::genProduceReg(GenTree* tree) // A multi-reg GT_COPY node produces those regs to which // copy has taken place. - GenTreeCopyOrReload* copy = tree->AsCopyOrReload(); - GenTreeCall* call = copy->gtGetOp1()->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + const GenTreeCopyOrReload* copy = tree->AsCopyOrReload(); + const GenTreeCall* call = copy->gtGetOp1()->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + const unsigned regCount = retTypeDesc->GetReturnRegCount(); for (unsigned i = 0; i < regCount; ++i) { diff --git a/src/coreclr/src/jit/codegenxarch.cpp b/src/coreclr/src/jit/codegenxarch.cpp index 2070291a20808..4d8d2fbf9e217 100644 --- a/src/coreclr/src/jit/codegenxarch.cpp +++ b/src/coreclr/src/jit/codegenxarch.cpp @@ -54,14 +54,14 @@ void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFla // genSetGSSecurityCookie: Set the "GS" security cookie in the prolog. // // Arguments: -// initReg - register to use as a scratch register -// pInitRegZeroed - OUT parameter. *pInitRegZeroed is set to 'false' if and only if -// this call sets 'initReg' to a non-zero value. +// initReg - register to use as a scratch register +// pInitRegModified - OUT parameter. *pInitRegModified is set to 'true' if and only if +// this call sets 'initReg' to a non-zero value. // // Return Value: // None // -void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -85,7 +85,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) // initReg = #GlobalSecurityCookieVal64; [frame.GSSecurityCookie] = initReg genSetRegToIcon(initReg, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL); GetEmitter()->emitIns_S_R(INS_mov, EA_PTRSIZE, initReg, compiler->lvaGSSecurityCookie, 0); - *pInitRegZeroed = false; + *pInitRegModified = true; } else #endif @@ -106,7 +106,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) GetEmitter()->emitIns_S_R(INS_mov, EA_PTRSIZE, REG_EAX, compiler->lvaGSSecurityCookie, 0); if (initReg == REG_EAX) { - *pInitRegZeroed = false; + *pInitRegModified = true; } } } @@ -137,14 +137,14 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) ReturnTypeDesc retTypeDesc; if (varTypeIsLong(compiler->info.compRetNativeType)) { - retTypeDesc.InitializeLongReturnType(compiler); + retTypeDesc.InitializeLongReturnType(); } else // we must have a struct return type { retTypeDesc.InitializeStructReturnType(compiler, compiler->info.compMethodInfo->args.retTypeClass); } - unsigned regCount = retTypeDesc.GetReturnRegCount(); + const unsigned regCount = retTypeDesc.GetReturnRegCount(); // Only x86 and x64 Unix ABI allows multi-reg return and // number of result regs should be equal to MAX_RET_REG_COUNT. @@ -1124,214 +1124,55 @@ void CodeGen::genCodeForMul(GenTreeOp* treeNode) genProduceReg(treeNode); } +#ifdef FEATURE_SIMD //------------------------------------------------------------------------ -// isStructReturn: Returns whether the 'treeNode' is returning a struct. +// genSIMDSplitReturn: Generates code for returning a fixed-size SIMD type that lives +// in a single register, but is returned in multiple registers. // // Arguments: -// treeNode - The tree node to evaluate whether is a struct return. -// -// Return Value: -// For AMD64 *nix: returns true if the 'treeNode" is a GT_RETURN node, of type struct. -// Otherwise returns false. -// For other platforms always returns false. +// src - The source of the return +// retTypeDesc - The return type descriptor. // -bool CodeGen::isStructReturn(GenTree* treeNode) +void CodeGen::genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc) { - // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN. - // For the GT_RET_FILT, the return is always - // a bool or a void, for the end of a finally block. - noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - if (treeNode->OperGet() != GT_RETURN) - { - return false; - } - -#ifdef UNIX_AMD64_ABI - return varTypeIsStruct(treeNode); -#else // !UNIX_AMD64_ABI - assert(!varTypeIsStruct(treeNode)); - return false; -#endif // UNIX_AMD64_ABI -} + assert(varTypeIsSIMD(src)); + assert(src->isUsedFromReg()); -//------------------------------------------------------------------------ -// genStructReturn: Generates code for returning a struct. -// -// Arguments: -// treeNode - The GT_RETURN tree node. -// -// Return Value: -// None -// -// Assumption: -// op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL -void CodeGen::genStructReturn(GenTree* treeNode) -{ - assert(treeNode->OperGet() == GT_RETURN); - GenTree* op1 = treeNode->gtGetOp1(); + // This is a case of operand is in a single reg and needs to be + // returned in multiple ABI return registers. + regNumber opReg = src->GetRegNum(); + regNumber reg0 = retTypeDesc->GetABIReturnReg(0); + regNumber reg1 = retTypeDesc->GetABIReturnReg(1); -#ifdef UNIX_AMD64_ABI - if (op1->OperGet() == GT_LCL_VAR) + if (opReg != reg0 && opReg != reg1) { - GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon(); - LclVarDsc* varDsc = &(compiler->lvaTable[lclVar->GetLclNum()]); - assert(varDsc->lvIsMultiRegRet); - - ReturnTypeDesc retTypeDesc; - retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); - unsigned regCount = retTypeDesc.GetReturnRegCount(); - assert(regCount == MAX_RET_REG_COUNT); - - if (varTypeIsEnregisterable(op1)) - { - // Right now the only enregisterable structs supported are SIMD vector types. - assert(varTypeIsSIMD(op1)); - assert(op1->isUsedFromReg()); - - // This is a case of operand is in a single reg and needs to be - // returned in multiple ABI return registers. - regNumber opReg = genConsumeReg(op1); - regNumber reg0 = retTypeDesc.GetABIReturnReg(0); - regNumber reg1 = retTypeDesc.GetABIReturnReg(1); - - if (opReg != reg0 && opReg != reg1) - { - // Operand reg is different from return regs. - // Copy opReg to reg0 and let it to be handled by one of the - // two cases below. - inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); - opReg = reg0; - } - - if (opReg == reg0) - { - assert(opReg != reg1); - - // reg0 - already has required 8-byte in bit position [63:0]. - // reg1 = opReg. - // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. - inst_RV_RV(ins_Copy(TYP_DOUBLE), reg1, opReg, TYP_DOUBLE); - } - else - { - assert(opReg == reg1); + // Operand reg is different from return regs. + // Copy opReg to reg0 and let it to be handled by one of the + // two cases below. + inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); + opReg = reg0; + } - // reg0 = opReg. - // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. - inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); - } - inst_RV_RV_IV(INS_shufpd, EA_16BYTE, reg1, reg1, 0x01); - } - else - { - assert(op1->isUsedFromMemory()); + if (opReg == reg0) + { + assert(opReg != reg1); - // Copy var on stack into ABI return registers - int offset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc.GetReturnRegType(i); - regNumber reg = retTypeDesc.GetABIReturnReg(i); - GetEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), reg, lclVar->GetLclNum(), offset); - offset += genTypeSize(type); - } - } + // reg0 - already has required 8-byte in bit position [63:0]. + // reg1 = opReg. + // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. + inst_RV_RV(ins_Copy(TYP_DOUBLE), reg1, opReg, TYP_DOUBLE); } else { - assert(op1->IsMultiRegCall() || op1->IsCopyOrReloadOfMultiRegCall()); - - genConsumeRegs(op1); - - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - assert(regCount == MAX_RET_REG_COUNT); - - // Handle circular dependency between call allocated regs and ABI return regs. - // - // It is possible under LSRA stress that originally allocated regs of call node, - // say rax and rdx, are spilled and reloaded to rdx and rax respectively. But - // GT_RETURN needs to move values as follows: rdx->rax, rax->rdx. Similar kind - // kind of circular dependency could arise between xmm0 and xmm1 return regs. - // Codegen is expected to handle such circular dependency. - // - var_types regType0 = retTypeDesc->GetReturnRegType(0); - regNumber returnReg0 = retTypeDesc->GetABIReturnReg(0); - regNumber allocatedReg0 = call->GetRegNumByIdx(0); - - var_types regType1 = retTypeDesc->GetReturnRegType(1); - regNumber returnReg1 = retTypeDesc->GetABIReturnReg(1); - regNumber allocatedReg1 = call->GetRegNumByIdx(1); - - if (op1->IsCopyOrReload()) - { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0); - if (reloadReg != REG_NA) - { - allocatedReg0 = reloadReg; - } - - reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1); - if (reloadReg != REG_NA) - { - allocatedReg1 = reloadReg; - } - } + assert(opReg == reg1); - if (allocatedReg0 == returnReg1 && allocatedReg1 == returnReg0) - { - // Circular dependency - swap allocatedReg0 and allocatedReg1 - if (varTypeIsFloating(regType0)) - { - assert(varTypeIsFloating(regType1)); - - // The fastest way to swap two XMM regs is using PXOR - inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE); - inst_RV_RV(INS_pxor, allocatedReg1, allocatedReg0, TYP_DOUBLE); - inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE); - } - else - { - assert(varTypeIsIntegral(regType0)); - assert(varTypeIsIntegral(regType1)); - inst_RV_RV(INS_xchg, allocatedReg1, allocatedReg0, TYP_I_IMPL); - } - } - else if (allocatedReg1 == returnReg0) - { - // Change the order of moves to correctly handle dependency. - if (allocatedReg1 != returnReg1) - { - inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1); - } - - if (allocatedReg0 != returnReg0) - { - inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0); - } - } - else - { - // No circular dependency case. - if (allocatedReg0 != returnReg0) - { - inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0); - } - - if (allocatedReg1 != returnReg1) - { - inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1); - } - } + // reg0 = opReg. + // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. + inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); } -#else - unreached(); -#endif + inst_RV_RV_IV(INS_shufpd, EA_16BYTE, reg1, reg1, 0x01); } +#endif // FEATURE_SIMD #if defined(TARGET_X86) @@ -2009,7 +1850,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) } //---------------------------------------------------------------------------------- -// genMultiRegCallStoreToLocal: store multi-reg return value of a call node to a local +// genMultiRegStoreToLocal: store multi-reg return value of a call node to a local // // Arguments: // treeNode - Gentree of GT_STORE_LCL_VAR @@ -2017,45 +1858,52 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) // Return Value: // None // -// Assumption: -// The child of store is a multi-reg call node. -// genProduceReg() on treeNode is made by caller of this routine. +// Assumptions: +// The child of store is a multi-reg node. // -void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode) +void CodeGen::genMultiRegStoreToLocal(GenTree* treeNode) { assert(treeNode->OperGet() == GT_STORE_LCL_VAR); + assert(varTypeIsStruct(treeNode) || varTypeIsMultiReg(treeNode)); + GenTree* op1 = treeNode->gtGetOp1(); + GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + assert(op1->IsMultiRegNode()); + unsigned regCount = actualOp1->GetMultiRegCount(); -#ifdef UNIX_AMD64_ABI - // Structs of size >=9 and <=16 are returned in two return registers on x64 Unix. - assert(varTypeIsStruct(treeNode)); - - // Assumption: current x64 Unix implementation requires that a multi-reg struct + // Assumption: The current implementation requires that a multi-reg // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from // being struct promoted. - unsigned lclNum = treeNode->AsLclVarCommon()->GetLclNum(); - LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - noway_assert(varDsc->lvIsMultiRegRet); - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - assert(call->HasMultiRegRetVal()); + unsigned lclNum = treeNode->AsLclVarCommon()->GetLclNum(); + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); + if (op1->OperIs(GT_CALL)) + { + assert(regCount == MAX_RET_REG_COUNT); + noway_assert(varDsc->lvIsMultiRegRet); + } genConsumeRegs(op1); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - assert(retTypeDesc->GetReturnRegCount() == MAX_RET_REG_COUNT); - unsigned regCount = retTypeDesc->GetReturnRegCount(); +#ifdef UNIX_AMD64_ABI + // Structs of size >=9 and <=16 are returned in two return registers on x64 Unix. - if (treeNode->GetRegNum() != REG_NA) + // Handle the case of a SIMD type returned in 2 registers. + if (varTypeIsSIMD(treeNode) && (treeNode->GetRegNum() != REG_NA)) { // Right now the only enregistrable structs supported are SIMD types. - assert(varTypeIsSIMD(treeNode)); + // They are only returned in 1 or 2 registers - the 1 register case is + // handled as a regular STORE_LCL_VAR. + // This case is always a call (AsCall() will assert if it is not). + GenTreeCall* call = actualOp1->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + assert(retTypeDesc->GetReturnRegCount() == MAX_RET_REG_COUNT); + + assert(regCount == 2); assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(0))); assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(1))); - // This is a case of two 8-bytes that comprise the operand is in - // two different xmm registers and needs to assembled into a single + // This is a case where the two 8-bytes that comprise the operand are in + // two different xmm registers and need to be assembled into a single // xmm register. regNumber targetReg = treeNode->GetRegNum(); regNumber reg0 = call->GetRegNumByIdx(0); @@ -2111,95 +1959,52 @@ void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode) } } else +#endif // UNIX_AMD64_ABI { - // Stack store + // This may be: + // - a call returning multiple registers + // - a HW intrinsic producing two registers to be stored into a TYP_STRUCT + // int offset = 0; for (unsigned i = 0; i < regCount; ++i) { - var_types type = retTypeDesc->GetReturnRegType(i); - regNumber reg = call->GetRegNumByIdx(i); - if (op1->IsCopyOrReload()) + var_types type = actualOp1->GetRegTypeByIndex(i); + regNumber reg = op1->GetRegByIndex(i); + if (reg == REG_NA) { - // GT_COPY/GT_RELOAD will have valid reg for those positions + // GT_COPY/GT_RELOAD will have valid reg only for those positions // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); - if (reloadReg != REG_NA) - { - reg = reloadReg; - } + assert(op1->IsCopyOrReload()); + reg = actualOp1->GetRegByIndex(i); } assert(reg != REG_NA); GetEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset); offset += genTypeSize(type); } - + // Update variable liveness. + genUpdateLife(treeNode); varDsc->SetRegNum(REG_STK); } -#elif defined(TARGET_X86) - // Longs are returned in two return registers on x86. - assert(varTypeIsLong(treeNode)); - - // Assumption: current x86 implementation requires that a multi-reg long - // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from - // being promoted. - unsigned lclNum = treeNode->AsLclVarCommon()->GetLclNum(); - LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - noway_assert(varDsc->lvIsMultiRegRet); - - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - assert(call->HasMultiRegRetVal()); - - genConsumeRegs(op1); - - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - assert(regCount == MAX_RET_REG_COUNT); - - // Stack store - int offset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc->GetReturnRegType(i); - regNumber reg = call->GetRegNumByIdx(i); - if (op1->IsCopyOrReload()) - { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); - if (reloadReg != REG_NA) - { - reg = reloadReg; - } - } - - assert(reg != REG_NA); - GetEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset); - offset += genTypeSize(type); - } - - varDsc->SetRegNum(REG_STK); -#else // !UNIX_AMD64_ABI && !TARGET_X86 - assert(!"Unreached"); -#endif // !UNIX_AMD64_ABI && !TARGET_X86 } //------------------------------------------------------------------------ // genAllocLclFrame: Probe the stack and allocate the local stack frame - subtract from SP. // // Arguments: -// frameSize - the size of the stack frame being allocated. -// initReg - register to use as a scratch register. -// pInitRegZeroed - OUT parameter. *pInitRegZeroed is set to 'false' if and only if -// this call sets 'initReg' to a non-zero value. -// maskArgRegsLiveIn - incoming argument registers that are currently live. +// frameSize - the size of the stack frame being allocated. +// initReg - register to use as a scratch register. +// pInitRegModified - OUT parameter. *pInitRegModified is set to 'true' if and only if +// this call sets 'initReg' to a non-zero value. +// maskArgRegsLiveIn - incoming argument registers that are currently live. // // Return value: // None // -void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn) +void CodeGen::genAllocLclFrame(unsigned frameSize, + regNumber initReg, + bool* pInitRegModified, + regMaskTP maskArgRegsLiveIn) { assert(compiler->compGeneratingProlog); @@ -2283,7 +2088,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni if (initReg == REG_DEFAULT_HELPER_CALL_TARGET) { - *pInitRegZeroed = false; + *pInitRegModified = true; } static_assert_no_msg((RBM_STACK_PROBE_HELPER_TRASH & RBM_STACK_PROBE_HELPER_ARG) == RBM_NONE); @@ -2293,7 +2098,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni if (initReg == REG_STACK_PROBE_HELPER_ARG) { - *pInitRegZeroed = false; + *pInitRegModified = true; } } @@ -4636,9 +4441,9 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) // var = call, where call returns a multi-reg return value // case is handled separately. - if (op1->gtSkipReloadOrCopy()->IsMultiRegCall()) + if (op1->gtSkipReloadOrCopy()->IsMultiRegNode()) { - genMultiRegCallStoreToLocal(tree); + genMultiRegStoreToLocal(tree); } else { @@ -4676,17 +4481,6 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) genStoreLclTypeSIMD12(tree); return; } - - // TODO-CQ: It would be better to simply contain the zero, rather than - // generating zero into a register. - if (varTypeIsSIMD(targetType) && (targetReg != REG_NA) && op1->IsCnsIntOrI()) - { - // This is only possible for a zero-init. - noway_assert(op1->IsIntegralConst(0)); - genSIMDZero(targetType, varDsc->lvBaseType, targetReg); - genProduceReg(tree); - return; - } #endif // FEATURE_SIMD genConsumeRegs(op1); @@ -4885,130 +4679,6 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) genProduceReg(tree); } -//------------------------------------------------------------------------ -// genRegCopy: Produce code for a GT_COPY node. -// -// Arguments: -// tree - the GT_COPY node -// -// Notes: -// This will copy the register(s) produced by this nodes source, to -// the register(s) allocated to this GT_COPY node. -// It has some special handling for these casess: -// - when the source and target registers are in different register files -// (note that this is *not* a conversion). -// - when the source is a lclVar whose home location is being moved to a new -// register (rather than just being copied for temporary use). -// -void CodeGen::genRegCopy(GenTree* treeNode) -{ - assert(treeNode->OperGet() == GT_COPY); - GenTree* op1 = treeNode->AsOp()->gtOp1; - - if (op1->IsMultiRegNode()) - { - genConsumeReg(op1); - - GenTreeCopyOrReload* copyTree = treeNode->AsCopyOrReload(); - unsigned regCount = treeNode->GetMultiRegCount(); - - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = op1->GetRegTypeByIndex(i); - regNumber fromReg = op1->GetRegByIndex(i); - regNumber toReg = copyTree->GetRegNumByIdx(i); - - // A Multi-reg GT_COPY node will have a valid reg only for those positions for which a corresponding - // result reg of the multi-reg node needs to be copied. - if (toReg != REG_NA) - { - assert(toReg != fromReg); - inst_RV_RV(ins_Copy(type), toReg, fromReg, type); - } - } - } - else - { - var_types targetType = treeNode->TypeGet(); - regNumber targetReg = treeNode->GetRegNum(); - assert(targetReg != REG_NA); - - // Check whether this node and the node from which we're copying the value have - // different register types. This can happen if (currently iff) we have a SIMD - // vector type that fits in an integer register, in which case it is passed as - // an argument, or returned from a call, in an integer register and must be - // copied if it's in an xmm register. - - bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1)); - bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode)); - if (srcFltReg != tgtFltReg) - { - instruction ins; - regNumber fpReg; - regNumber intReg; - if (tgtFltReg) - { - ins = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet()); - fpReg = targetReg; - intReg = op1->GetRegNum(); - } - else - { - ins = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet()); - intReg = targetReg; - fpReg = op1->GetRegNum(); - } - inst_RV_RV(ins, fpReg, intReg, targetType); - } - else - { - inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType); - } - - if (op1->IsLocal()) - { - // The lclVar will never be a def. - // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will - // appropriately set the gcInfo for the copied value. - // If not, there are two cases we need to handle: - // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable - // will remain live in its original register. - // genProduceReg() will appropriately set the gcInfo for the copied value, - // and genConsumeReg will reset it. - // - Otherwise, we need to update register info for the lclVar. - - GenTreeLclVarCommon* lcl = op1->AsLclVarCommon(); - assert((lcl->gtFlags & GTF_VAR_DEF) == 0); - - if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0) - { - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - - // If we didn't just spill it (in genConsumeReg, above), then update the register info - if (varDsc->GetRegNum() != REG_STK) - { - // The old location is dying - genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1)); - - gcInfo.gcMarkRegSetNpt(genRegMask(op1->GetRegNum())); - - genUpdateVarReg(varDsc, treeNode); - -#ifdef USING_VARIABLE_LIVE_RANGE - // Report the home change for this variable - varLiveKeeper->siUpdateVariableLiveRange(varDsc, lcl->GetLclNum()); -#endif // USING_VARIABLE_LIVE_RANGE - - // The new location is going live - genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode)); - } - } - } - } - - genProduceReg(treeNode); -} - //------------------------------------------------------------------------ // genCodeForStoreInd: Produce code for a GT_STOREIND node. // @@ -5501,9 +5171,9 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } // Determine return value size(s). - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - emitAttr retSize = EA_PTRSIZE; - emitAttr secondRetSize = EA_UNKNOWN; + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + emitAttr retSize = EA_PTRSIZE; + emitAttr secondRetSize = EA_UNKNOWN; if (call->HasMultiRegRetVal()) { @@ -5766,7 +5436,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (call->HasMultiRegRetVal()) { assert(retTypeDesc != nullptr); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + const unsigned regCount = retTypeDesc->GetReturnRegCount(); // If regs allocated to call node are different from ABI return // regs in which the call has returned its result, move the result @@ -7191,7 +6861,11 @@ void CodeGen::genSSE2BitwiseOp(GenTree* treeNode) if (*bitMask == nullptr) { assert(cnsAddr != nullptr); - *bitMask = GetEmitter()->emitAnyConst(cnsAddr, genTypeSize(targetType), emitDataAlignment::Preferred); + + UNATIVE_OFFSET cnsSize = genTypeSize(targetType); + UNATIVE_OFFSET cnsAlign = (compiler->compCodeOpt() != Compiler::SMALL_CODE) ? cnsSize : 1; + + *bitMask = GetEmitter()->emitAnyConst(cnsAddr, cnsSize, cnsAlign); } // We need an additional register for bitmask. @@ -8825,9 +8499,9 @@ void CodeGen::genAmd64EmitterUnitTests() // genProfilingEnterCallback: Generate the profiling function enter callback. // // Arguments: -// initReg - register to use as scratch register -// pInitRegZeroed - OUT parameter. *pInitRegZeroed set to 'false' if 'initReg' is -// not zero after this call. +// initReg - register to use as scratch register +// pInitRegModified - OUT parameter. *pInitRegModified set to 'true' if 'initReg' is +// not zero after this call. // // Return Value: // None @@ -8846,7 +8520,7 @@ void CodeGen::genAmd64EmitterUnitTests() // 4. All registers are preserved. // 5. The helper pops the FunctionIDOrClientID argument from the stack. // -void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -8991,14 +8665,14 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper) // genProfilingEnterCallback: Generate the profiling function enter callback. // // Arguments: -// initReg - register to use as scratch register -// pInitRegZeroed - OUT parameter. *pInitRegZeroed set to 'false' if 'initReg' is -// not zero after this call. +// initReg - register to use as scratch register +// pInitRegModified - OUT parameter. *pInitRegModified set to 'true' if 'initReg' is +// not zero after this call. // // Return Value: // None // -void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) +void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegModified) { assert(compiler->compGeneratingProlog); @@ -9135,7 +8809,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) // If initReg is one of RBM_CALLEE_TRASH, then it needs to be zero'ed before using. if ((RBM_CALLEE_TRASH & genRegMask(initReg)) != 0) { - *pInitRegZeroed = false; + *pInitRegModified = true; } #else // !defined(UNIX_AMD64_ABI) @@ -9184,7 +8858,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) // If initReg is one of RBM_CALLEE_TRASH, then it needs to be zero'ed before using. if ((RBM_CALLEE_TRASH & genRegMask(initReg)) != 0) { - *pInitRegZeroed = false; + *pInitRegModified = true; } #endif // !defined(UNIX_AMD64_ABI) diff --git a/src/coreclr/src/jit/compiler.cpp b/src/coreclr/src/jit/compiler.cpp index 4779a6fa90c48..0a9003f51268c 100644 --- a/src/coreclr/src/jit/compiler.cpp +++ b/src/coreclr/src/jit/compiler.cpp @@ -4690,6 +4690,8 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags DoPhase(this, PHASE_BUILD_SSA, &Compiler::fgSsaBuild); } + DoPhase(this, PHASE_ZERO_INITS, &Compiler::optRemoveRedundantZeroInits); + if (doEarlyProp) { // Propagate array length and rewrite getType() method call diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 8f9b8e7535a89..c6181d5e194a5 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -518,6 +518,10 @@ class LclVarDsc unsigned char lvSuppressedZeroInit : 1; // local needs zero init if we transform tail call to loop + unsigned char lvHasExplicitInit : 1; // The local is explicitly initialized and doesn't need zero initialization in + // the prolog. If the local has gc pointers, there are no gc-safe points + // between the prolog and the explicit initialization. + union { unsigned lvFieldLclStart; // The index of the local var representing the first field in the promoted struct // local. For implicit byref parameters, this gets hijacked between @@ -1738,6 +1742,10 @@ struct fgArgTabEntry #else unsigned int regSize = 1; #endif + + if (numRegs > MAX_ARG_REG_COUNT) + NO_WAY("Multireg argument exceeds the maximum length"); + for (unsigned int regIndex = 1; regIndex < numRegs; regIndex++) { argReg = (regNumber)(argReg + regSize); @@ -2617,6 +2625,16 @@ class Compiler var_types baseType, unsigned size); + GenTreeHWIntrinsic* gtNewSimdAsHWIntrinsicNode(var_types type, + NamedIntrinsic hwIntrinsicID, + var_types baseType, + unsigned size) + { + GenTreeHWIntrinsic* node = gtNewSimdHWIntrinsicNode(type, hwIntrinsicID, baseType, size); + node->gtFlags |= GTF_SIMDASHW_OP; + return node; + } + GenTreeHWIntrinsic* gtNewSimdAsHWIntrinsicNode( var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned size) { @@ -2653,7 +2671,6 @@ class Compiler NamedIntrinsic hwIntrinsicID); GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode( var_types type, GenTree* op1, GenTree* op2, GenTree* op3, NamedIntrinsic hwIntrinsicID); - GenTree* gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd); CORINFO_CLASS_HANDLE gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType); var_types getBaseTypeFromArgIfNeeded(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, @@ -2661,6 +2678,8 @@ class Compiler var_types baseType); #endif // FEATURE_HW_INTRINSICS + GenTree* gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd); + GenTreeLclFld* gtNewLclFldNode(unsigned lnum, var_types type, unsigned offset); GenTree* gtNewInlineCandidateReturnExpr(GenTree* inlineCandidate, var_types type); @@ -3496,19 +3515,21 @@ class Compiler assert(varDsc->lvSize() == 16); #endif // defined(TARGET_64BIT) - // We make local variable SIMD12 types 16 bytes instead of just 12. lvSize() - // already does this calculation. However, we also need to prevent mapping types if the var is a - // dependently promoted struct field, which must remain its exact size within its parent struct. - // However, we don't know this until late, so we may have already pretended the field is bigger - // before that. - if ((varDsc->lvSize() == 16) && !lvaIsFieldOfDependentlyPromotedStruct(varDsc)) + // We make local variable SIMD12 types 16 bytes instead of just 12. + // lvSize() will return 16 bytes for SIMD12, even for fields. + // However, we can't do that mapping if the var is a dependently promoted struct field. + // Such a field must remain its exact size within its parent struct unless it is a single + // field *and* it is the only field in a struct of 16 bytes. + if (varDsc->lvSize() != 16) { - return true; + return false; } - else + if (lvaIsFieldOfDependentlyPromotedStruct(varDsc)) { - return false; + LclVarDsc* parentVarDsc = lvaGetDesc(varDsc->lvParentLcl); + return (parentVarDsc->lvFieldCnt == 1) && (parentVarDsc->lvSize() == 16); } + return true; } #endif // defined(FEATURE_SIMD) @@ -3709,6 +3730,10 @@ class Compiler CorInfoIntrinsics intrinsicID, bool tailCall); NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method); + GenTree* impUnsupportedNamedIntrinsic(unsigned helper, + CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* sig, + bool mustExpand); #ifdef FEATURE_HW_INTRINSICS GenTree* impHWIntrinsic(NamedIntrinsic intrinsic, @@ -3716,10 +3741,6 @@ class Compiler CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, bool mustExpand); - GenTree* impUnsupportedHWIntrinsic(unsigned helper, - CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig, - bool mustExpand); GenTree* impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, @@ -3747,17 +3768,24 @@ class Compiler GenTree* impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig); + CORINFO_SIG_INFO* sig, + var_types baseType, + var_types retType, + unsigned simdSize); GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass, bool expectAddr = false); GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType); - GenTree* addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand, int immUpperBound); + GenTree* addRangeCheckIfNeeded( + NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand, int immLowerBound, int immUpperBound); #ifdef TARGET_XARCH GenTree* impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig); + CORINFO_SIG_INFO* sig, + var_types baseType, + var_types retType, + unsigned simdSize); GenTree* impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); GenTree* impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); GenTree* impAvxOrAvx2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); @@ -4629,8 +4657,11 @@ class Compiler unsigned fgSsaPassesCompleted; // Number of times fgSsaBuild has been run. + // Returns "true" if this is a special variable that is never zero initialized in the prolog. + inline bool fgVarIsNeverZeroInitializedInProlog(unsigned varNum); + // Returns "true" if the variable needs explicit zero initialization. - inline bool fgVarNeedsExplicitZeroInit(LclVarDsc* varDsc, bool bbInALoop, bool bbIsReturn); + inline bool fgVarNeedsExplicitZeroInit(unsigned varNum, bool bbInALoop, bool bbIsReturn); // The value numbers for this compilation. ValueNumStore* vnStore; @@ -5882,6 +5913,8 @@ class Compiler void optUnrollLoops(); // Unrolls loops (needs to have cost info) + void optRemoveRedundantZeroInits(); + protected: // This enumeration describes what is killed by a call. @@ -7957,9 +7990,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX static bool isRelOpSIMDIntrinsic(SIMDIntrinsicID intrinsicId) { - return (intrinsicId == SIMDIntrinsicEqual || intrinsicId == SIMDIntrinsicLessThan || - intrinsicId == SIMDIntrinsicLessThanOrEqual || intrinsicId == SIMDIntrinsicGreaterThan || - intrinsicId == SIMDIntrinsicGreaterThanOrEqual); + return (intrinsicId == SIMDIntrinsicEqual); } // Returns base type of a TYP_SIMD local. @@ -8063,22 +8094,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Create a GT_SIMD tree for a Get property of SIMD vector with a fixed index. GenTreeSIMD* impSIMDGetFixed(var_types simdType, var_types baseType, unsigned simdSize, int index); - // Creates a GT_SIMD tree for Select operation - GenTree* impSIMDSelect(CORINFO_CLASS_HANDLE typeHnd, - var_types baseType, - unsigned simdVectorSize, - GenTree* op1, - GenTree* op2, - GenTree* op3); - - // Creates a GT_SIMD tree for Min/Max operation - GenTree* impSIMDMinMax(SIMDIntrinsicID intrinsicId, - CORINFO_CLASS_HANDLE typeHnd, - var_types baseType, - unsigned simdVectorSize, - GenTree* op1, - GenTree* op2); - // Transforms operands and returns the SIMD intrinsic to be applied on // transformed operands to obtain given relop result. SIMDIntrinsicID impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, @@ -8088,9 +8103,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX GenTree** op1, GenTree** op2); - // Creates a GT_SIMD tree for Abs intrinsic. - GenTree* impSIMDAbs(CORINFO_CLASS_HANDLE typeHnd, var_types baseType, unsigned simdVectorSize, GenTree* op1); - #if defined(TARGET_XARCH) // Transforms operands and returns the SIMD intrinsic to be applied on @@ -8100,26 +8112,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX GenTree** op1, GenTree** op2); - // Transforms operands and returns the SIMD intrinsic to be applied on - // transformed operands to obtain > comparison result. - SIMDIntrinsicID impSIMDLongRelOpGreaterThan(CORINFO_CLASS_HANDLE typeHnd, - unsigned simdVectorSize, - GenTree** op1, - GenTree** op2); - - // Transforms operands and returns the SIMD intrinsic to be applied on - // transformed operands to obtain >= comparison result. - SIMDIntrinsicID impSIMDLongRelOpGreaterThanOrEqual(CORINFO_CLASS_HANDLE typeHnd, - unsigned simdVectorSize, - GenTree** op1, - GenTree** op2); - - // Transforms operands and returns the SIMD intrinsic to be applied on - // transformed operands to obtain >= comparison result in case of int32 - // and small int base type vectors. - SIMDIntrinsicID impSIMDIntegralRelOpGreaterThanOrEqual( - CORINFO_CLASS_HANDLE typeHnd, unsigned simdVectorSize, var_types baseType, GenTree** op1, GenTree** op2); - #endif // defined(TARGET_XARCH) void setLclRelatedToSIMDIntrinsic(GenTree* tree); diff --git a/src/coreclr/src/jit/compiler.hpp b/src/coreclr/src/jit/compiler.hpp index 993c287aea54b..f3e590a7303a4 100644 --- a/src/coreclr/src/jit/compiler.hpp +++ b/src/coreclr/src/jit/compiler.hpp @@ -4145,11 +4145,39 @@ inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename) #endif // MEASURE_CLRAPI_CALLS +//------------------------------------------------------------------------------ +// fgVarIsNeverZeroInitializedInProlog : Check whether the variable is never zero initialized in the prolog. +// +// Arguments: +// varNum - local variable number +// +// Returns: +// true if this is a special variable that is never zero initialized in the prolog; +// false otherwise +// + +bool Compiler::fgVarIsNeverZeroInitializedInProlog(unsigned varNum) +{ + LclVarDsc* varDsc = lvaGetDesc(varNum); + bool result = varDsc->lvIsParam || lvaIsOSRLocal(varNum) || (opts.IsOSR() && (varNum == lvaGSSecurityCookie)) || + (varNum == lvaInlinedPInvokeFrameVar) || (varNum == lvaStubArgumentVar) || (varNum == lvaRetAddrVar); + +#if FEATURE_FIXED_OUT_ARGS + result = result || (varNum == lvaPInvokeFrameRegSaveVar) || (varNum == lvaOutgoingArgSpaceVar); +#endif + +#if defined(FEATURE_EH_FUNCLETS) + result = result || (varNum == lvaPSPSym); +#endif + + return result; +} + //------------------------------------------------------------------------------ // fgVarNeedsExplicitZeroInit : Check whether the variable needs an explicit zero initialization. // // Arguments: -// varDsc - local var description +// varNum - local var number // bbInALoop - true if the basic block may be in a loop // bbIsReturn - true if the basic block always returns // @@ -4165,13 +4193,20 @@ inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename) // - compInitMem is set and the variable has a long lifetime or has gc fields. // In these cases we will insert zero-initialization in the prolog if necessary. -bool Compiler::fgVarNeedsExplicitZeroInit(LclVarDsc* varDsc, bool bbInALoop, bool bbIsReturn) +bool Compiler::fgVarNeedsExplicitZeroInit(unsigned varNum, bool bbInALoop, bool bbIsReturn) { + LclVarDsc* varDsc = lvaGetDesc(varNum); + if (bbInALoop && !bbIsReturn) { return true; } + if (fgVarIsNeverZeroInitializedInProlog(varNum)) + { + return true; + } + if (varTypeIsGC(varDsc->lvType)) { return false; diff --git a/src/coreclr/src/jit/compmemkind.h b/src/coreclr/src/jit/compmemkind.h index 1b409544ba23b..586e5f3ac3ca7 100644 --- a/src/coreclr/src/jit/compmemkind.h +++ b/src/coreclr/src/jit/compmemkind.h @@ -58,6 +58,7 @@ CompMemKindMacro(VariableLiveRanges) CompMemKindMacro(ClassLayout) CompMemKindMacro(TailMergeThrows) CompMemKindMacro(EarlyProp) +CompMemKindMacro(ZeroInit) //clang-format on #undef CompMemKindMacro diff --git a/src/coreclr/src/jit/compphases.h b/src/coreclr/src/jit/compphases.h index 0cafdc1793e3c..ccda79c4cfe79 100644 --- a/src/coreclr/src/jit/compphases.h +++ b/src/coreclr/src/jit/compphases.h @@ -55,6 +55,7 @@ CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", CompPhaseNameMacro(PHASE_MERGE_THROWS, "Merge throw blocks", "MRGTHROW", false, -1, false) CompPhaseNameMacro(PHASE_OPTIMIZE_LAYOUT, "Optimize layout", "LAYOUT", false, -1, false) CompPhaseNameMacro(PHASE_COMPUTE_REACHABILITY, "Compute blocks reachability", "BL_REACH", false, -1, false) +CompPhaseNameMacro(PHASE_ZERO_INITS, "Redundant zero Inits", "ZERO-INIT", false, -1, false) CompPhaseNameMacro(PHASE_OPTIMIZE_LOOPS, "Optimize loops", "LOOP-OPT", false, -1, false) CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1, false) CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1, false) diff --git a/src/coreclr/src/jit/decomposelongs.cpp b/src/coreclr/src/jit/decomposelongs.cpp index 77112049271ea..855d60813ca02 100644 --- a/src/coreclr/src/jit/decomposelongs.cpp +++ b/src/coreclr/src/jit/decomposelongs.cpp @@ -1362,7 +1362,7 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use) GenTreeCall::Use* argList = m_compiler->gtNewCallArgs(loOp1, hiOp1, shiftByOp); - GenTree* call = m_compiler->gtNewHelperCallNode(helper, TYP_LONG, argList); + GenTreeCall* call = m_compiler->gtNewHelperCallNode(helper, TYP_LONG, argList); call->gtFlags |= shift->gtFlags & GTF_ALL_EFFECT; if (shift->IsUnusedValue()) @@ -1370,11 +1370,7 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use) call->SetUnusedValue(); } - GenTreeCall* callNode = call->AsCall(); - ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); - retTypeDesc->InitializeLongReturnType(m_compiler); - - call = m_compiler->fgMorphArgs(callNode); + call = m_compiler->fgMorphArgs(call); Range().InsertAfter(shift, LIR::SeqTree(m_compiler, call)); Range().Remove(shift); diff --git a/src/coreclr/src/jit/emit.cpp b/src/coreclr/src/jit/emit.cpp index f0fd875006c97..2613cd453e61a 100644 --- a/src/coreclr/src/jit/emit.cpp +++ b/src/coreclr/src/jit/emit.cpp @@ -4622,10 +4622,18 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, } #endif - if (emitConsDsc.align16) + // This restricts the emitConsDsc.alignment to: 1, 2, 4, 8, 16, or 32 bytes + // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem + assert(isPow2(emitConsDsc.alignment) && (emitConsDsc.alignment <= 32)); + + if (emitConsDsc.alignment == 16) { allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN); } + else if (emitConsDsc.alignment == 32) + { + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN); + } #ifdef TARGET_ARM64 // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does. @@ -4637,7 +4645,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, } UNATIVE_OFFSET roDataAlignmentDelta = 0; - if (emitConsDsc.dsdOffs) + if (emitConsDsc.dsdOffs && (emitConsDsc.alignment == TARGET_POINTER_SIZE)) { UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default. roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize; @@ -5320,49 +5328,54 @@ UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum) * block. */ -UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, bool align) +UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, UNATIVE_OFFSET alignment) { unsigned secOffs; dataSection* secDesc; assert(emitDataSecCur == nullptr); - /* The size better not be some kind of an odd thing */ + // The size must not be zero and must be a multiple of 4 bytes + // Additionally, 4 bytes is the minimum alignment that will + // actually be used. That is, if the user requests an alignment + // of 1 or 2, they will get something that is at least 4-byte + // aligned. We allow the others since 4 is at least 1/2 and its + // simpler to allow it than to check and block. + assert((size != 0) && ((size % 4) == 0)); - assert(size && size % sizeof(int) == 0); + // This restricts the alignment to: 1, 2, 4, 8, 16, or 32 bytes + // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem - /* Get hold of the current offset */ + const size_t MaxAlignment = 32; + assert(isPow2(alignment) && (alignment <= MaxAlignment)); + /* Get hold of the current offset */ secOffs = emitConsDsc.dsdOffs; - if (align) + if (alignment > 4) { - // Data can have any size but since alignment is deduced from the size there's no - // way to have a larger data size (e.g. 128) and request 4/8/16 byte alignment. - // 32 bytes (and more) alignment requires VM support (see ICorJitInfo::allocMem). - assert(size <= 16); + // As per the above comment, the minimum alignment is actually 4 + // bytes so we don't need to make any adjustments if the requested + // alignment is 1, 2, or 4. + // + // The maximum requested alignment is tracked and the memory allocator + // will end up ensuring offset 0 is at an address matching that + // alignment. So if the requested alignment is greater than 4, we need + // to pad the space out so the offset is a multiple of the requested. - if (size == 16) - { - emitConsDsc.align16 = true; - } + uint8_t zero[MaxAlignment] = {}; - while ((secOffs % size) != 0) - { - /* Need to skip 4 bytes to honor alignment */ - /* Must allocate a dummy 4 byte integer */ - int zero = 0; - emitDataGenBeg(4, false); - emitDataGenData(0, &zero, 4); - emitDataGenEnd(); + UNATIVE_OFFSET zeroSize = alignment - (secOffs % alignment); + UNATIVE_OFFSET zeroAlign = 4; - /* Get the new secOffs */ - secOffs = emitConsDsc.dsdOffs; - } + emitAnyConst(&zero, zeroSize, zeroAlign); + secOffs = emitConsDsc.dsdOffs; } - /* Advance the current offset */ + assert((secOffs % alignment) == 0); + emitConsDsc.alignment = max(emitConsDsc.alignment, alignment); + /* Advance the current offset */ emitConsDsc.dsdOffs += size; /* Allocate a data section descriptor and add it to the list */ @@ -5450,7 +5463,7 @@ UNATIVE_OFFSET emitter::emitBBTableDataGenBeg(unsigned numEntries, bool relative * Emit the given block of bits into the current data section. */ -void emitter::emitDataGenData(unsigned offs, const void* data, size_t size) +void emitter::emitDataGenData(unsigned offs, const void* data, UNATIVE_OFFSET size) { assert(emitDataSecCur && (emitDataSecCur->dsSize >= offs + size)); @@ -5497,19 +5510,13 @@ void emitter::emitDataGenEnd() * Parameters: * cnsAddr - memory location containing constant value * cnsSize - size of constant in bytes - * dblAlign - whether to double align the data section constant + * cnsAlign - alignment of constant in bytes * * Returns constant number as offset into data section. */ -UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign) +UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, UNATIVE_OFFSET cnsSize, UNATIVE_OFFSET cnsAlign) { - // When generating SMALL_CODE, we don't bother with dblAlign - if (dblAlign && (emitComp->compCodeOpt() == Compiler::SMALL_CODE)) - { - dblAlign = false; - } - - UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, dblAlign); + UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, cnsAlign); emitDataGenData(0, cnsAddr, cnsSize); emitDataGenEnd(); @@ -5521,33 +5528,18 @@ UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, boo // // Arguments: // cnsAddr - pointer to the data to be placed in the data section -// cnsSize - size of the data -// alignment - indicates how to align the constant +// cnsSize - size of the data in bytes +// cnsAlign - alignment of the data in bytes // // Return Value: // A field handle representing the data offset to access the constant. // -CORINFO_FIELD_HANDLE emitter::emitAnyConst(const void* cnsAddr, unsigned cnsSize, emitDataAlignment alignment) +CORINFO_FIELD_HANDLE emitter::emitAnyConst(const void* cnsAddr, UNATIVE_OFFSET cnsSize, UNATIVE_OFFSET cnsAlign) { - bool align; - - switch (alignment) - { - case emitDataAlignment::None: - align = false; - break; - case emitDataAlignment::Preferred: - align = (emitComp->compCodeOpt() != Compiler::SMALL_CODE); - break; - case emitDataAlignment::Required: - default: - align = true; - break; - } - - UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, align); + UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, cnsAlign); emitDataGenData(0, cnsAddr, cnsSize); emitDataGenEnd(); + return emitComp->eeFindJitDataOffs(cnum); } @@ -5571,26 +5563,35 @@ CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(double constValue, emitAttr attr void* cnsAddr; float f; - bool dblAlign; if (attr == EA_4BYTE) { - f = forceCastToFloat(constValue); - cnsAddr = &f; - dblAlign = false; + f = forceCastToFloat(constValue); + cnsAddr = &f; } else { - cnsAddr = &constValue; - dblAlign = true; + cnsAddr = &constValue; } // Access to inline data is 'abstracted' by a special type of static member // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference // to constant data, not a real static field. - UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8; - UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign); + UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8; + UNATIVE_OFFSET cnsAlign = cnsSize; + +#ifdef TARGET_XARCH + if (emitComp->compCodeOpt() == Compiler::SMALL_CODE) + { + // Some platforms don't require doubles to be aligned and so + // we can use a smaller alignment to help with smaller code + + cnsAlign = 1; + } +#endif // TARGET_XARCH + + UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, cnsAlign); return emitComp->eeFindJitDataOffs(cnum); } diff --git a/src/coreclr/src/jit/emit.h b/src/coreclr/src/jit/emit.h index 6574fef7af862..cd1616b37eb8c 100644 --- a/src/coreclr/src/jit/emit.h +++ b/src/coreclr/src/jit/emit.h @@ -200,13 +200,6 @@ class emitLocation unsigned codePos; // the code position within the IG (see emitCurOffset()) }; -enum class emitDataAlignment -{ - None, - Preferred, - Required -}; - /************************************************************************/ /* The following describes an instruction group */ /************************************************************************/ @@ -1685,7 +1678,7 @@ class emitter void emitSetMediumJump(instrDescJmp* id); public: - CORINFO_FIELD_HANDLE emitAnyConst(const void* cnsAddr, unsigned cnsSize, emitDataAlignment alignment); + CORINFO_FIELD_HANDLE emitAnyConst(const void* cnsAddr, UNATIVE_OFFSET cnsSize, UNATIVE_OFFSET cnsAlign); private: CORINFO_FIELD_HANDLE emitFltOrDblConst(double constValue, emitAttr attr); @@ -2180,9 +2173,9 @@ class emitter dataSection* dsdList; dataSection* dsdLast; UNATIVE_OFFSET dsdOffs; - bool align16; + UNATIVE_OFFSET alignment; // in bytes, defaults to 4 - dataSecDsc() : dsdList(nullptr), dsdLast(nullptr), dsdOffs(0), align16(false) + dataSecDsc() : dsdList(nullptr), dsdLast(nullptr), dsdOffs(0), alignment(4) { } }; diff --git a/src/coreclr/src/jit/emitarm64.cpp b/src/coreclr/src/jit/emitarm64.cpp index 0d3eaba955931..7df6edf7ea6c4 100644 --- a/src/coreclr/src/jit/emitarm64.cpp +++ b/src/coreclr/src/jit/emitarm64.cpp @@ -604,20 +604,23 @@ void emitter::emitInsSanityCheck(instrDesc* id) break; case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar) - assert(id->idOpSize() == EA_8BYTE); + ins = id->idIns(); + datasize = id->idOpSize(); assert(insOptsNone(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); assert(isVectorRegister(id->idReg2())); - assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE)); + assert(isValidVectorShiftAmount(emitGetInsSC(id), datasize, emitInsIsVectorRightShift(ins))); break; case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector) - assert(isValidVectorDatasize(id->idOpSize())); - assert(isValidArrangement(id->idOpSize(), id->idInsOpt())); + ins = id->idIns(); + datasize = id->idOpSize(); + elemsize = optGetElemsize(id->idInsOpt()); + assert(isValidVectorDatasize(datasize)); + assert(isValidArrangement(datasize, id->idInsOpt())); assert(isVectorRegister(id->idReg1())); assert(isVectorRegister(id->idReg2())); - elemsize = optGetElemsize(id->idInsOpt()); - assert(isValidImmShift(emitGetInsSC(id), elemsize)); + assert(isValidVectorShiftAmount(emitGetInsSC(id), elemsize, emitInsIsVectorRightShift(ins))); break; case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general) @@ -649,12 +652,13 @@ void emitter::emitInsSanityCheck(instrDesc* id) break; case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector) + ins = id->idIns(); datasize = id->idOpSize(); assert(isValidVectorDatasize(datasize)); assert(isValidArrangement(datasize, id->idInsOpt())); elemsize = optGetElemsize(id->idInsOpt()); index = emitGetInsSC(id); - assert(isValidVectorIndex(datasize, elemsize, index)); + assert((ins == INS_dup) || isValidVectorIndex(datasize, elemsize, index)); assert(isVectorRegister(id->idReg1())); assert(isVectorRegister(id->idReg2())); break; @@ -1375,13 +1379,13 @@ emitter::insFormat emitter::emitInsFormat(instruction ins) // clang-format off const static insFormat insFormats[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt, - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt, - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt, + #define INST1(id, nm, info, fmt, e1 ) fmt, + #define INST2(id, nm, info, fmt, e1, e2 ) fmt, + #define INST3(id, nm, info, fmt, e1, e2, e3 ) fmt, + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) fmt, + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) fmt, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) fmt, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt, #include "instrs.h" }; // clang-format on @@ -1392,76 +1396,81 @@ emitter::insFormat emitter::emitInsFormat(instruction ins) return insFormats[ins]; } -// INST_FP is 1 -#define LD 2 -#define ST 4 -#define CMP 8 +#define LD 1 +#define ST 2 +#define CMP 4 +#define RSH 8 // clang-format off /*static*/ const BYTE CodeGenInterface::instInfo[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp, - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp, - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp, + #define INST1(id, nm, info, fmt, e1 ) info, + #define INST2(id, nm, info, fmt, e1, e2 ) info, + #define INST3(id, nm, info, fmt, e1, e2, e3 ) info, + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) info, + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) info, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) info, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) info, #include "instrs.h" }; // clang-format on -/***************************************************************************** - * - * Returns true if the instruction is some kind of compare or test instruction - */ - +//------------------------------------------------------------------------ +// emitInsIsCompare: Returns true if the instruction is some kind of compare or test instruction. +// bool emitter::emitInsIsCompare(instruction ins) { // We have pseudo ins like lea which are not included in emitInsLdStTab. if (ins < ArrLen(CodeGenInterface::instInfo)) - return (CodeGenInterface::instInfo[ins] & CMP) ? true : false; + return (CodeGenInterface::instInfo[ins] & CMP) != 0; else return false; } -/***************************************************************************** - * - * Returns true if the instruction is some kind of load instruction - */ - +//------------------------------------------------------------------------ +// emitInsIsLoad: Returns true if the instruction is some kind of load instruction. +// bool emitter::emitInsIsLoad(instruction ins) { // We have pseudo ins like lea which are not included in emitInsLdStTab. if (ins < ArrLen(CodeGenInterface::instInfo)) - return (CodeGenInterface::instInfo[ins] & LD) ? true : false; + return (CodeGenInterface::instInfo[ins] & LD) != 0; else return false; } -/***************************************************************************** - * - * Returns true if the instruction is some kind of store instruction - */ +//------------------------------------------------------------------------ +// emitInsIsStore: Returns true if the instruction is some kind of store instruction. +// bool emitter::emitInsIsStore(instruction ins) { // We have pseudo ins like lea which are not included in emitInsLdStTab. if (ins < ArrLen(CodeGenInterface::instInfo)) - return (CodeGenInterface::instInfo[ins] & ST) ? true : false; + return (CodeGenInterface::instInfo[ins] & ST) != 0; else return false; } -/***************************************************************************** - * - * Returns true if the instruction is some kind of load/store instruction - */ - +//------------------------------------------------------------------------ +// emitInsIsLoadOrStore: Returns true if the instruction is some kind of load or store instruction. +// bool emitter::emitInsIsLoadOrStore(instruction ins) { // We have pseudo ins like lea which are not included in emitInsLdStTab. if (ins < ArrLen(CodeGenInterface::instInfo)) - return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false; + return (CodeGenInterface::instInfo[ins] & (LD | ST)) != 0; + else + return false; +} + +//------------------------------------------------------------------------ +// emitInsIsVectorRightShift: Returns true if the instruction is ASIMD right shift. +// +bool emitter::emitInsIsVectorRightShift(instruction ins) +{ + // We have pseudo ins like lea which are not included in emitInsLdStTab. + if (ins < ArrLen(CodeGenInterface::instInfo)) + return (CodeGenInterface::instInfo[ins] & RSH) != 0; else return false; } @@ -1469,6 +1478,7 @@ bool emitter::emitInsIsLoadOrStore(instruction ins) #undef LD #undef ST #undef CMP +#undef RHS /***************************************************************************** * @@ -1480,101 +1490,101 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt) // clang-format off const static code_t insCodes1[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) e1, - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1, - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1, + #define INST1(id, nm, info, fmt, e1 ) e1, + #define INST2(id, nm, info, fmt, e1, e2 ) e1, + #define INST3(id, nm, info, fmt, e1, e2, e3 ) e1, + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e1, + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e1, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e1, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1, #include "instrs.h" }; const static code_t insCodes2[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2, - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) e2, + #define INST3(id, nm, info, fmt, e1, e2, e3 ) e2, + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e2, + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e2, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e2, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2, #include "instrs.h" }; const static code_t insCodes3[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) e3, + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e3, + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e3, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e3, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3, #include "instrs.h" }; const static code_t insCodes4[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) e4, + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e4, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e4, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4, #include "instrs.h" }; const static code_t insCodes5[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) e5, + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e5, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5, #include "instrs.h" }; const static code_t insCodes6[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) e6, + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6, #include "instrs.h" }; const static code_t insCodes7[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7, #include "instrs.h" }; const static code_t insCodes8[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8, #include "instrs.h" }; const static code_t insCodes9[] = { - #define INST1(id, nm, fp, ldst, fmt, e1 ) - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9, + #define INST1(id, nm, info, fmt, e1 ) + #define INST2(id, nm, info, fmt, e1, e2 ) + #define INST3(id, nm, info, fmt, e1, e2, e3 ) + #define INST4(id, nm, info, fmt, e1, e2, e3, e4 ) + #define INST5(id, nm, info, fmt, e1, e2, e3, e4, e5 ) + #define INST6(id, nm, info, fmt, e1, e2, e3, e4, e5, e6 ) + #define INST9(id, nm, info, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9, #include "instrs.h" }; // clang-format on @@ -1595,6 +1605,7 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt) const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L}; const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M}; const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A}; + const static insFormat formatEncode4J[4] = {IF_DV_2N, IF_DV_2O, IF_DV_3E, IF_DV_3A}; const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C}; const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C}; const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C}; @@ -1797,6 +1808,17 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt) } break; + case IF_EN4J: + for (index = 0; index < 4; index++) + { + if (fmt == formatEncode4J[index]) + { + encoding_found = true; + break; + } + } + break; + case IF_EN3A: for (index = 0; index < 3; index++) { @@ -4392,15 +4414,21 @@ void emitter::emitIns_R_R( break; case INS_fcvtl: - case INS_fcvtl2: case INS_fcvtn: + assert(isVectorRegister(reg1)); + assert(isVectorRegister(reg2)); + assert(size == EA_8BYTE); + assert((opt == INS_OPTS_4H) || (opt == INS_OPTS_2S)); + fmt = IF_DV_2A; + break; + + case INS_fcvtl2: case INS_fcvtn2: assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); - assert(isValidVectorDatasize(size)); - assert(insOptsNone(opt)); - assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported) - fmt = IF_DV_2G; + assert(size == EA_16BYTE); + assert((opt == INS_OPTS_8H) || (opt == INS_OPTS_4S)); + fmt = IF_DV_2A; break; case INS_scvtf: @@ -4796,6 +4824,7 @@ void emitter::emitIns_R_R_I( bool canEncode; bitMaskImm bmi; unsigned registerListSize; + bool isRightShift; case INS_mov: // Check for the 'mov' aliases for the vector registers @@ -4849,19 +4878,21 @@ void emitter::emitIns_R_R_I( fmt = IF_DI_2B; break; - case INS_sshr: - case INS_ssra: + case INS_shl: + case INS_sli: + case INS_sri: case INS_srshr: case INS_srsra: - case INS_shl: - case INS_ushr: - case INS_usra: + case INS_sshr: + case INS_ssra: case INS_urshr: case INS_ursra: - case INS_sri: - case INS_sli: + case INS_ushr: + case INS_usra: assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); + isRightShift = emitInsIsVectorRightShift(ins); + if (insOptsAnyArrangement(opt)) { // Vector operation @@ -4869,7 +4900,7 @@ void emitter::emitIns_R_R_I( assert(isValidArrangement(size, opt)); elemsize = optGetElemsize(opt); assert(isValidVectorElemsize(elemsize)); - assert(isValidImmShift(imm, elemsize)); + assert(isValidVectorShiftAmount(imm, elemsize, isRightShift)); assert(opt != INS_OPTS_1D); // Reserved encoding fmt = IF_DV_2O; break; @@ -4879,7 +4910,63 @@ void emitter::emitIns_R_R_I( // Scalar operation assert(insOptsNone(opt)); assert(size == EA_8BYTE); // only supported size - assert(isValidImmShift(imm, size)); + assert(isValidVectorShiftAmount(imm, size, isRightShift)); + fmt = IF_DV_2N; + } + break; + + case INS_sqshl: + case INS_uqshl: + case INS_sqshlu: + assert(isVectorRegister(reg1)); + assert(isVectorRegister(reg2)); + isRightShift = emitInsIsVectorRightShift(ins); + + if (insOptsAnyArrangement(opt)) + { + // Vector operation + assert(isValidArrangement(size, opt)); + assert(opt != INS_OPTS_1D); // The encoding immh = 1xxx, Q = 0 is reserved + elemsize = optGetElemsize(opt); + assert(isValidVectorShiftAmount(imm, elemsize, isRightShift)); + fmt = IF_DV_2O; + } + else + { + // Scalar operation + assert(insOptsNone(opt)); + assert(isValidVectorElemsize(size)); + assert(isValidVectorShiftAmount(imm, size, isRightShift)); + fmt = IF_DV_2N; + } + break; + + case INS_sqrshrn: + case INS_sqrshrun: + case INS_sqshrn: + case INS_sqshrun: + case INS_uqrshrn: + case INS_uqshrn: + assert(isVectorRegister(reg1)); + assert(isVectorRegister(reg2)); + isRightShift = emitInsIsVectorRightShift(ins); + + if (insOptsAnyArrangement(opt)) + { + // Vector operation + assert(isValidArrangement(size, opt)); + assert((opt != INS_OPTS_1D) && (opt != INS_OPTS_2D)); // The encoding immh = 1xxx, Q = x is reserved + elemsize = optGetElemsize(opt); + assert(isValidVectorShiftAmount(imm, elemsize, isRightShift)); + fmt = IF_DV_2O; + } + else + { + // Scalar operation + assert(insOptsNone(opt)); + assert(isValidVectorElemsize(size)); + assert(size != EA_8BYTE); // The encoding immh = 1xxx is reserved + assert(isValidVectorShiftAmount(imm, size, isRightShift)); fmt = IF_DV_2N; } break; @@ -4889,19 +4976,20 @@ void emitter::emitIns_R_R_I( assert(imm == 0); __fallthrough; - case INS_shrn: case INS_rshrn: + case INS_shrn: case INS_sshll: case INS_ushll: assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); + isRightShift = emitInsIsVectorRightShift(ins); // Vector operation assert(size == EA_8BYTE); assert(isValidArrangement(size, opt)); elemsize = optGetElemsize(opt); assert(elemsize != EA_8BYTE); // Reserved encodings assert(isValidVectorElemsize(elemsize)); - assert(isValidImmShift(imm, elemsize)); + assert(isValidVectorShiftAmount(imm, elemsize, isRightShift)); fmt = IF_DV_2O; break; @@ -4910,19 +4998,27 @@ void emitter::emitIns_R_R_I( assert(imm == 0); __fallthrough; - case INS_shrn2: case INS_rshrn2: + case INS_shrn2: + case INS_sqrshrn2: + case INS_sqrshrun2: + case INS_sqshrn2: + case INS_sqshrun2: case INS_sshll2: + case INS_uqrshrn2: + case INS_uqshrn2: case INS_ushll2: assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); + isRightShift = emitInsIsVectorRightShift(ins); + // Vector operation assert(size == EA_16BYTE); assert(isValidArrangement(size, opt)); elemsize = optGetElemsize(opt); - assert(elemsize != EA_8BYTE); // Reserved encodings + assert(elemsize != EA_8BYTE); // The encoding immh = 1xxx, Q = x is reserved assert(isValidVectorElemsize(elemsize)); - assert(isValidImmShift(imm, elemsize)); + assert(isValidVectorShiftAmount(imm, elemsize, isRightShift)); fmt = IF_DV_2O; break; @@ -5031,12 +5127,17 @@ void emitter::emitIns_R_R_I( { if (insOptsAnyArrangement(opt)) { + // The size and opt were modified to be based on the + // return type but the immediate is based on the operand + // which can be of a larger size. As such, we don't + // assert the index is valid here and instead do it in + // codegen. + // Vector operation assert(isValidVectorDatasize(size)); assert(isValidArrangement(size, opt)); elemsize = optGetElemsize(opt); assert(isValidVectorElemsize(elemsize)); - assert(isValidVectorIndex(size, elemsize, imm)); assert(opt != INS_OPTS_1D); // Reserved encoding fmt = IF_DV_2D; break; @@ -5565,6 +5666,10 @@ void emitter::emitIns_R_R_R( case INS_cmhi: case INS_cmhs: case INS_cmtst: + case INS_srshl: + case INS_sshl: + case INS_urshl: + case INS_ushl: assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); assert(isVectorRegister(reg3)); @@ -5586,8 +5691,12 @@ void emitter::emitIns_R_R_R( break; case INS_sqadd: + case INS_sqrshl: + case INS_sqshl: case INS_sqsub: case INS_uqadd: + case INS_uqrshl: + case INS_uqshl: case INS_uqsub: assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); @@ -7542,7 +7651,7 @@ void emitter::emitIns_R_C( fmt = IF_LARGELDC; if (isVectorRegister(reg)) { - assert(isValidScalarDatasize(size)); + assert(isValidVectorLSDatasize(size)); // For vector (float/double) register, we should have an integer address reg to // compute long address which consists of page address and page offset. // For integer constant, this is not needed since the dest reg can be used to @@ -7555,6 +7664,7 @@ void emitter::emitIns_R_C( assert(isValidGeneralDatasize(size)); } break; + default: unreached(); } @@ -8747,18 +8857,33 @@ void emitter::emitIns_Call(EmitCallType callType, return bits; } -/***************************************************************************** - * - * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction - */ - -/*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift) +// insEncodeVectorShift: Returns the encoding for the SIMD shift (immediate) instructions. +// +// Arguments: +// size - for the scalar variants specifies 'datasize', for the vector variants specifies 'element size'. +// shift - if the shift is positive, the operation is a left shift. Otherwise, it is a right shift. +// +// Returns: +// "immh:immb" field of the instruction that contains encoded shift amount. +// +/*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shiftAmount) { - assert(shift < getBitWidth(size)); - - code_t imm = (code_t)(getBitWidth(size) + shift); + if (shiftAmount < 0) + { + shiftAmount = -shiftAmount; + // The right shift amount must be in the range 1 to the destination element width in bits. + assert((shiftAmount > 0) && (shiftAmount <= getBitWidth(size))); - return imm << 16; + code_t imm = (code_t)(2 * getBitWidth(size) - shiftAmount); + return imm << 16; + } + else + { + // The left shift amount must in the range 0 to the element width in bits minus 1. + assert(shiftAmount < getBitWidth(size)); + code_t imm = (code_t)(getBitWidth(size) + shiftAmount); + return imm << 16; + } } /***************************************************************************** @@ -10588,9 +10713,25 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) elemsize = optGetElemsize(id->idInsOpt()); code = emitInsCode(ins, fmt); code |= insEncodeVectorsize(id->idOpSize()); // Q - code |= insEncodeFloatElemsize(elemsize); // X - code |= insEncodeReg_Vd(id->idReg1()); // ddddd - code |= insEncodeReg_Vn(id->idReg2()); // nnnnn + if ((ins == INS_fcvtl) || (ins == INS_fcvtl2) || (ins == INS_fcvtn) || (ins == INS_fcvtn2)) + { + // fcvtl{2} and fcvtn{2} encode the element size as + // esize = 16 << UInt(sz) + if (elemsize == EA_4BYTE) + { + code |= 0x00400000; // X + } + else + { + assert(elemsize == EA_2BYTE); + } + } + else + { + code |= insEncodeFloatElemsize(elemsize); // X + } + code |= insEncodeReg_Vd(id->idReg1()); // ddddd + code |= insEncodeReg_Vn(id->idReg2()); // nnnnn dst += emitOutput_Instr(dst, code); break; @@ -10731,11 +10872,12 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) break; case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar) - imm = emitGetInsSC(id); - code = emitInsCode(ins, fmt); - code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii - code |= insEncodeReg_Vd(id->idReg1()); // ddddd - code |= insEncodeReg_Vn(id->idReg2()); // nnnnn + imm = emitGetInsSC(id); + elemsize = id->idOpSize(); + code = emitInsCode(ins, fmt); + code |= insEncodeVectorShift(elemsize, emitInsIsVectorRightShift(ins) ? -imm : imm); // iiiiiii + code |= insEncodeReg_Vd(id->idReg1()); // ddddd + code |= insEncodeReg_Vn(id->idReg2()); // nnnnn dst += emitOutput_Instr(dst, code); break; @@ -10743,10 +10885,10 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) imm = emitGetInsSC(id); elemsize = optGetElemsize(id->idInsOpt()); code = emitInsCode(ins, fmt); - code |= insEncodeVectorsize(id->idOpSize()); // Q - code |= insEncodeVectorShift(elemsize, imm); // iiiiiii - code |= insEncodeReg_Vd(id->idReg1()); // ddddd - code |= insEncodeReg_Vn(id->idReg2()); // nnnnn + code |= insEncodeVectorsize(id->idOpSize()); // Q + code |= insEncodeVectorShift(elemsize, emitInsIsVectorRightShift(ins) ? -imm : imm); // iiiiiii + code |= insEncodeReg_Vd(id->idReg1()); // ddddd + code |= insEncodeReg_Vn(id->idReg2()); // nnnnn dst += emitOutput_Instr(dst, code); break; @@ -12338,6 +12480,23 @@ void emitter::emitDispIns( break; case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector) + if ((ins == INS_fcvtl) || (ins == INS_fcvtl2)) + { + emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true); + emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); + } + else if ((ins == INS_fcvtn) || (ins == INS_fcvtn2)) + { + emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); + emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), false); + } + else + { + emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); + emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); + } + break; + case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); @@ -12485,7 +12644,14 @@ void emitter::emitDispIns( } else { - elemsize = optGetElemsize(id->idInsOpt()); + if ((ins == INS_saddlv) || (ins == INS_uaddlv)) + { + elemsize = optGetElemsize(optWidenDstArrangement(id->idInsOpt())); + } + else + { + elemsize = optGetElemsize(id->idInsOpt()); + } emitDispReg(id->idReg1(), elemsize, true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } @@ -12712,7 +12878,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (addr->isContained()) { - assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA); + assert(addr->OperGet() == GT_CLS_VAR_ADDR || addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA); int offset = 0; DWORD lsl = 0; @@ -12789,7 +12955,13 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR } else // no Index register { - if (emitIns_valid_imm_for_ldst_offset(offset, emitTypeSize(indir->TypeGet()))) + if (addr->OperGet() == GT_CLS_VAR_ADDR) + { + // Get a temp integer register to compute long address. + regNumber addrReg = indir->GetSingleTempReg(); + emitIns_R_C(ins, attr, dataReg, addrReg, addr->AsClsVar()->gtClsVarHnd, 0); + } + else if (emitIns_valid_imm_for_ldst_offset(offset, emitTypeSize(indir->TypeGet()))) { // Then load/store dataReg from/to [memBase + offset] emitIns_R_R_I(ins, attr, dataReg, memBase->GetRegNum(), offset); @@ -13918,6 +14090,14 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins result.insLatency = PERFSCORE_LATENCY_2C; break; + case INS_fcvtl: + case INS_fcvtl2: + case INS_fcvtn: + case INS_fcvtn2: + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + result.insLatency = PERFSCORE_LATENCY_4C; + break; + default: // all other instructions perfScoreUnhandledInstruction(id, &result); @@ -13970,14 +14150,6 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins result.insLatency = PERFSCORE_LATENCY_2C; break; - case INS_fcvtl: - case INS_fcvtl2: - case INS_fcvtn: - case INS_fcvtn2: - result.insThroughput = PERFSCORE_THROUGHPUT_1C; - result.insLatency = PERFSCORE_LATENCY_4C; - break; - case INS_frecpe: case INS_frecpx: case INS_frsqrte: @@ -14284,6 +14456,8 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins case INS_shadd: case INS_shsub: case INS_srhadd: + case INS_srshl: + case INS_sshl: case INS_smax: case INS_smaxp: case INS_smin: @@ -14295,6 +14469,8 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins case INS_uhadd: case INS_uhsub: case INS_urhadd: + case INS_urshl: + case INS_ushl: case INS_uzp1: case INS_uzp2: case INS_zip1: @@ -14333,6 +14509,10 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins case INS_mul: case INS_mla: case INS_mls: + case INS_sqshl: + case INS_sqrshl: + case INS_uqrshl: + case INS_uqshl: result.insThroughput = PERFSCORE_THROUGHPUT_2X; result.insLatency = PERFSCORE_LATENCY_4C; break; @@ -14462,9 +14642,13 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins case INS_rshrn: case INS_rshrn2: - case INS_ssra: case INS_srshr: + case INS_sqshrn: + case INS_sqshrn2: + case INS_ssra: case INS_urshr: + case INS_uqshrn: + case INS_uqshrn2: case INS_usra: if (id->idOpSize() == EA_16BYTE) { @@ -14484,6 +14668,29 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins result.insLatency = PERFSCORE_LATENCY_4C; break; + case INS_sqrshrn: + case INS_sqrshrn2: + case INS_sqrshrun: + case INS_sqrshrun2: + case INS_sqshrun: + case INS_sqshrun2: + case INS_sqshl: + case INS_sqshlu: + case INS_uqrshrn: + case INS_uqrshrn2: + case INS_uqshl: + if (id->idOpSize() == EA_16BYTE) + { + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + result.insLatency = PERFSCORE_LATENCY_4C; + } + else + { + result.insThroughput = PERFSCORE_THROUGHPUT_2X; + result.insLatency = PERFSCORE_LATENCY_4C; + } + break; + default: // all other instructions perfScoreUnhandledInstruction(id, &result); diff --git a/src/coreclr/src/jit/emitarm64.h b/src/coreclr/src/jit/emitarm64.h index 96bbb37aec732..9c365c005d1fd 100644 --- a/src/coreclr/src/jit/emitarm64.h +++ b/src/coreclr/src/jit/emitarm64.h @@ -87,6 +87,7 @@ bool emitInsIsCompare(instruction ins); bool emitInsIsLoad(instruction ins); bool emitInsIsStore(instruction ins); bool emitInsIsLoadOrStore(instruction ins); +bool emitInsIsVectorRightShift(instruction ins); emitAttr emitInsTargetRegSize(instrDesc* id); emitAttr emitInsLoadStoreSize(instrDesc* id); @@ -300,8 +301,8 @@ static code_t insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2); // Returns the encoding to select 'index' for an Arm64 'mul' elem instruction static code_t insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index); -// Returns the encoding to shift by 'shift' bits for an Arm64 vector or scalar instruction -static code_t insEncodeVectorShift(emitAttr size, ssize_t shift); +// Returns the encoding for ASIMD Shift instruction. +static code_t insEncodeVectorShift(emitAttr size, ssize_t shiftAmount); // Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction static code_t insEncodeElemsize(emitAttr size); @@ -517,6 +518,13 @@ inline static unsigned isValidImmShift(ssize_t imm, emitAttr size) return (imm >= 0) && (imm < getBitWidth(size)); } +// Returns true if the 'shiftAmount' represents a valid shift for the given 'size'. +inline static unsigned isValidVectorShiftAmount(ssize_t shiftAmount, emitAttr size, bool rightShift) +{ + return (rightShift && (shiftAmount >= 1) && (shiftAmount <= getBitWidth(size))) || + ((shiftAmount >= 0) && (shiftAmount < getBitWidth(size))); +} + inline static bool isValidGeneralDatasize(emitAttr size) { return (size == EA_8BYTE) || (size == EA_4BYTE); diff --git a/src/coreclr/src/jit/emitfmtsarm64.h b/src/coreclr/src/jit/emitfmtsarm64.h index 16244c1a34285..c39f85d99ae69 100644 --- a/src/coreclr/src/jit/emitfmtsarm64.h +++ b/src/coreclr/src/jit/emitfmtsarm64.h @@ -61,6 +61,7 @@ IF_DEF(EN4F, IS_NONE, NONE) // Instruction has 4 possible encoding types, type F IF_DEF(EN4G, IS_NONE, NONE) // Instruction has 4 possible encoding types, type G IF_DEF(EN4H, IS_NONE, NONE) // Instruction has 4 possible encoding types, type H IF_DEF(EN4I, IS_NONE, NONE) // Instruction has 4 possible encoding types, type I +IF_DEF(EN4J, IS_NONE, NONE) // Instruction has 3 possible encoding types, type J IF_DEF(EN3A, IS_NONE, NONE) // Instruction has 3 possible encoding types, type A IF_DEF(EN3B, IS_NONE, NONE) // Instruction has 3 possible encoding types, type B IF_DEF(EN3C, IS_NONE, NONE) // Instruction has 3 possible encoding types, type C diff --git a/src/coreclr/src/jit/emitpub.h b/src/coreclr/src/jit/emitpub.h index cd28e0355c03b..e1f5e80b5295b 100644 --- a/src/coreclr/src/jit/emitpub.h +++ b/src/coreclr/src/jit/emitpub.h @@ -83,17 +83,17 @@ void emitIns_J(instruction ins, BasicBlock* dst, int instrCount = 0); /* Emit initialized data sections */ /************************************************************************/ -UNATIVE_OFFSET emitDataGenBeg(UNATIVE_OFFSET size, bool align); +UNATIVE_OFFSET emitDataGenBeg(UNATIVE_OFFSET size, UNATIVE_OFFSET alignment); UNATIVE_OFFSET emitBBTableDataGenBeg(unsigned numEntries, bool relativeAddr); -void emitDataGenData(unsigned offs, const void* data, size_t size); +void emitDataGenData(unsigned offs, const void* data, UNATIVE_OFFSET size); void emitDataGenData(unsigned offs, BasicBlock* label); void emitDataGenEnd(); -UNATIVE_OFFSET emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign); +UNATIVE_OFFSET emitDataConst(const void* cnsAddr, UNATIVE_OFFSET cnsSize, UNATIVE_OFFSET cnsAlign); UNATIVE_OFFSET emitDataSize(); diff --git a/src/coreclr/src/jit/emitxarch.cpp b/src/coreclr/src/jit/emitxarch.cpp index 269324d9a9d4f..0167887f0c919 100644 --- a/src/coreclr/src/jit/emitxarch.cpp +++ b/src/coreclr/src/jit/emitxarch.cpp @@ -10765,7 +10765,12 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) } // Check that the offset is properly aligned (i.e. the ddd in [ddd]) - assert((emitChkAlign == false) || (ins == INS_lea) || (((size_t)addr & (byteSize - 1)) == 0)); + // When SMALL_CODE is set, we only expect 4-byte alignment, otherwise + // we expect the same alignment as the size of the constant. + + assert((emitChkAlign == false) || (ins == INS_lea) || + ((emitComp->compCodeOpt() == Compiler::SMALL_CODE) && (((size_t)addr & 3) == 0)) || + (((size_t)addr & (byteSize - 1)) == 0)); } else { diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp index 854142856c0f1..778962636fb0a 100644 --- a/src/coreclr/src/jit/flowgraph.cpp +++ b/src/coreclr/src/jit/flowgraph.cpp @@ -271,23 +271,16 @@ void Compiler::fgInstrumentMethod() HRESULT res = info.compCompHnd->allocMethodBlockCounts(countOfBlocks, &profileBlockCountsStart); - Statement* stmt; - if (!SUCCEEDED(res)) { // The E_NOTIMPL status is returned when we are profiling a generic method from a different assembly if (res == E_NOTIMPL) { - // In such cases we still want to add the method entry callback node - - GenTreeCall::Use* args = gtNewCallArgs(gtNewIconEmbMethHndNode(info.compMethodHnd)); - GenTree* call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args); - - stmt = gtNewStmt(call); + // expected failure... } else { - noway_assert(!"Error: failed to allocate profileBlockCounts"); + noway_assert(!"Error: failed to allocate profileBlockCounts"); return; } } @@ -310,8 +303,8 @@ void Compiler::fgInstrumentMethod() } // Assign the current block's IL offset into the profile data - currentBlockCounts->ILOffset = block->bbCodeOffs; - assert(currentBlockCounts->ExecutionCount == 0); // This value should already be zero-ed out + currentBlockCounts->ILOffset = block->bbCodeOffs; + currentBlockCounts->ExecutionCount = 0; size_t addrOfCurrentExecutionCount = (size_t)¤tBlockCounts->ExecutionCount; @@ -337,50 +330,51 @@ void Compiler::fgInstrumentMethod() // Check that we allocated and initialized the same number of BlockCounts tuples noway_assert(countOfBlocks == 0); - // Add the method entry callback node - - GenTree* arg; + // When prejitting, add the method entry callback node + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) + { + GenTree* arg; #ifdef FEATURE_READYTORUN_COMPILER - if (opts.IsReadyToRun()) - { - mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd); + if (opts.IsReadyToRun()) + { + mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd); - CORINFO_RESOLVED_TOKEN resolvedToken; - resolvedToken.tokenContext = MAKE_METHODCONTEXT(info.compMethodHnd); - resolvedToken.tokenScope = info.compScopeHnd; - resolvedToken.token = currentMethodToken; - resolvedToken.tokenType = CORINFO_TOKENKIND_Method; + CORINFO_RESOLVED_TOKEN resolvedToken; + resolvedToken.tokenContext = MAKE_METHODCONTEXT(info.compMethodHnd); + resolvedToken.tokenScope = info.compScopeHnd; + resolvedToken.token = currentMethodToken; + resolvedToken.tokenType = CORINFO_TOKENKIND_Method; - info.compCompHnd->resolveToken(&resolvedToken); + info.compCompHnd->resolveToken(&resolvedToken); - arg = impTokenToHandle(&resolvedToken); - } - else + arg = impTokenToHandle(&resolvedToken); + } + else #endif - { - arg = gtNewIconEmbMethHndNode(info.compMethodHnd); - } + { + arg = gtNewIconEmbMethHndNode(info.compMethodHnd); + } - GenTreeCall::Use* args = gtNewCallArgs(arg); - GenTree* call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args); + GenTreeCall::Use* args = gtNewCallArgs(arg); + GenTree* call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args); - // Get the address of the first blocks ExecutionCount - size_t addrOfFirstExecutionCount = (size_t)&profileBlockCountsStart->ExecutionCount; + // Get the address of the first blocks ExecutionCount + size_t addrOfFirstExecutionCount = (size_t)&profileBlockCountsStart->ExecutionCount; - // Read Basic-Block count value - GenTree* valueNode = gtNewIndOfIconHandleNode(TYP_INT, addrOfFirstExecutionCount, GTF_ICON_BBC_PTR, false); + // Read Basic-Block count value + GenTree* valueNode = gtNewIndOfIconHandleNode(TYP_INT, addrOfFirstExecutionCount, GTF_ICON_BBC_PTR, false); - // Compare Basic-Block count value against zero - GenTree* relop = gtNewOperNode(GT_NE, TYP_INT, valueNode, gtNewIconNode(0, TYP_INT)); - GenTree* colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call); - GenTree* cond = gtNewQmarkNode(TYP_VOID, relop, colon); - stmt = gtNewStmt(cond); - } + // Compare Basic-Block count value against zero + GenTree* relop = gtNewOperNode(GT_NE, TYP_INT, valueNode, gtNewIconNode(0, TYP_INT)); + GenTree* colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call); + GenTree* cond = gtNewQmarkNode(TYP_VOID, relop, colon); + Statement* stmt = gtNewStmt(cond); - fgEnsureFirstBBisScratch(); - - fgInsertStmtAtEnd(fgFirstBB, stmt); + fgEnsureFirstBBisScratch(); + fgInsertStmtAtEnd(fgFirstBB, stmt); + } + } } /***************************************************************************** @@ -10959,7 +10953,11 @@ void Compiler::fgRemoveConditionalJump(BasicBlock* block) { test->SetRootNode(sideEffList); - fgMorphBlockStmt(block, test DEBUGARG("fgRemoveConditionalJump")); + if (fgStmtListThreaded) + { + gtSetStmtInfo(test); + fgSetStmtSeq(test); + } } } } @@ -23783,7 +23781,7 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) if (tmpNum != BAD_VAR_NUM) { LclVarDsc* const tmpDsc = lvaGetDesc(tmpNum); - if (!fgVarNeedsExplicitZeroInit(tmpDsc, bbInALoop, bbIsReturn)) + if (!fgVarNeedsExplicitZeroInit(tmpNum, bbInALoop, bbIsReturn)) { JITDUMP("\nSuppressing zero-init for V%02u -- expect to zero in prolog\n", tmpNum); tmpDsc->lvSuppressedZeroInit = 1; diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp index 8e341ce7dab5a..191c87322b4ec 100644 --- a/src/coreclr/src/jit/gentree.cpp +++ b/src/coreclr/src/jit/gentree.cpp @@ -622,15 +622,12 @@ void GenTree::CopyReg(GenTree* from) // bool GenTree::gtHasReg() const { - bool hasReg; + bool hasReg = false; if (IsMultiRegCall()) { - // Have to cast away const-ness because GetReturnTypeDesc() is a non-const method - GenTree* tree = const_cast(this); - GenTreeCall* call = tree->AsCall(); - unsigned regCount = call->GetReturnTypeDesc()->GetReturnRegCount(); - hasReg = false; + const GenTreeCall* call = AsCall(); + const unsigned regCount = call->GetReturnTypeDesc()->GetReturnRegCount(); // A Multi-reg call node is said to have regs, if it has // reg assigned to each of its result registers. @@ -645,11 +642,9 @@ bool GenTree::gtHasReg() const } else if (IsCopyOrReloadOfMultiRegCall()) { - GenTree* tree = const_cast(this); - GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload(); - GenTreeCall* call = copyOrReload->gtGetOp1()->AsCall(); - unsigned regCount = call->GetReturnTypeDesc()->GetReturnRegCount(); - hasReg = false; + const GenTreeCopyOrReload* copyOrReload = AsCopyOrReload(); + const GenTreeCall* call = copyOrReload->gtGetOp1()->AsCall(); + const unsigned regCount = call->GetReturnTypeDesc()->GetReturnRegCount(); // A Multi-reg copy or reload node is said to have regs, // if it has valid regs in any of the positions. @@ -693,9 +688,7 @@ int GenTree::GetRegisterDstCount() const } else if (IsMultiRegCall()) { - // temporarily cast away const-ness as AsCall() method is not declared const - GenTree* temp = const_cast(this); - return temp->AsCall()->GetReturnTypeDesc()->GetReturnRegCount(); + return AsCall()->GetReturnTypeDesc()->GetReturnRegCount(); } else if (IsCopyOrReload()) { @@ -750,9 +743,8 @@ regMaskTP GenTree::gtGetRegMask() const if (IsMultiRegCall()) { // temporarily cast away const-ness as AsCall() method is not declared const - resultMask = genRegMask(GetRegNum()); - GenTree* temp = const_cast(this); - resultMask |= temp->AsCall()->GetOtherRegMask(); + resultMask = genRegMask(GetRegNum()); + resultMask |= AsCall()->GetOtherRegMask(); } else if (IsCopyOrReloadOfMultiRegCall()) { @@ -760,10 +752,9 @@ regMaskTP GenTree::gtGetRegMask() const // positions that need to be copied or reloaded. Hence we need // to consider only those registers for computing reg mask. - GenTree* tree = const_cast(this); - GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload(); - GenTreeCall* call = copyOrReload->gtGetOp1()->AsCall(); - unsigned regCount = call->GetReturnTypeDesc()->GetReturnRegCount(); + const GenTreeCopyOrReload* copyOrReload = AsCopyOrReload(); + const GenTreeCall* call = copyOrReload->gtGetOp1()->AsCall(); + const unsigned regCount = call->GetReturnTypeDesc()->GetReturnRegCount(); resultMask = RBM_NONE; for (unsigned i = 0; i < regCount; ++i) @@ -778,9 +769,8 @@ regMaskTP GenTree::gtGetRegMask() const #if FEATURE_ARG_SPLIT else if (OperIsPutArgSplit()) { - GenTree* tree = const_cast(this); - GenTreePutArgSplit* splitArg = tree->AsPutArgSplit(); - unsigned regCount = splitArg->gtNumRegs; + const GenTreePutArgSplit* splitArg = AsPutArgSplit(); + const unsigned regCount = splitArg->gtNumRegs; resultMask = RBM_NONE; for (unsigned i = 0; i < regCount; ++i) @@ -6182,21 +6172,14 @@ GenTreeCall* Compiler::gtNewCallNode( // Initialize spill flags of gtOtherRegs node->ClearOtherRegFlags(); -#if defined(TARGET_X86) || defined(TARGET_ARM) - // Initialize the multi-reg long return info if necessary +#if !defined(TARGET_64BIT) if (varTypeIsLong(node)) { - // The return type will remain as the incoming long type - node->gtReturnType = node->gtType; - + assert(node->gtReturnType == node->gtType); // Initialize Return type descriptor of call node - ReturnTypeDesc* retTypeDesc = node->GetReturnTypeDesc(); - retTypeDesc->InitializeLongReturnType(this); - - // must be a long returned in two registers - assert(retTypeDesc->GetReturnRegCount() == 2); + node->InitializeLongReturnType(); } -#endif // defined(TARGET_X86) || defined(TARGET_ARM) +#endif // !defined(TARGET_64BIT) return node; } @@ -7861,6 +7844,15 @@ GenTreeCall* Compiler::gtCloneExprCallHelper(GenTreeCall* tree, unsigned addFlag copy->CopyOtherRegFlags(tree); + // We keep track of the number of no return calls, so if we've cloned + // one of these, update the tracking. + // + if (tree->IsNoReturn()) + { + assert(copy->IsNoReturn()); + setMethodHasNoReturnCalls(); + } + return copy; } @@ -10217,8 +10209,8 @@ void Compiler::gtDispRegVal(GenTree* tree) { // 0th reg is GettRegNum(), which is already printed above. // Print the remaining regs of a multi-reg call node. - GenTreeCall* call = tree->AsCall(); - unsigned regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount(); + const GenTreeCall* call = tree->AsCall(); + const unsigned regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount(); for (unsigned i = 1; i < regCount; ++i) { printf(",%s", compRegVarName(call->GetRegNumByIdx(i))); @@ -10226,9 +10218,9 @@ void Compiler::gtDispRegVal(GenTree* tree) } else if (tree->IsCopyOrReloadOfMultiRegCall()) { - GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload(); - GenTreeCall* call = tree->gtGetOp1()->AsCall(); - unsigned regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount(); + const GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload(); + const GenTreeCall* call = tree->gtGetOp1()->AsCall(); + const unsigned regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount(); for (unsigned i = 1; i < regCount; ++i) { printf(",%s", compRegVarName(copyOrReload->GetRegNumByIdx(i))); @@ -15315,9 +15307,7 @@ GenTree* Compiler::gtNewRefCOMfield(GenTree* objPtr, #if FEATURE_MULTIREG_RET if (varTypeIsStruct(call)) { - // Initialize Return type descriptor of call node. - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - retTypeDesc->InitializeStructReturnType(this, structType); + call->InitializeStructReturnType(this, structType); } #endif // FEATURE_MULTIREG_RET @@ -16529,14 +16519,8 @@ bool GenTree::isContained() const else if (OperKind() & GTK_RELOP) { // We have to cast away const-ness since AsOp() method is non-const. - GenTree* childNode = const_cast(this)->AsOp()->gtOp1; - assert((isMarkedContained == false) || childNode->IsSIMDEqualityOrInequality()); - } - - // these either produce a result in register or set flags reg. - else if (IsSIMDEqualityOrInequality()) - { - assert(!isMarkedContained); + const GenTree* childNode = AsOp()->gtGetOp1(); + assert(isMarkedContained == false); } // if it's contained it can't be unused. @@ -18461,13 +18445,8 @@ bool GenTree::isCommutativeSIMDIntrinsic() case SIMDIntrinsicAdd: case SIMDIntrinsicBitwiseAnd: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: case SIMDIntrinsicEqual: - case SIMDIntrinsicMax: - case SIMDIntrinsicMin: case SIMDIntrinsicMul: - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: return true; default: return false; @@ -18659,40 +18638,6 @@ GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode( GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3), hwIntrinsicID, TYP_UNKNOWN, 0); } -//--------------------------------------------------------------------------------------- -// gtNewMustThrowException: -// create a throw node (calling into JIT helper) that must be thrown. -// The result would be a comma node: COMMA(jithelperthrow(void), x) where x's type should be specified. -// -// Arguments -// helper - JIT helper ID -// type - return type of the node -// -// Return Value -// pointer to the throw node -// -GenTree* Compiler::gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd) -{ - GenTreeCall* node = gtNewHelperCallNode(helper, TYP_VOID); - node->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; - if (type != TYP_VOID) - { - unsigned dummyTemp = lvaGrabTemp(true DEBUGARG("dummy temp of must thrown exception")); - if (type == TYP_STRUCT) - { - lvaSetStruct(dummyTemp, clsHnd, false); - type = lvaTable[dummyTemp].lvType; // struct type is normalized - } - else - { - lvaTable[dummyTemp].lvType = type; - } - GenTree* dummyNode = gtNewLclvNode(dummyTemp, type); - return gtNewOperNode(GT_COMMA, type, node, dummyNode); - } - return node; -} - // Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise bool GenTreeHWIntrinsic::OperIsMemoryLoad() const { @@ -18782,6 +18727,40 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoadOrStore() const #endif // FEATURE_HW_INTRINSICS +//--------------------------------------------------------------------------------------- +// gtNewMustThrowException: +// create a throw node (calling into JIT helper) that must be thrown. +// The result would be a comma node: COMMA(jithelperthrow(void), x) where x's type should be specified. +// +// Arguments +// helper - JIT helper ID +// type - return type of the node +// +// Return Value +// pointer to the throw node +// +GenTree* Compiler::gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd) +{ + GenTreeCall* node = gtNewHelperCallNode(helper, TYP_VOID); + node->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + if (type != TYP_VOID) + { + unsigned dummyTemp = lvaGrabTemp(true DEBUGARG("dummy temp of must thrown exception")); + if (type == TYP_STRUCT) + { + lvaSetStruct(dummyTemp, clsHnd, false); + type = lvaTable[dummyTemp].lvType; // struct type is normalized + } + else + { + lvaTable[dummyTemp].lvType = type; + } + GenTree* dummyNode = gtNewLclvNode(dummyTemp, type); + return gtNewOperNode(GT_COMMA, type, node, dummyNode); + } + return node; +} + //--------------------------------------------------------------------------------------- // InitializeStructReturnType: // Initialize the Return Type Descriptor for a method that returns a struct type @@ -18909,16 +18888,10 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HA // InitializeLongReturnType: // Initialize the Return Type Descriptor for a method that returns a TYP_LONG // -// Arguments -// comp - Compiler Instance -// -// Return Value -// None -// -void ReturnTypeDesc::InitializeLongReturnType(Compiler* comp) +void ReturnTypeDesc::InitializeLongReturnType() { + assert(!m_inited); #if defined(TARGET_X86) || defined(TARGET_ARM) - // Setups up a ReturnTypeDesc for returning a long using two registers // assert(MAX_RET_REG_COUNT >= 2); @@ -18950,7 +18923,7 @@ void ReturnTypeDesc::InitializeLongReturnType(Compiler* comp) // x86 and ARM return long in multiple registers. // ARM and ARM64 return HFA struct in multiple registers. // -regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx) +regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx) const { unsigned count = GetReturnRegCount(); assert(idx < count); @@ -19079,7 +19052,7 @@ regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx) // of return registers and wants to know the set of return registers. // // static -regMaskTP ReturnTypeDesc::GetABIReturnRegs() +regMaskTP ReturnTypeDesc::GetABIReturnRegs() const { regMaskTP resultMask = RBM_NONE; diff --git a/src/coreclr/src/jit/gentree.h b/src/coreclr/src/jit/gentree.h index 12645fb12d219..c43227bd66311 100644 --- a/src/coreclr/src/jit/gentree.h +++ b/src/coreclr/src/jit/gentree.h @@ -775,14 +775,14 @@ struct GenTree // Note that a node marked GTF_VAR_MULTIREG can only be a pure definition of all the fields, or a pure use of all the fields, // so we don't need the equivalent of GTF_VAR_USEASG. -#define GTF_VAR_MULTIREG_DEATH0 0x20000000 // GT_LCL_VAR -- The last-use bit for a lclVar (the first register if it is multireg). +#define GTF_VAR_MULTIREG_DEATH0 0x04000000 // GT_LCL_VAR -- The last-use bit for a lclVar (the first register if it is multireg). #define GTF_VAR_DEATH GTF_VAR_MULTIREG_DEATH0 -#define GTF_VAR_MULTIREG_DEATH1 0x10000000 // GT_LCL_VAR -- The last-use bit for the second register of a multireg lclVar. -#define GTF_VAR_MULTIREG_DEATH2 0x08000000 // GT_LCL_VAR -- The last-use bit for the third register of a multireg lclVar. -#define GTF_VAR_MULTIREG_DEATH3 0x04000000 // GT_LCL_VAR -- The last-use bit for the fourth register of a multireg lclVar. +#define GTF_VAR_MULTIREG_DEATH1 0x08000000 // GT_LCL_VAR -- The last-use bit for the second register of a multireg lclVar. +#define GTF_VAR_MULTIREG_DEATH2 0x10000000 // GT_LCL_VAR -- The last-use bit for the third register of a multireg lclVar. +#define GTF_VAR_MULTIREG_DEATH3 0x20000000 // GT_LCL_VAR -- The last-use bit for the fourth register of a multireg lclVar. #define GTF_VAR_DEATH_MASK (GTF_VAR_MULTIREG_DEATH0|GTF_VAR_MULTIREG_DEATH1 | GTF_VAR_MULTIREG_DEATH2 | GTF_VAR_MULTIREG_DEATH3) - // This is the amount we have to shift, plus the regIndex, to get the last use bit we want. -#define MULTIREG_LAST_USE_SHIFT 17 +// This is the amount we have to shift, plus the regIndex, to get the last use bit we want. +#define MULTIREG_LAST_USE_SHIFT 26 #define GTF_VAR_MULTIREG 0x02000000 // This is a struct or (on 32-bit platforms) long variable that is used or defined // to/from a multireg source or destination (e.g. a call arg or return, or an op // that returns its result in multiple registers such as a long multiply). @@ -1646,11 +1646,10 @@ struct GenTree inline bool IsFPZero(); inline bool IsIntegralConst(ssize_t constVal); inline bool IsIntegralConstVector(ssize_t constVal); + inline bool IsSIMDZero(); inline bool IsBoxedValue(); - inline bool IsSIMDEqualityOrInequality() const; - static bool OperIsList(genTreeOps gtOper) { return gtOper == GT_LIST; @@ -1732,6 +1731,9 @@ struct GenTree // Returns the type of the regIndex'th register defined by a multi-reg node. var_types GetRegTypeByIndex(int regIndex); + // Returns the GTF flag equivalent for the regIndex'th register of a multi-reg node. + unsigned int GetRegSpillFlagByIdx(int regIndex) const; + // Returns true if it is a GT_COPY or GT_RELOAD node inline bool IsCopyOrReload() const; @@ -3232,6 +3234,7 @@ struct GenTreeLclVar : public GenTreeLclVarCommon unsigned int GetLastUseBit(int regIndex) { assert(regIndex < 4); + static_assert_no_msg((1 << MULTIREG_LAST_USE_SHIFT) == GTF_VAR_MULTIREG_DEATH0); return (1 << (MULTIREG_LAST_USE_SHIFT + regIndex)); } @@ -3250,6 +3253,7 @@ struct GenTreeLclVar : public GenTreeLclVarCommon void SetMultiReg() { gtFlags |= GTF_VAR_MULTIREG; + ClearOtherRegFlags(); } regNumber GetRegNumByIdx(int regIndex) @@ -3600,8 +3604,8 @@ struct ReturnTypeDesc void InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd); // Initialize the Return Type Descriptor for a method that returns a TYP_LONG - // Only needed for X86 - void InitializeLongReturnType(Compiler* comp); + // Only needed for X86 and arm32. + void InitializeLongReturnType(); // Reset type descriptor to defaults void Reset() @@ -3680,6 +3684,7 @@ struct ReturnTypeDesc } else { + assert(m_inited); return ((m_regType[0] != TYP_UNKNOWN) && (m_regType[1] != TYP_UNKNOWN)); } } @@ -3695,7 +3700,7 @@ struct ReturnTypeDesc // var_type of the return register specified by its index. // asserts if the index does not have a valid register return type. - var_types GetReturnRegType(unsigned index) + var_types GetReturnRegType(unsigned index) const { var_types result = m_regType[index]; assert(result != TYP_UNKNOWN); @@ -3711,10 +3716,10 @@ struct ReturnTypeDesc } // Get ith ABI return register - regNumber GetABIReturnReg(unsigned idx); + regNumber GetABIReturnReg(unsigned idx) const; // Get reg mask of ABI return registers - regMaskTP GetABIReturnRegs(); + regMaskTP GetABIReturnRegs() const; }; class TailCallSiteInfo @@ -3918,7 +3923,6 @@ struct GenTreeCall final : public GenTree #if FEATURE_MULTIREG_RET // State required to support multi-reg returning call nodes. - // For now it is enabled only for x64 unix. // // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns. ReturnTypeDesc gtReturnTypeDesc; @@ -3940,12 +3944,8 @@ struct GenTreeCall final : public GenTree // Returns // Type descriptor of the value returned by call // - // Note: - // Right now implemented only for x64 unix and yet to be - // implemented for other multi-reg target arch (Arm64/Arm32/x86). - // // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns. - ReturnTypeDesc* GetReturnTypeDesc() + const ReturnTypeDesc* GetReturnTypeDesc() const { #if FEATURE_MULTIREG_RET return >ReturnTypeDesc; @@ -3954,6 +3954,27 @@ struct GenTreeCall final : public GenTree #endif } + void InitializeLongReturnType() + { +#if FEATURE_MULTIREG_RET + gtReturnTypeDesc.InitializeLongReturnType(); +#endif + } + + void InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd) + { +#if FEATURE_MULTIREG_RET + gtReturnTypeDesc.InitializeStructReturnType(comp, retClsHnd); +#endif + } + + void ResetReturnType() + { +#if FEATURE_MULTIREG_RET + gtReturnTypeDesc.Reset(); +#endif + } + //--------------------------------------------------------------------------- // GetRegNumByIdx: get ith return register allocated to this call node. // @@ -4220,18 +4241,29 @@ struct GenTreeCall final : public GenTree // bool HasMultiRegRetVal() const { -#if defined(TARGET_X86) - return varTypeIsLong(gtType); -#elif FEATURE_MULTIREG_RET && defined(TARGET_ARM) - return varTypeIsLong(gtType) || (varTypeIsStruct(gtType) && !HasRetBufArg()); +#ifdef FEATURE_MULTIREG_RET +#if defined(TARGET_X86) || defined(TARGET_ARM) + if (varTypeIsLong(gtType)) + { + return true; + } #elif defined(FEATURE_HFA) && defined(TARGET_ARM64) // SIMD types are returned in vector regs on ARM64. - return (gtType == TYP_STRUCT) && !HasRetBufArg(); -#elif FEATURE_MULTIREG_RET - return varTypeIsStruct(gtType) && !HasRetBufArg(); -#else + if (varTypeIsSIMD(gtType)) + { + return false; + } +#endif // FEATURE_HFA && TARGET_ARM64 + + if (!varTypeIsStruct(gtType) || HasRetBufArg()) + { + return false; + } + // Now it is a struct that is returned in registers. + return GetReturnTypeDesc()->IsMultiRegRetType(); +#else // !FEATURE_MULTIREG_RET return false; -#endif +#endif // !FEATURE_MULTIREG_RET } // Returns true if VM has flagged this method as CORINFO_FLG_PINVOKE. @@ -6765,30 +6797,79 @@ inline bool GenTree::IsIntegralConstVector(ssize_t constVal) assert(gtGetOp2IfPresent() == nullptr); return true; } -#endif +#endif // FEATURE_SIMD - return false; -} +#ifdef FEATURE_HW_INTRINSICS + if (gtOper == GT_HWINTRINSIC) + { + GenTreeHWIntrinsic* node = AsHWIntrinsic(); -inline bool GenTree::IsBoxedValue() -{ - assert(gtOper != GT_BOX || AsBox()->BoxOp() != nullptr); - return (gtOper == GT_BOX) && (gtFlags & GTF_BOX_VALUE); + if (!varTypeIsIntegral(node->gtSIMDBaseType)) + { + // Can't be an integral constant + return false; + } + + GenTree* op1 = gtGetOp1(); + GenTree* op2 = gtGetOp2(); + + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + + if (op1 == nullptr) + { + assert(op2 == nullptr); + + if (constVal == 0) + { +#if defined(TARGET_XARCH) + return (intrinsicId == NI_Vector128_get_Zero) || (intrinsicId == NI_Vector256_get_Zero); +#elif defined(TARGET_ARM64) + return (intrinsicId == NI_Vector64_get_Zero) || (intrinsicId == NI_Vector128_get_Zero); +#endif // !TARGET_XARCH && !TARGET_ARM64 + } + } + else if ((op2 == nullptr) && !op1->OperIsList()) + { + if (op1->IsIntegralConst(constVal)) + { +#if defined(TARGET_XARCH) + return (intrinsicId == NI_Vector128_Create) || (intrinsicId == NI_Vector256_Create); +#elif defined(TARGET_ARM64) + return (intrinsicId == NI_Vector64_Create) || (intrinsicId == NI_Vector128_Create); +#endif // !TARGET_XARCH && !TARGET_ARM64 + } + } + } +#endif // FEATURE_HW_INTRINSICS + + return false; } -inline bool GenTree::IsSIMDEqualityOrInequality() const +//------------------------------------------------------------------- +// IsSIMDZero: returns true if this this is a SIMD vector +// with all its elements equal to zero. +// +// Returns: +// True if this represents an integral const SIMD vector. +// +inline bool GenTree::IsSIMDZero() { #ifdef FEATURE_SIMD - if (gtOper == GT_SIMD) + if ((gtOper == GT_SIMD) && (AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicInit)) { - SIMDIntrinsicID id = AsSIMD()->gtSIMDIntrinsicID; - return (id == SIMDIntrinsicOpEquality) || (id == SIMDIntrinsicOpInEquality); + return (gtGetOp1()->IsIntegralConst(0) || gtGetOp1()->IsFPZero()); } #endif return false; } +inline bool GenTree::IsBoxedValue() +{ + assert(gtOper != GT_BOX || AsBox()->BoxOp() != nullptr); + return (gtOper == GT_BOX) && (gtFlags & GTF_BOX_VALUE); +} + inline GenTree* GenTree::MoveNext() { assert(OperIsAnyList()); @@ -7255,6 +7336,61 @@ inline var_types GenTree::GetRegTypeByIndex(int regIndex) return TYP_UNDEF; } +//----------------------------------------------------------------------------------- +// GetRegSpillFlagByIdx: Get a specific register's spill flags, based on regIndex, +// for this multi-reg node. +// +// Arguments: +// regIndex - which register's spill flags to return +// +// Return Value: +// The spill flags (GTF_SPILL GTF_SPILLED) for this register. +// +// Notes: +// This must be a multireg node and 'regIndex' must be a valid index for this node. +// This method returns the GTF "equivalent" flags based on the packed flags on the multireg node. +// +inline unsigned int GenTree::GetRegSpillFlagByIdx(int regIndex) const +{ +#if FEATURE_MULTIREG_RET + if (IsMultiRegCall()) + { + return AsCall()->AsCall()->GetRegSpillFlagByIdx(regIndex); + } + +#if FEATURE_ARG_SPLIT + if (OperIsPutArgSplit()) + { + return AsPutArgSplit()->GetRegSpillFlagByIdx(regIndex); + } +#endif +#if !defined(TARGET_64BIT) + if (OperIsMultiRegOp()) + { + return AsMultiRegOp()->GetRegSpillFlagByIdx(regIndex); + } +#endif + +#endif // FEATURE_MULTIREG_RET + +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + if (OperIs(GT_HWINTRINSIC)) + { + // At this time, the only multi-reg HW intrinsics all return the type of their + // arguments. If this changes, we will need a way to record or determine this. + assert(TypeGet() == TYP_STRUCT); + return gtGetOp1()->TypeGet(); + } +#endif + if (OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR)) + { + return AsLclVar()->GetRegSpillFlagByIdx(regIndex); + } + + assert(!"Invalid node type for GetRegSpillFlagByIdx"); + return TYP_UNDEF; +} + //------------------------------------------------------------------------- // IsCopyOrReload: whether this is a GT_COPY or GT_RELOAD node. // diff --git a/src/coreclr/src/jit/hwintrinsic.cpp b/src/coreclr/src/jit/hwintrinsic.cpp index 674b7f9946e0d..16332b859894b 100644 --- a/src/coreclr/src/jit/hwintrinsic.cpp +++ b/src/coreclr/src/jit/hwintrinsic.cpp @@ -89,50 +89,6 @@ var_types Compiler::getBaseTypeFromArgIfNeeded(NamedIntrinsic intrinsic, return baseType; } -//------------------------------------------------------------------------ -// impUnsupportedHWIntrinsic: returns a node for an unsupported HWIntrinsic -// -// Arguments: -// helper - JIT helper ID for the exception to be thrown -// method - method handle of the intrinsic function. -// sig - signature of the intrinsic call -// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false -// -// Return Value: -// a gtNewMustThrowException if mustExpand is true; otherwise, nullptr -// -GenTree* Compiler::impUnsupportedHWIntrinsic(unsigned helper, - CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig, - bool mustExpand) -{ - // We've hit some error case and may need to return a node for the given error. - // - // When `mustExpand=false`, we are attempting to inline the intrinsic directly into another method. In this - // scenario, we need to return `nullptr` so that a GT_CALL to the intrinsic is emitted instead. This is to - // ensure that everything continues to behave correctly when optimizations are enabled (e.g. things like the - // inliner may expect the node we return to have a certain signature, and the `MustThrowException` node won't - // match that). - // - // When `mustExpand=true`, we are in a GT_CALL to the intrinsic and are attempting to JIT it. This will generally - // be in response to an indirect call (e.g. done via reflection) or in response to an earlier attempt returning - // `nullptr` (under `mustExpand=false`). In that scenario, we are safe to return the `MustThrowException` node. - - if (mustExpand) - { - for (unsigned i = 0; i < sig->numArgs; i++) - { - impPopStack(); - } - - return gtNewMustThrowException(helper, JITtype2varType(sig->retType), sig->retTypeClass); - } - else - { - return nullptr; - } -} - CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType) { if (simdType == TYP_SIMD16) @@ -292,16 +248,19 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleForHWSIMD(var_types simdType, va // lookupId: Gets the NamedIntrinsic for a given method name and InstructionSet // // Arguments: +// comp -- The compiler +// sig -- The signature of the intrinsic // className -- The name of the class associated with the HWIntrinsic to lookup // methodName -- The name of the method associated with the HWIntrinsic to lookup // enclosingClassName -- The name of the enclosing class of X64 classes // // Return Value: // The NamedIntrinsic associated with methodName and isa -NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, - const char* className, - const char* methodName, - const char* enclosingClassName) +NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, + CORINFO_SIG_INFO* sig, + const char* className, + const char* methodName, + const char* enclosingClassName) { // TODO-Throughput: replace sequential search by binary search CORINFO_InstructionSet isa = lookupIsa(className, enclosingClassName); @@ -324,14 +283,23 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, for (int i = 0; i < (NI_HW_INTRINSIC_END - NI_HW_INTRINSIC_START - 1); i++) { + const HWIntrinsicInfo& intrinsicInfo = hwIntrinsicInfoArray[i]; + if (isa != hwIntrinsicInfoArray[i].isa) { continue; } - if (strcmp(methodName, hwIntrinsicInfoArray[i].name) == 0) + int numArgs = static_cast(intrinsicInfo.numArgs); + + if ((numArgs != -1) && (sig->numArgs != static_cast(intrinsicInfo.numArgs))) { - return hwIntrinsicInfoArray[i].id; + continue; + } + + if (strcmp(methodName, intrinsicInfo.name) == 0) + { + return intrinsicInfo.id; } } @@ -514,11 +482,14 @@ bool HWIntrinsicInfo::isImmOp(NamedIntrinsic id, const GenTree* op) GenTree* Compiler::getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass, bool expectAddr) { GenTree* arg = nullptr; - if (argType == TYP_STRUCT) + if (varTypeIsStruct(argType)) { - unsigned int argSizeBytes; - var_types base = getBaseTypeAndSizeOfSIMDType(argClass, &argSizeBytes); - argType = getSIMDTypeForSize(argSizeBytes); + if (!varTypeIsSIMD(argType)) + { + unsigned int argSizeBytes; + var_types base = getBaseTypeAndSizeOfSIMDType(argClass, &argSizeBytes); + argType = getSIMDTypeForSize(argSizeBytes); + } assert(varTypeIsSIMD(argType)); arg = impSIMDPopStack(argType, expectAddr); assert(varTypeIsSIMD(arg->TypeGet())); @@ -540,13 +511,15 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE // intrinsic -- intrinsic ID // immOp -- the immediate operand of the intrinsic // mustExpand -- true if the compiler is compiling the fallback(GT_CALL) of this intrinsics -// immUpperBound -- upper bound for a value of the immediate operand (for a non-full-range imm-intrinsic) +// immLowerBound -- lower incl. bound for a value of the immediate operand (for a non-full-range imm-intrinsic) +// immUpperBound -- upper incl. bound for a value of the immediate operand (for a non-full-range imm-intrinsic) // // Return Value: // add a GT_HW_INTRINSIC_CHK node for non-full-range imm-intrinsic, which would throw ArgumentOutOfRangeException // when the imm-argument is not in the valid range // -GenTree* Compiler::addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* immOp, bool mustExpand, int immUpperBound) +GenTree* Compiler::addRangeCheckIfNeeded( + NamedIntrinsic intrinsic, GenTree* immOp, bool mustExpand, int immLowerBound, int immUpperBound) { assert(immOp != nullptr); // Full-range imm-intrinsics do not need the range-check @@ -560,19 +533,37 @@ GenTree* Compiler::addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* immO ) { assert(!immOp->IsCnsIntOrI()); - GenTree* upperBoundNode = gtNewIconNode(immUpperBound, TYP_INT); - GenTree* index = nullptr; - if ((immOp->gtFlags & GTF_SIDE_EFFECT) != 0) - { - index = fgInsertCommaFormTemp(&immOp); - } - else + assert(varTypeIsUnsigned(immOp)); + + // Bounds check for value of an immediate operand + // (immLowerBound <= immOp) && (immOp <= immUpperBound) + // + // implemented as a single comparison in the form of + // + // if ((immOp - immLowerBound) >= (immUpperBound - immLowerBound + 1)) + // { + // throw new ArgumentOutOfRangeException(); + // } + // + // The value of (immUpperBound - immLowerBound + 1) is denoted as adjustedUpperBound. + + const ssize_t adjustedUpperBound = (ssize_t)immUpperBound - immLowerBound + 1; + GenTree* adjustedUpperBoundNode = gtNewIconNode(adjustedUpperBound, TYP_INT); + + GenTree* immOpDup = nullptr; + + immOp = impCloneExpr(immOp, &immOpDup, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone an immediate operand for immediate value bounds check")); + + if (immLowerBound != 0) { - index = gtCloneExpr(immOp); + immOpDup = gtNewOperNode(GT_SUB, TYP_INT, immOpDup, gtNewIconNode(immLowerBound, TYP_INT)); } + GenTreeBoundsChk* hwIntrinsicChk = new (this, GT_HW_INTRINSIC_CHK) - GenTreeBoundsChk(GT_HW_INTRINSIC_CHK, TYP_VOID, index, upperBoundNode, SCK_RNGCHK_FAIL); + GenTreeBoundsChk(GT_HW_INTRINSIC_CHK, TYP_VOID, immOpDup, adjustedUpperBoundNode, SCK_RNGCHK_FAIL); hwIntrinsicChk->gtThrowKind = SCK_ARG_RNG_EXCPN; + return gtNewOperNode(GT_COMMA, immOp->TypeGet(), hwIntrinsicChk, immOp); } else @@ -615,6 +606,67 @@ static bool impIsTableDrivenHWIntrinsic(NamedIntrinsic intrinsicId, HWIntrinsicC !HWIntrinsicInfo::HasSpecialImport(intrinsicId); } +//------------------------------------------------------------------------ +// isSupportedBaseType +// +// Arguments: +// intrinsicId - HW intrinsic id +// baseType - Base type of the intrinsic. +// +// Return Value: +// returns true if the baseType is supported for given intrinsic. +// +static bool isSupportedBaseType(NamedIntrinsic intrinsic, var_types baseType) +{ + // We don't actually check the intrinsic outside of the false case as we expect + // the exposed managed signatures are either generic and support all types + // or they are explicit and support the type indicated. + if (varTypeIsArithmetic(baseType)) + { + return true; + } + +#ifdef TARGET_XARCH + assert((intrinsic == NI_Vector128_As) || (intrinsic == NI_Vector128_AsByte) || + (intrinsic == NI_Vector128_AsDouble) || (intrinsic == NI_Vector128_AsInt16) || + (intrinsic == NI_Vector128_AsInt32) || (intrinsic == NI_Vector128_AsInt64) || + (intrinsic == NI_Vector128_AsSByte) || (intrinsic == NI_Vector128_AsSingle) || + (intrinsic == NI_Vector128_AsUInt16) || (intrinsic == NI_Vector128_AsUInt32) || + (intrinsic == NI_Vector128_AsUInt64) || (intrinsic == NI_Vector128_get_AllBitsSet) || + (intrinsic == NI_Vector128_get_Count) || (intrinsic == NI_Vector128_get_Zero) || + (intrinsic == NI_Vector128_GetElement) || (intrinsic == NI_Vector128_WithElement) || + (intrinsic == NI_Vector128_ToScalar) || (intrinsic == NI_Vector128_ToVector256) || + (intrinsic == NI_Vector128_ToVector256Unsafe) || (intrinsic == NI_Vector256_As) || + (intrinsic == NI_Vector256_AsByte) || (intrinsic == NI_Vector256_AsDouble) || + (intrinsic == NI_Vector256_AsInt16) || (intrinsic == NI_Vector256_AsInt32) || + (intrinsic == NI_Vector256_AsInt64) || (intrinsic == NI_Vector256_AsSByte) || + (intrinsic == NI_Vector256_AsSingle) || (intrinsic == NI_Vector256_AsUInt16) || + (intrinsic == NI_Vector256_AsUInt32) || (intrinsic == NI_Vector256_AsUInt64) || + (intrinsic == NI_Vector256_get_AllBitsSet) || (intrinsic == NI_Vector256_get_Count) || + (intrinsic == NI_Vector256_get_Zero) || (intrinsic == NI_Vector256_GetElement) || + (intrinsic == NI_Vector256_WithElement) || (intrinsic == NI_Vector256_GetLower) || + (intrinsic == NI_Vector256_ToScalar)); +#else + assert((intrinsic == NI_Vector64_AsByte) || (intrinsic == NI_Vector64_AsInt16) || + (intrinsic == NI_Vector64_AsInt32) || (intrinsic == NI_Vector64_AsSByte) || + (intrinsic == NI_Vector64_AsSingle) || (intrinsic == NI_Vector64_AsUInt16) || + (intrinsic == NI_Vector64_AsUInt32) || (intrinsic == NI_Vector64_get_AllBitsSet) || + (intrinsic == NI_Vector64_get_Count) || (intrinsic == NI_Vector64_get_Zero) || + (intrinsic == NI_Vector64_GetElement) || (intrinsic == NI_Vector64_ToScalar) || + (intrinsic == NI_Vector64_ToVector128) || (intrinsic == NI_Vector64_ToVector128Unsafe) || + (intrinsic == NI_Vector128_As) || (intrinsic == NI_Vector128_AsByte) || + (intrinsic == NI_Vector128_AsDouble) || (intrinsic == NI_Vector128_AsInt16) || + (intrinsic == NI_Vector128_AsInt32) || (intrinsic == NI_Vector128_AsInt64) || + (intrinsic == NI_Vector128_AsSByte) || (intrinsic == NI_Vector128_AsSingle) || + (intrinsic == NI_Vector128_AsUInt16) || (intrinsic == NI_Vector128_AsUInt32) || + (intrinsic == NI_Vector128_AsUInt64) || (intrinsic == NI_Vector128_get_AllBitsSet) || + (intrinsic == NI_Vector128_get_Count) || (intrinsic == NI_Vector128_get_Zero) || + (intrinsic == NI_Vector128_GetElement) || (intrinsic == NI_Vector128_GetLower) || + (intrinsic == NI_Vector128_ToScalar)); +#endif + return false; +} + //------------------------------------------------------------------------ // impHWIntrinsic: Import a hardware intrinsic as a GT_HWINTRINSIC node if possible // @@ -646,9 +698,38 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &sizeBytes); retType = getSIMDTypeForSize(sizeBytes); assert(sizeBytes != 0); + + // We want to return early here for cases where retType was TYP_STRUCT as per method signature and + // rather than deferring the decision after getting the baseType of arg. + if (!isSupportedBaseType(intrinsic, baseType)) + { + return nullptr; + } + } + + baseType = getBaseTypeFromArgIfNeeded(intrinsic, clsHnd, sig, baseType); + + if (baseType == TYP_UNKNOWN) + { + if (category != HW_Category_Scalar) + { + unsigned int sizeBytes; + baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &sizeBytes); + assert((category == HW_Category_Special) || (sizeBytes != 0)); + } + else + { + baseType = retType; + } + } + + // Immediately return if the category is other than scalar/special and this is not a supported base type. + if ((category != HW_Category_Special) && (category != HW_Category_Scalar) && + !isSupportedBaseType(intrinsic, baseType)) + { + return nullptr; } - baseType = getBaseTypeFromArgIfNeeded(intrinsic, clsHnd, sig, baseType); unsigned simdSize = HWIntrinsicInfo::lookupSimdSize(this, intrinsic, sig); GenTree* immOp = nullptr; @@ -715,6 +796,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, var_types argType = TYP_UNKNOWN; CORINFO_CLASS_HANDLE argClass; + int immLowerBound = 0; int immUpperBound = 0; if (immOp != nullptr) @@ -722,11 +804,12 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, #if defined(TARGET_XARCH) immUpperBound = HWIntrinsicInfo::lookupImmUpperBound(intrinsic); #elif defined(TARGET_ARM64) - immUpperBound = HWIntrinsicInfo::lookupImmUpperBound(intrinsic, simdSize, baseType); + HWIntrinsicInfo::lookupImmBounds(intrinsic, simdSize, baseType, &immLowerBound, &immUpperBound); #endif } assert(numArgs >= 0); + if (!isScalar && ((HWIntrinsicInfo::lookupIns(intrinsic, baseType) == INS_invalid) || ((simdSize != 8) && (simdSize != 16) && (simdSize != 32)))) { @@ -774,7 +857,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); - op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immUpperBound); + op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); op1 = getArgForHWIntrinsic(argType, argClass); @@ -825,12 +908,12 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, #ifdef TARGET_ARM64 if (intrinsic == NI_AdvSimd_Insert) { - op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immUpperBound); + op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound); } else #endif { - op3 = addRangeCheckIfNeeded(intrinsic, op3, mustExpand, immUpperBound); + op3 = addRangeCheckIfNeeded(intrinsic, op3, mustExpand, immLowerBound, immUpperBound); } retNode = isScalar ? gtNewScalarHWIntrinsicNode(retType, op1, op2, op3, intrinsic) @@ -868,7 +951,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, return retNode; } - return impSpecialIntrinsic(intrinsic, clsHnd, method, sig); + return impSpecialIntrinsic(intrinsic, clsHnd, method, sig, baseType, retType, simdSize); } #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/src/jit/hwintrinsic.h b/src/coreclr/src/jit/hwintrinsic.h index b3c00f45d9809..34a92d858e43d 100644 --- a/src/coreclr/src/jit/hwintrinsic.h +++ b/src/coreclr/src/jit/hwintrinsic.h @@ -258,10 +258,11 @@ struct HWIntrinsicInfo static const HWIntrinsicInfo& lookup(NamedIntrinsic id); - static NamedIntrinsic lookupId(Compiler* comp, - const char* className, - const char* methodName, - const char* enclosingClassName); + static NamedIntrinsic lookupId(Compiler* comp, + CORINFO_SIG_INFO* sig, + const char* className, + const char* methodName, + const char* enclosingClassName); static CORINFO_InstructionSet lookupIsa(const char* className, const char* enclosingClassName); static unsigned lookupSimdSize(Compiler* comp, NamedIntrinsic id, CORINFO_SIG_INFO* sig); @@ -271,7 +272,8 @@ struct HWIntrinsicInfo #if defined(TARGET_XARCH) static int lookupImmUpperBound(NamedIntrinsic intrinsic); #elif defined(TARGET_ARM64) - static int lookupImmUpperBound(NamedIntrinsic intrinsic, int simdSize, var_types baseType); + static void lookupImmBounds( + NamedIntrinsic intrinsic, int simdSize, var_types baseType, int* lowerBound, int* upperBound); #else #error Unsupported platform #endif diff --git a/src/coreclr/src/jit/hwintrinsicarm64.cpp b/src/coreclr/src/jit/hwintrinsicarm64.cpp index 85c734d97bb31..dc7bbcab49f04 100644 --- a/src/coreclr/src/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsicarm64.cpp @@ -177,19 +177,24 @@ bool HWIntrinsicInfo::isScalarIsa(CORINFO_InstructionSet isa) } //------------------------------------------------------------------------ -// lookupImmUpperBound: Gets the upper bound for the imm-value of a given NamedIntrinsic +// lookupImmBounds: Gets the lower and upper bounds for the imm-value of a given NamedIntrinsic // // Arguments: // intrinsic -- NamedIntrinsic associated with the HWIntrinsic to lookup // simdType -- vector size // baseType -- base type of the Vector64/128 +// pImmLowerBound [OUT] - The lower incl. bound for a value of the intrinsic immediate operand +// pImmUpperBound [OUT] - The upper incl. bound for a value of the intrinsic immediate operand // -// Return Value: -// The upper bound for a value of the intrinsic immediate operand -int HWIntrinsicInfo::lookupImmUpperBound(NamedIntrinsic intrinsic, int simdSize, var_types baseType) +void HWIntrinsicInfo::lookupImmBounds( + NamedIntrinsic intrinsic, int simdSize, var_types baseType, int* pImmLowerBound, int* pImmUpperBound) { assert(HWIntrinsicInfo::lookupCategory(intrinsic) == HW_Category_IMM); + assert(pImmLowerBound != nullptr); + assert(pImmUpperBound != nullptr); + + int immLowerBound = 0; int immUpperBound = 0; if (HWIntrinsicInfo::HasFullRangeImm(intrinsic)) @@ -200,19 +205,83 @@ int HWIntrinsicInfo::lookupImmUpperBound(NamedIntrinsic intrinsic, int simdSize, { switch (intrinsic) { + case NI_AdvSimd_DuplicateSelectedScalarToVector64: + case NI_AdvSimd_DuplicateSelectedScalarToVector128: case NI_AdvSimd_Extract: case NI_AdvSimd_ExtractVector128: case NI_AdvSimd_ExtractVector64: case NI_AdvSimd_Insert: - immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType); + case NI_AdvSimd_Arm64_DuplicateSelectedScalarToVector128: + case NI_Vector64_GetElement: + case NI_Vector128_GetElement: + immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1; + break; + + case NI_AdvSimd_ShiftLeftLogical: + case NI_AdvSimd_ShiftLeftLogicalSaturate: + case NI_AdvSimd_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsigned: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_ShiftLeftLogicalScalar: + case NI_AdvSimd_ShiftLeftLogicalWideningLower: + case NI_AdvSimd_ShiftLeftLogicalWideningUpper: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateUnsignedScalar: + // The left shift amount is in the range 0 to the element width in bits minus 1. + immUpperBound = BITS_PER_BYTE * genTypeSize(baseType) - 1; break; + case NI_AdvSimd_ShiftRightArithmetic: + case NI_AdvSimd_ShiftRightArithmeticAdd: + case NI_AdvSimd_ShiftRightArithmeticAddScalar: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightArithmeticRounded: + case NI_AdvSimd_ShiftRightArithmeticRoundedAdd: + case NI_AdvSimd_ShiftRightArithmeticRoundedAddScalar: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedScalar: + case NI_AdvSimd_ShiftRightArithmeticScalar: + case NI_AdvSimd_ShiftRightLogical: + case NI_AdvSimd_ShiftRightLogicalAdd: + case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalNarrowingUpper: + case NI_AdvSimd_ShiftRightLogicalRounded: + case NI_AdvSimd_ShiftRightLogicalRoundedAdd: + case NI_AdvSimd_ShiftRightLogicalRoundedAddScalar: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedScalar: + case NI_AdvSimd_ShiftRightLogicalScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalRoundedNarrowingSaturateScalar: + // The right shift amount, in the range 1 to the element width in bits. + immLowerBound = 1; + immUpperBound = BITS_PER_BYTE * genTypeSize(baseType); + break; default: unreached(); } } - return immUpperBound; + assert(immLowerBound <= immUpperBound); + + *pImmLowerBound = immLowerBound; + *pImmUpperBound = immUpperBound; } //------------------------------------------------------------------------ @@ -231,7 +300,12 @@ bool HWIntrinsicInfo::isInImmRange(NamedIntrinsic id, int ival, int simdSize, va { assert(HWIntrinsicInfo::lookupCategory(id) == HW_Category_IMM); - return ival <= lookupImmUpperBound(id, simdSize, baseType) && ival >= 0; + int immLowerBound = 0; + int immUpperBound = 0; + + lookupImmBounds(id, simdSize, baseType, &immLowerBound, &immUpperBound); + + return (immLowerBound <= ival) && (ival <= immUpperBound); } //------------------------------------------------------------------------ @@ -257,7 +331,9 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT // intrinsic -- id of the intrinsic function. // clsHnd -- class handle containing the intrinsic function. // method -- method handle of the intrinsic function. -// sig -- signature of the intrinsic call +// sig -- signature of the intrinsic call. +// baseType -- generic argument of the intrinsic. +// retType -- return type of the intrinsic. // // Return Value: // The GT_HWINTRINSIC node, or nullptr if not a supported intrinsic @@ -265,52 +341,16 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig) + CORINFO_SIG_INFO* sig, + var_types baseType, + var_types retType, + unsigned simdSize) { HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); int numArgs = sig->numArgs; - var_types retType = JITtype2varType(sig->retType); - var_types baseType = TYP_UNKNOWN; - - if ((retType == TYP_STRUCT) && featureSIMD) - { - unsigned int sizeBytes; - baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &sizeBytes); - retType = getSIMDTypeForSize(sizeBytes); - assert(sizeBytes != 0); - - if (!varTypeIsArithmetic(baseType)) - { - assert((intrinsic == NI_Vector64_AsByte) || (intrinsic == NI_Vector128_As) || - (intrinsic == NI_Vector64_get_Zero) || (intrinsic == NI_Vector64_get_AllBitsSet) || - (intrinsic == NI_Vector128_get_Zero) || (intrinsic == NI_Vector128_get_AllBitsSet)); - return nullptr; - } - } - - baseType = getBaseTypeFromArgIfNeeded(intrinsic, clsHnd, sig, baseType); - - if (baseType == TYP_UNKNOWN) - { - if (category != HW_Category_Scalar) - { - unsigned int sizeBytes; - baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &sizeBytes); - assert(sizeBytes != 0); - } - else - { - baseType = retType; - } - } - - if (!varTypeIsArithmetic(baseType)) - { - return nullptr; - } - unsigned simdSize = HWIntrinsicInfo::lookupSimdSize(this, intrinsic, sig); assert(numArgs >= 0); + assert(varTypeIsArithmetic(baseType)); GenTree* retNode = nullptr; GenTree* op1 = nullptr; @@ -354,6 +394,47 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, assert(retNode->gtType == getSIMDTypeForSize(getSIMDTypeSizeInBytes(sig->retTypeSigClass))); break; } + + case NI_Vector64_Create: + case NI_Vector128_Create: + { + // We shouldn't handle this as an intrinsic if the + // respective ISAs have been disabled by the user. + + if (!compExactlyDependsOn(InstructionSet_AdvSimd)) + { + break; + } + + if (sig->numArgs == 1) + { + op1 = impPopStack().val; + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize); + } + else if (sig->numArgs == 2) + { + op2 = impPopStack().val; + op1 = impPopStack().val; + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, baseType, simdSize); + } + else + { + assert(sig->numArgs >= 3); + + GenTreeArgList* tmp = nullptr; + + for (unsigned i = 0; i < sig->numArgs; i++) + { + tmp = gtNewArgList(impPopStack().val); + tmp->gtOp2 = op1; + op1 = tmp; + } + + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize); + } + break; + } + case NI_Vector64_get_Count: case NI_Vector128_get_Count: { diff --git a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp index fafbf06489728..179c1807e118a 100644 --- a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp @@ -47,15 +47,16 @@ CodeGen::HWIntrinsicImmOpHelper::HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTre nonConstImmReg = REG_NA; immValue = (int)immOp->AsIntCon()->IconValue(); - immUpperBound = immValue + 1; + immLowerBound = immValue; + immUpperBound = immValue; } else { - nonConstImmReg = immOp->GetRegNum(); + HWIntrinsicInfo::lookupImmBounds(intrin->gtHWIntrinsicId, intrin->gtSIMDSize, intrin->gtSIMDBaseType, + &immLowerBound, &immUpperBound); - immValue = 0; - immUpperBound = - HWIntrinsicInfo::lookupImmUpperBound(intrin->gtHWIntrinsicId, intrin->gtSIMDSize, intrin->gtSIMDBaseType); + nonConstImmReg = immOp->GetRegNum(); + immValue = immLowerBound; if (TestImmOpZeroOrOne()) { @@ -110,6 +111,15 @@ void CodeGen::HWIntrinsicImmOpHelper::EmitBegin() GetEmitter()->emitIns_R_L(INS_adr, EA_8BYTE, beginLabel, branchTargetReg); GetEmitter()->emitIns_R_R_R_I(INS_add, EA_8BYTE, branchTargetReg, branchTargetReg, nonConstImmReg, 3, INS_OPTS_LSL); + + // If the lower bound is non zero we need to adjust the branch target value by subtracting + // (immLowerBound << 3). + if (immLowerBound != 0) + { + GetEmitter()->emitIns_R_R_I(INS_sub, EA_8BYTE, branchTargetReg, branchTargetReg, + ((ssize_t)immLowerBound << 3)); + } + GetEmitter()->emitIns_R(INS_br, EA_8BYTE, branchTargetReg); } @@ -136,7 +146,7 @@ void CodeGen::HWIntrinsicImmOpHelper::EmitCaseEnd() if (NonConstImmOp()) { - const bool isLastCase = (immValue + 1 == immUpperBound); + const bool isLastCase = (immValue == immUpperBound); if (isLastCase) { @@ -360,6 +370,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_Aes_PolynomialMultiplyWideningLower: + ins = INS_pmull; + opt = INS_OPTS_1D; + break; + default: ins = HWIntrinsicInfo::lookupIns(intrin.id, intrin.baseType); break; @@ -397,6 +412,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case NI_Crc32_ComputeCrc32C: case NI_Crc32_Arm64_ComputeCrc32: case NI_Crc32_Arm64_ComputeCrc32C: + case NI_Aes_PolynomialMultiplyWideningLower: GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); break; @@ -430,6 +446,35 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R(ins, emitSize, op2Reg, op1Reg, opt); break; + case NI_AdvSimd_DuplicateSelectedScalarToVector64: + case NI_AdvSimd_DuplicateSelectedScalarToVector128: + case NI_AdvSimd_Arm64_DuplicateSelectedScalarToVector128: + { + HWIntrinsicImmOpHelper helper(this, intrin.op2, node); + + // Prior to codegen, the emitSize is based on node->gtSIMDSize which + // tracks the size of the first operand and is used to tell if the index + // is in range. However, when actually emitting it needs to be the size + // of the return and the size of the operand is interpreted based on the + // index value. + + assert( + GetEmitter()->isValidVectorIndex(emitSize, GetEmitter()->optGetElemsize(opt), helper.ImmValue())); + + emitSize = emitActualTypeSize(node->gtType); + opt = genGetSimdInsOpt(emitSize, intrin.baseType); + + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + const int elementIndex = helper.ImmValue(); + + assert(opt != INS_OPTS_NONE); + GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op1Reg, elementIndex, opt); + } + + break; + } + case NI_AdvSimd_Extract: { HWIntrinsicImmOpHelper helper(this, intrin.op2, node); @@ -554,31 +599,162 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_I(ins, emitSize, targetReg, 0, INS_OPTS_4S); break; - case NI_Vector64_Create: - case NI_Vector128_Create: - if (intrin.op1->isContainedFltOrDblImmed()) - { - const double dataValue = intrin.op1->AsDblCon()->gtDconVal; - GetEmitter()->emitIns_R_F(INS_fmov, emitSize, targetReg, dataValue, opt); - } - else if (varTypeIsFloating(intrin.baseType)) - { - GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op1Reg, 0, opt); - } - else + case NI_AdvSimd_DuplicateToVector64: + case NI_AdvSimd_DuplicateToVector128: + case NI_AdvSimd_Arm64_DuplicateToVector64: + case NI_AdvSimd_Arm64_DuplicateToVector128: + { + if (varTypeIsFloating(intrin.baseType)) { - if (intrin.op1->isContainedIntOrIImmed()) + if (intrin.op1->isContainedFltOrDblImmed()) { - const ssize_t dataValue = intrin.op1->AsIntCon()->gtIconVal; - GetEmitter()->emitIns_R_I(INS_movi, emitSize, targetReg, dataValue, opt); + const double dataValue = intrin.op1->AsDblCon()->gtDconVal; + GetEmitter()->emitIns_R_F(INS_fmov, emitSize, targetReg, dataValue, opt); } - else + else if (intrin.id == NI_AdvSimd_Arm64_DuplicateToVector64) { + assert(intrin.baseType == TYP_DOUBLE); GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); } + else + { + GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op1Reg, 0, opt); + } + } + else if (intrin.op1->isContainedIntOrIImmed()) + { + const ssize_t dataValue = intrin.op1->AsIntCon()->gtIconVal; + GetEmitter()->emitIns_R_I(INS_movi, emitSize, targetReg, dataValue, opt); + } + else + { + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); } + } + break; + + case NI_Vector64_ToVector128: + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg); break; + case NI_Vector64_ToVector128Unsafe: + case NI_Vector128_GetLower: + if (op1Reg != targetReg) + { + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg); + } + break; + + case NI_Vector64_GetElement: + case NI_Vector128_GetElement: + case NI_Vector64_ToScalar: + case NI_Vector128_ToScalar: + { + ssize_t indexValue = 0; + if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement)) + { + assert(intrin.op2->IsCnsIntOrI()); + indexValue = intrin.op2->AsIntCon()->gtIconVal; + } + + // no-op if vector is float/double, targetReg == op1Reg and fetching for 0th index. + if ((varTypeIsFloating(intrin.baseType) && (targetReg == op1Reg) && (indexValue == 0))) + { + break; + } + + GetEmitter()->emitIns_R_R_I(ins, emitTypeSize(intrin.baseType), targetReg, op1Reg, indexValue, + INS_OPTS_NONE); + } + break; + + case NI_AdvSimd_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_ShiftLeftLogicalScalar: + case NI_AdvSimd_ShiftRightArithmeticRoundedScalar: + case NI_AdvSimd_ShiftRightArithmeticScalar: + case NI_AdvSimd_ShiftRightLogicalRoundedScalar: + case NI_AdvSimd_ShiftRightLogicalScalar: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalRoundedNarrowingSaturateScalar: + opt = INS_OPTS_NONE; + emitSize = emitTypeSize(intrin.baseType); + __fallthrough; + + case NI_AdvSimd_ShiftLeftLogical: + case NI_AdvSimd_ShiftLeftLogicalSaturate: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsigned: + case NI_AdvSimd_ShiftLeftLogicalWideningLower: + case NI_AdvSimd_ShiftLeftLogicalWideningUpper: + case NI_AdvSimd_ShiftRightArithmetic: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticRounded: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightLogical: + case NI_AdvSimd_ShiftRightLogicalNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalRounded: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateLower: + { + HWIntrinsicImmOpHelper helper(this, intrin.op2, node); + + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + const int shiftAmount = helper.ImmValue(); + + GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op1Reg, shiftAmount, opt); + } + } + break; + + case NI_AdvSimd_ShiftRightArithmeticAddScalar: + case NI_AdvSimd_ShiftRightArithmeticRoundedAddScalar: + case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalRoundedAddScalar: + opt = INS_OPTS_NONE; + emitSize = emitTypeSize(intrin.baseType); + __fallthrough; + + case NI_AdvSimd_ShiftRightArithmeticAdd: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedAdd: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalAdd: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalNarrowingUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedAdd: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingUpper: + { + assert(isRMW); + + if (targetReg != op1Reg) + { + GetEmitter()->emitIns_R_R(INS_mov, emitTypeSize(node), targetReg, op1Reg); + } + + HWIntrinsicImmOpHelper helper(this, intrin.op3, node); + + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + const int shiftAmount = helper.ImmValue(); + + GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op2Reg, shiftAmount, opt); + } + } + break; + default: unreached(); } diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h index bd192bd217bfb..be8a0d552da75 100644 --- a/src/coreclr/src/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h @@ -12,297 +12,393 @@ #ifdef FEATURE_HW_INTRINSICS // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector64 Intrinsics -HARDWARE_INTRINSIC(Vector64, AsByte, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, AsInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, AsInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, AsSByte, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, AsSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, AsUInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, AsUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, Create, 8, 1, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_mov, INS_mov, INS_dup, INS_dup}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector64, get_Count, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, AsByte, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsSByte, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsUInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, Create, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, get_Count, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, GetElement, 8, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_IMM, HW_Flag_NoJmpTableIMM|HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, op_Equality, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, op_Inequality, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, ToScalar, 8, 1, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ToVector128, 8, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, ToVector128Unsafe, 8, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector128 Intrinsics -HARDWARE_INTRINSIC(Vector128, As, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, Create, 16, 1, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, As, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_IMM, HW_Flag_NoJmpTableIMM|HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, GetLower, 16, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, op_Equality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, op_Inequality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AdvSimd Intrinsics -HARDWARE_INTRINSIC(AdvSimd, Abs, -1, 1, {INS_abs, INS_invalid, INS_abs, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AbsScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_fabs}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThan, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThanOrEqual, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThan, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThanOrEqual, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifference, -1, 2, {INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_invalid, INS_invalid, INS_fabd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceAdd, -1, 3, {INS_saba, INS_uaba, INS_saba, INS_uaba, INS_saba, INS_uaba, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLower, 8, 2, {INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLowerAndAdd, 8, 3, {INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpper, 16, 2, {INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpperAndAdd, 16, 3, {INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, Add, -1, 2, {INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_fadd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddPairwise, 8, 2, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_invalid, INS_invalid, INS_faddp, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWidening, -1, 1, {INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAdd, -1, 2, {INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAddScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AddReturningHighNarrowLower, 8, 2, {INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddReturningHighNarrowUpper, 16, 3, {INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AddReturningRoundedHighNarrowLower, 8, 2, {INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddReturningRoundedHighNarrowUpper, 16, 3, {INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AddSaturate, -1, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_add, INS_add, INS_fadd, INS_fadd}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddWideningLower, 8, 2, {INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddw, INS_uaddw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, AddWideningUpper, 16, 2, {INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddw2, INS_uaddw2, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, And, -1, 2, {INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, -1, 2, {INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, DivideScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Extract, -1, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, ExtractAndNarrowHigh, 16, 2, {INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ExtractAndNarrowLow, 8, 1, {INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ExtractVector64, 8, 3, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_invalid, INS_invalid, INS_ext, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, ExtractVector128, 16, 3, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedAddHalving, -1, 2, {INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, FusedAddRoundedHalving, -1, 2, {INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAdd, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmadd, INS_fmadd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddNegatedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmadd, INS_fnmadd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtract, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmsub, INS_fmsub}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractNegatedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmsub, INS_fnmsub}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedSubtractHalving, -1, 2, {INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Insert, -1, 3, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, LeadingSignCount, -1, 1, {INS_cls, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LeadingZeroCount, -1, 1, {INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LoadVector64, 8, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LoadVector128, 16, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Max, -1, 2, {INS_smax, INS_umax, INS_smax, INS_umax, INS_smax, INS_umax, INS_invalid, INS_invalid, INS_fmax, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MaxNumber, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MaxNumberScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_fmaxnm}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MaxPairwise, 8, 2, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Min, -1, 2, {INS_smin, INS_umin, INS_smin, INS_umin, INS_smin, INS_umin, INS_invalid, INS_invalid, INS_fmin, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MinNumber, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MinNumberScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_fminnm}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MinPairwise, 8, 2, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Multiply, -1, 2, {INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_fmul}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyAdd, -1, 3, {INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplySubtract, -1, 3, {INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLower, 8, 2, {INS_smull, INS_umull, INS_smull, INS_umull, INS_smull, INS_umull, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndAdd, 8, 3, {INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndSubtract, 8, 3, {INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpper, 16, 2, {INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndAdd, 16, 3, {INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndSubtract, 16, 3, {INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, Negate, -1, 1, {INS_neg, INS_invalid, INS_neg, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, NegateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_fneg}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Not, -1, 1, {INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Or, -1, 2, {INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, OrNot, -1, 2, {INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiply, -1, 2, {INS_pmul, INS_pmul, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, PopCount, -1, 1, {INS_cnt, INS_cnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalEstimate, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urecpe, INS_invalid, INS_invalid, INS_frecpe, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootEstimate, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursqrte, INS_invalid, INS_invalid, INS_frsqrte, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootStep, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalStep, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, SqrtScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Store, -1, 2, {INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1}, HW_Category_MemoryStore, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, 2, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractReturningHighNarrowLower, 8, 2, {INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractReturningHighNarrowUpper, 16, 3, {INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, SubtractReturningRoundedHighNarrowLower, 8, 2, {INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractReturningRoundedHighNarrowUpper, 16, 3, {INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, SubtractSaturate, -1, 2, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractWideningLower, 8, 2, {INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubw, INS_usubw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, SubtractWideningUpper, 16, 2, {INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubw2, INS_usubw2, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, VectorTableLookup, 8, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, VectorTableLookupExtension, 8, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, Xor, -1, 2, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, Abs, -1, 1, {INS_abs, INS_invalid, INS_abs, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AbsScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_fabs}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThan, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThanOrEqual, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThan, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThanOrEqual, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifference, -1, 2, {INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_invalid, INS_invalid, INS_fabd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceAdd, -1, 3, {INS_saba, INS_uaba, INS_saba, INS_uaba, INS_saba, INS_uaba, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLower, 8, 2, {INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLowerAndAdd, 8, 3, {INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpper, 16, 2, {INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpperAndAdd, 16, 3, {INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, Add, -1, 2, {INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_fadd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddHighNarrowingLower, 8, 2, {INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddHighNarrowingUpper, 16, 3, {INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AddPairwise, 8, 2, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_invalid, INS_invalid, INS_faddp, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWidening, -1, 1, {INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAdd, -1, 2, {INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAddScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AddRoundedHighNarrowingLower, 8, 2, {INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddRoundedHighNarrowingUpper, 16, 3, {INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AddSaturate, -1, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_add, INS_add, INS_fadd, INS_fadd}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddWideningLower, 8, 2, {INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddw, INS_uaddw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, AddWideningUpper, 16, 2, {INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddw2, INS_uaddw2, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, And, -1, 2, {INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, -1, 2, {INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, DivideScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, DuplicateSelectedScalarToVector64, -1, 2, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, DuplicateSelectedScalarToVector128, -1, 2, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, DuplicateToVector64, 8, 1, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, DuplicateToVector128, 16, 1, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Extract, -1, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingUpper, 16, 2, {INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingLower, 8, 1, {INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ExtractVector64, 8, 3, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_invalid, INS_invalid, INS_ext, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ExtractVector128, 16, 3, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Floor, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_frintm}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, FusedAddHalving, -1, 2, {INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, FusedAddRoundedHalving, -1, 2, {INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAdd, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmadd, INS_fmadd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddNegatedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmadd, INS_fnmadd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtract, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmsub, INS_fmsub}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractNegatedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmsub, INS_fnmsub}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedSubtractHalving, -1, 2, {INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Insert, -1, 3, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, LeadingSignCount, -1, 1, {INS_cls, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, LeadingZeroCount, -1, 1, {INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, LoadVector64, 8, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, LoadVector128, 16, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Max, -1, 2, {INS_smax, INS_umax, INS_smax, INS_umax, INS_smax, INS_umax, INS_invalid, INS_invalid, INS_fmax, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MaxNumber, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MaxNumberScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_fmaxnm}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MaxPairwise, 8, 2, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Min, -1, 2, {INS_smin, INS_umin, INS_smin, INS_umin, INS_smin, INS_umin, INS_invalid, INS_invalid, INS_fmin, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MinNumber, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MinNumberScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_fminnm}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MinPairwise, 8, 2, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Multiply, -1, 2, {INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_fmul}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyAdd, -1, 3, {INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplySubtract, -1, 3, {INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLower, 8, 2, {INS_smull, INS_umull, INS_smull, INS_umull, INS_smull, INS_umull, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndAdd, 8, 3, {INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndSubtract, 8, 3, {INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpper, 16, 2, {INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndAdd, 16, 3, {INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndSubtract, 16, 3, {INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, Negate, -1, 1, {INS_neg, INS_invalid, INS_neg, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, NegateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_fneg}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Not, -1, 1, {INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Or, -1, 2, {INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, OrNot, -1, 2, {INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiply, -1, 2, {INS_pmul, INS_pmul, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiplyWideningLower, 8, 2, {INS_pmull, INS_pmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiplyWideningUpper, 16, 2, {INS_pmull2, INS_pmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, PopCount, -1, 1, {INS_cnt, INS_cnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalEstimate, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urecpe, INS_invalid, INS_invalid, INS_frecpe, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootEstimate, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursqrte, INS_invalid, INS_invalid, INS_frsqrte, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootStep, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalStep, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmetic, -1, 2, {INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRounded, -1, 2, {INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedSaturate, -1, 2, {INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturate, -1, 2, {INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogical, -1, 2, {INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturate, -1, 2, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsigned, -1, 2, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsignedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalWideningLower, 8, 2, {INS_sshll, INS_ushll, INS_sshll, INS_ushll, INS_sshll, INS_ushll, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalWideningUpper, 16, 2, {INS_sshll2, INS_ushll2, INS_sshll2, INS_ushll2, INS_sshll2, INS_ushll2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogical, -1, 2, {INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRounded, -1, 2, {INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedSaturate, -1, 2, {INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urshl, INS_urshl, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturate, -1, 2, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmetic, -1, 2, {INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAdd, -1, 3, {INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateLower, 8, 2, {INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUnsignedLower, 8, 2, {INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUnsignedUpper, 16, 3, {INS_invalid, INS_sqshrun2, INS_invalid, INS_sqshrun2, INS_invalid, INS_sqshrun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUpper, 16, 3, {INS_sqshrn2, INS_invalid, INS_sqshrn2, INS_invalid, INS_sqshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRounded, -1, 2, {INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedAdd, -1, 3, {INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srsra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateLower, 8, 2, {INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower, 8, 2, {INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper, 16, 3, {INS_invalid, INS_sqrshrun2, INS_invalid, INS_sqrshrun2, INS_invalid, INS_sqrshrun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUpper, 16, 3, {INS_sqrshrn2, INS_invalid, INS_sqrshrn2, INS_invalid, INS_sqrshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogical, -1, 2, {INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAdd, -1, 3, {INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_usra, INS_usra, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingLower, 8, 2, {INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingSaturateLower, 8, 2, {INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingSaturateUpper, 16, 3, {INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingUpper, 16, 3, {INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRounded, -1, 2, {INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedAdd, -1, 3, {INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursra, INS_ursra, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingLower, 8, 2, {INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingSaturateLower, 8, 2, {INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingSaturateUpper, 16, 3, {INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingUpper, 16, 3, {INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urshr, INS_urshr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushr, INS_ushr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, SignExtendWideningLower, 8, 1, {INS_sxtl, INS_invalid, INS_sxtl, INS_invalid, INS_sxtl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, SignExtendWideningUpper, 16, 1, {INS_sxtl2, INS_invalid, INS_sxtl2, INS_invalid, INS_sxtl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, SqrtScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Store, -1, 2, {INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1}, HW_Category_MemoryStore, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, 2, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractHighNarrowingLower, 8, 2, {INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractHighNarrowingUpper, 16, 3, {INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, SubtractRoundedHighNarrowingLower, 8, 2, {INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractRoundedHighNarrowingUpper, 16, 3, {INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, SubtractSaturate, -1, 2, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractWideningLower, 8, 2, {INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubw, INS_usubw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, SubtractWideningUpper, 16, 2, {INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubw2, INS_usubw2, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, VectorTableLookup, 8, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, VectorTableLookupExtension, 8, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, Xor, -1, 2, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ZeroExtendWideningLower, 8, 1, {INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ZeroExtendWideningUpper, 16, 1, {INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AdvSimd 64-bit only Intrinsics -HARDWARE_INTRINSIC(AdvSimd_Arm64, Abs, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_fabs}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifference, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifferenceScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd, INS_fabd}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Add, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fadd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddAcross, -1, 1, {INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwise, 16, 2, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTest, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTestScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Divide, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAdd, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtract, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxAcross, -1, 1, {INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_invalid, INS_invalid, INS_fmaxv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberAcross, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwise, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwise, 16, 2, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax, INS_fmax}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Min, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinAcross, -1, 1, {INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_invalid, INS_invalid, INS_fminv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberAcross, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwise, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwise, 16, 2, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin, INS_fmin}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Multiply, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtended, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Negate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_fneg}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe, INS_frecpe}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalExponentScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpx, INS_frecpx}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte, INS_frsqrte}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStep, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStepScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_frsqrts}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStep, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStepScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_frecps}, HW_Category_SIMDScalar, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReverseElementBits, -1, 1, {INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Sqrt, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsub}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, SubtractSaturateScalar, 8, 2, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeEven, -1, 2, {INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeOdd, -1, 2, {INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipEven, -1, 2, {INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipOdd, -1, 2, {INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookup, 16, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookupExtension, 16, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipHigh, -1, 2, {INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipLow, -1, 2, {INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Abs, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_fabs}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifference, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifferenceScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd, INS_fabd}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Add, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fadd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddAcross, -1, 1, {INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwise, 16, 2, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTest, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTestScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Divide, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateSelectedScalarToVector128, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dup, INS_dup, INS_invalid, INS_dup}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateToVector64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_fmov}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateToVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dup, INS_dup, INS_invalid, INS_dup}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAdd, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtract, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxAcross, -1, 1, {INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_invalid, INS_invalid, INS_fmaxv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberAcross, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwise, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwise, 16, 2, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax, INS_fmax}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Min, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinAcross, -1, 1, {INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_invalid, INS_invalid, INS_fminv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberAcross, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmv, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwise, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwise, 16, 2, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin, INS_fmin}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Multiply, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtended, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Negate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_fneg}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe, INS_frecpe}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalExponentScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpx, INS_frecpx}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte, INS_frsqrte}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStep, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStepScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_frsqrts}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStep, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStepScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_frecps}, HW_Category_SIMDScalar, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReverseElementBits, -1, 1, {INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftArithmeticRoundedSaturateScalar, 8, 2, {INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftArithmeticSaturateScalar, 8, 2, {INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLeftLogicalSaturateScalar, 8, 2, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLeftLogicalSaturateUnsignedScalar, 8, 2, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLogicalRoundedSaturateScalar, 8, 2, {INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLogicalSaturateScalar, 8, 2, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticNarrowingSaturateScalar, 8, 2, {INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticNarrowingSaturateUnsignedScalar, 8, 2, {INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticRoundedNarrowingSaturateScalar, 8, 2, {INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar, 8, 2, {INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightLogicalNarrowingSaturateScalar, 8, 2, {INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightLogicalRoundedNarrowingSaturateScalar, 8, 2, {INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Sqrt, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsub}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, SubtractSaturateScalar, 8, 2, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeEven, -1, 2, {INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeOdd, -1, 2, {INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipEven, -1, 2, {INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipOdd, -1, 2, {INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookup, 16, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookupExtension, 16, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipHigh, -1, 2, {INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipLow, -1, 2, {INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AES Intrinsics -HARDWARE_INTRINSIC(Aes, Decrypt, 16, 2, {INS_invalid, INS_aesd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Aes, Encrypt, 16, 2, {INS_invalid, INS_aese, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Aes, InverseMixColumns, 16, 1, {INS_invalid, INS_aesimc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(Aes, MixColumns, 16, 1, {INS_invalid, INS_aesmc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(Aes, Decrypt, 16, 2, {INS_invalid, INS_aesd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Aes, Encrypt, 16, 2, {INS_invalid, INS_aese, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Aes, InverseMixColumns, 16, 1, {INS_invalid, INS_aesimc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(Aes, MixColumns, 16, 1, {INS_invalid, INS_aesmc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningLower, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmull, INS_pmull, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningUpper, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmull2, INS_pmull2, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Base Intrinsics -HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(ArmBase, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(ArmBase, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFlag) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Base 64-bit only Intrinsics -HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(ArmBase_Arm64, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(ArmBase_Arm64, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFlag) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // CRC32 Intrinsics -HARDWARE_INTRINSIC(Crc32, ComputeCrc32, 0, 2, {INS_invalid, INS_crc32b, INS_invalid, INS_crc32h, INS_invalid, INS_crc32w, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(Crc32, ComputeCrc32C, 0, 2, {INS_invalid, INS_crc32cb, INS_invalid, INS_crc32ch, INS_invalid, INS_crc32cw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(Crc32, ComputeCrc32, 0, 2, {INS_invalid, INS_crc32b, INS_invalid, INS_crc32h, INS_invalid, INS_crc32w, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(Crc32, ComputeCrc32C, 0, 2, {INS_invalid, INS_crc32cb, INS_invalid, INS_crc32ch, INS_invalid, INS_crc32cw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // CRC32 64-bit only Intrinsics -HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32x, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32C, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32cx, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32x, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32C, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32cx, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SHA1 Intrinsics -HARDWARE_INTRINSIC(Sha1, FixedRotate, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(Sha1, HashUpdateChoose, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1c, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, HashUpdateMajority, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1m, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, HashUpdateParity, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1p, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, ScheduleUpdate0, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, ScheduleUpdate1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, FixedRotate, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(Sha1, HashUpdateChoose, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1c, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, HashUpdateMajority, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1m, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, HashUpdateParity, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1p, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, ScheduleUpdate0, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, ScheduleUpdate1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA Function name SIMD size Number of arguments Instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SHA256 Intrinsics -HARDWARE_INTRINSIC(Sha256, HashUpdate1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha256, HashUpdate2, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha256, ScheduleUpdate0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha256, ScheduleUpdate1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, HashUpdate1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, HashUpdate2, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, ScheduleUpdate0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, ScheduleUpdate1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_HasRMWSemantics) #endif // FEATURE_HW_INTRINSIC diff --git a/src/coreclr/src/jit/hwintrinsiclistxarch.h b/src/coreclr/src/jit/hwintrinsiclistxarch.h index 4be0cdadd809c..c6017fb12c44c 100644 --- a/src/coreclr/src/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/src/jit/hwintrinsiclistxarch.h @@ -43,16 +43,19 @@ HARDWARE_INTRINSIC(Vector128, AsVector2, HARDWARE_INTRINSIC(Vector128, AsVector3, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, AsVector4, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, AsVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) // The instruction generated for float/double depends on which ISAs are supported HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmppd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, op_Equality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, op_Inequality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256Unsafe, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg Instructions Category Flags @@ -76,11 +79,14 @@ HARDWARE_INTRINSIC(Vector256, AsVector256, HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmppd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, get_Count, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, get_Zero, 32, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector256, Create, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector256, GetElement, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, WithElement, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector256, op_Equality, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, op_Inequality, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Vector256, WithElement, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg Instructions Category Flags diff --git a/src/coreclr/src/jit/hwintrinsicxarch.cpp b/src/coreclr/src/jit/hwintrinsicxarch.cpp index 010cd5fa5063d..214ce21496f5a 100644 --- a/src/coreclr/src/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/src/jit/hwintrinsicxarch.cpp @@ -469,22 +469,26 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT // intrinsic -- id of the intrinsic function. // clsHnd -- class handle containing the intrinsic function. // method -- method handle of the intrinsic function. -// sig -- signature of the intrinsic call -// +// sig -- signature of the intrinsic call. +// baseType -- generic argument of the intrinsic. +// retType -- return type of the intrinsic. // Return Value: // the expanded intrinsic. // GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig) + CORINFO_SIG_INFO* sig, + var_types baseType, + var_types retType, + unsigned simdSize) { // other intrinsics need special importation switch (HWIntrinsicInfo::lookupIsa(intrinsic)) { case InstructionSet_Vector128: case InstructionSet_Vector256: - return impBaseIntrinsic(intrinsic, clsHnd, method, sig); + return impBaseIntrinsic(intrinsic, clsHnd, method, sig, baseType, retType, simdSize); case InstructionSet_SSE: return impSSEIntrinsic(intrinsic, method, sig); case InstructionSet_SSE2: @@ -509,60 +513,29 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, // Arguments: // intrinsic -- id of the intrinsic function. // method -- method handle of the intrinsic function. -// sig -- signature of the intrinsic call -// +// sig -- signature of the intrinsic call. +// baseType -- generic argument of the intrinsic. +// retType -- return type of the intrinsic. // Return Value: // the expanded intrinsic. // GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig) + CORINFO_SIG_INFO* sig, + var_types baseType, + var_types retType, + unsigned simdSize) { GenTree* retNode = nullptr; GenTree* op1 = nullptr; + GenTree* op2 = nullptr; if (!featureSIMD) { return nullptr; } - unsigned simdSize = 0; - var_types baseType = TYP_UNKNOWN; - var_types retType = JITtype2varType(sig->retType); - - assert(!sig->hasThis()); - - if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic)) - { - baseType = getBaseTypeAndSizeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args), &simdSize); - - if (retType == TYP_STRUCT) - { - unsigned retSimdSize = 0; - var_types retBasetype = getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &retSimdSize); - if (!varTypeIsArithmetic(retBasetype)) - { - return nullptr; - } - retType = getSIMDTypeForSize(retSimdSize); - } - } - else if (retType == TYP_STRUCT) - { - baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &simdSize); - retType = getSIMDTypeForSize(simdSize); - } - else - { - baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &simdSize); - } - - if (!varTypeIsArithmetic(baseType)) - { - return nullptr; - } - switch (intrinsic) { case NI_Vector256_As: @@ -617,7 +590,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, if (getSIMDVectorRegisterByteLength() == YMM_REGSIZE_BYTES) { // Vector is TYP_SIMD32, so we should treat this as a call to Vector128.ToVector256 - return impBaseIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig); + return impBaseIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig, baseType, retType, simdSize); } assert(getSIMDVectorRegisterByteLength() == XMM_REGSIZE_BYTES); @@ -658,6 +631,11 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_AsVector128: { assert(sig->numArgs == 1); + assert(HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic)); + + var_types baseTypeOfIntrinsic = + getBaseTypeAndSizeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args), &simdSize); + assert(baseType == baseTypeOfIntrinsic); switch (getSIMDTypeForSize(simdSize)) { @@ -685,7 +663,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, case TYP_SIMD32: { // Vector is TYP_SIMD32, so we should treat this as a call to Vector256.GetLower - return impBaseIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig); + return impBaseIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig, baseType, retType, simdSize); } default: @@ -724,12 +702,12 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, if (intrinsic == NI_Vector256_AsVector) { - return impBaseIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig); + return impBaseIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig, baseType, retType, simdSize); } else { assert(intrinsic == NI_Vector256_AsVector256); - return impBaseIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig); + return impBaseIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig, baseType, retType, simdSize); } } @@ -747,6 +725,70 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_Create: + case NI_Vector256_Create: + { +#if defined(TARGET_X86) + if (varTypeIsLong(baseType)) + { + // TODO-XARCH-CQ: It may be beneficial to emit the movq + // instruction, which takes a 64-bit memory address and + // works on 32-bit x86 systems. + break; + } +#endif // TARGET_X86 + + // We shouldn't handle this as an intrinsic if the + // respective ISAs have been disabled by the user. + + if (intrinsic == NI_Vector256_Create) + { + if (!compExactlyDependsOn(InstructionSet_AVX)) + { + break; + } + } + else if (baseType == TYP_FLOAT) + { + if (!compExactlyDependsOn(InstructionSet_SSE)) + { + break; + } + } + else if (!compExactlyDependsOn(InstructionSet_SSE2)) + { + break; + } + + if (sig->numArgs == 1) + { + op1 = impPopStack().val; + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize); + } + else if (sig->numArgs == 2) + { + op2 = impPopStack().val; + op1 = impPopStack().val; + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, baseType, simdSize); + } + else + { + assert(sig->numArgs >= 3); + + GenTreeArgList* tmp = nullptr; + + for (unsigned i = 0; i < sig->numArgs; i++) + { + tmp = gtNewArgList(impPopStack().val); + tmp->gtOp2 = op1; + op1 = tmp; + } + + retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize); + } + break; + } + case NI_Vector128_CreateScalarUnsafe: { assert(sig->numArgs == 1); diff --git a/src/coreclr/src/jit/importer.cpp b/src/coreclr/src/jit/importer.cpp index aae168c337883..d5bf9bf745541 100644 --- a/src/coreclr/src/jit/importer.cpp +++ b/src/coreclr/src/jit/importer.cpp @@ -3478,29 +3478,34 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, { ni = lookupNamedIntrinsic(method); -#ifdef FEATURE_HW_INTRINSICS + // We specially support the following on all platforms to allow for dead + // code optimization and to more generally support recursive intrinsics. + if (ni == NI_IsSupported_True) { + assert(sig->numArgs == 0); return gtNewIconNode(true); } if (ni == NI_IsSupported_False) { + assert(sig->numArgs == 0); return gtNewIconNode(false); } if (ni == NI_Throw_PlatformNotSupportedException) { - return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand); + return impUnsupportedNamedIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand); } +#ifdef FEATURE_HW_INTRINSICS if ((ni > NI_HW_INTRINSIC_START) && (ni < NI_HW_INTRINSIC_END)) { GenTree* hwintrinsic = impHWIntrinsic(ni, clsHnd, method, sig, mustExpand); if (mustExpand && (hwintrinsic == nullptr)) { - return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_NOT_IMPLEMENTED, method, sig, mustExpand); + return impUnsupportedNamedIntrinsic(CORINFO_HELP_THROW_NOT_IMPLEMENTED, method, sig, mustExpand); } return hwintrinsic; @@ -4272,7 +4277,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, if (mustExpand && (retNode == nullptr)) { - NO_WAY("JIT must expand the intrinsic!"); + assert(!"Unhandled must expand intrinsic, throwing PlatformNotSupportedException"); + return impUnsupportedNamedIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand); } // Optionally report if this intrinsic is special @@ -4489,8 +4495,30 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) result = SimdAsHWIntrinsicInfo::lookupId(&sig, className, methodName, enclosingClassName, sizeOfVectorT); } +#endif // FEATURE_HW_INTRINSICS else if (strncmp(namespaceName, "System.Runtime.Intrinsics", 25) == 0) { + // We go down this path even when FEATURE_HW_INTRINSICS isn't enabled + // so we can specially handle IsSupported and recursive calls. + + // This is required to appropriately handle the intrinsics on platforms + // which don't support them. On such a platform methods like Vector64.Create + // will be seen as `Intrinsic` and `mustExpand` due to having a code path + // which is recursive. When such a path is hit we expect it to be handled by + // the importer and we fire an assert if it wasn't and in previous versions + // of the JIT would fail fast. This was changed to throw a PNSE instead but + // we still assert as most intrinsics should have been recognized/handled. + + // In order to avoid the assert, we specially handle the IsSupported checks + // (to better allow dead-code optimizations) and we explicitly throw a PNSE + // as we know that is the desired behavior for the HWIntrinsics when not + // supported. For cases like Vector64.Create, this is fine because it will + // be behind a relevant IsSupported check and will never be hit and the + // software fallback will be executed instead. + + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef FEATURE_HW_INTRINSICS namespaceName += 25; const char* platformNamespaceName; @@ -4504,23 +4532,45 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) if ((namespaceName[0] == '\0') || (strcmp(namespaceName, platformNamespaceName) == 0)) { - result = HWIntrinsicInfo::lookupId(this, className, methodName, enclosingClassName); - } - else if (strcmp(methodName, "get_IsSupported") == 0) - { - return NI_IsSupported_False; + CORINFO_SIG_INFO sig; + info.compCompHnd->getMethodSig(method, &sig); + + result = HWIntrinsicInfo::lookupId(this, &sig, className, methodName, enclosingClassName); } - else +#endif // FEATURE_HW_INTRINSICS + + if (result == NI_Illegal) { - return gtIsRecursiveCall(method) ? NI_Throw_PlatformNotSupportedException : NI_Illegal; + if (strcmp(methodName, "get_IsSupported") == 0) + { + // This allows the relevant code paths to be dropped as dead code even + // on platforms where FEATURE_HW_INTRINSICS is not supported. + + result = NI_IsSupported_False; + } + else if (gtIsRecursiveCall(method)) + { + // For the framework itself, any recursive intrinsics will either be + // only supported on a single platform or will be guarded by a relevant + // IsSupported check so the throw PNSE will be valid or dropped. + + result = NI_Throw_PlatformNotSupportedException; + } } } -#endif // FEATURE_HW_INTRINSICS if (result == NI_Illegal) { JITDUMP("Not recognized\n"); } + else if (result == NI_IsSupported_False) + { + JITDUMP("Unsupported - return false"); + } + else if (result == NI_Throw_PlatformNotSupportedException) + { + JITDUMP("Unsupported - throw PlatformNotSupportedException"); + } else { JITDUMP("Recognized\n"); @@ -4528,6 +4578,50 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) return result; } +//------------------------------------------------------------------------ +// impUnsupportedNamedIntrinsic: Throws an exception for an unsupported named intrinsic +// +// Arguments: +// helper - JIT helper ID for the exception to be thrown +// method - method handle of the intrinsic function. +// sig - signature of the intrinsic call +// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false +// +// Return Value: +// a gtNewMustThrowException if mustExpand is true; otherwise, nullptr +// +GenTree* Compiler::impUnsupportedNamedIntrinsic(unsigned helper, + CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* sig, + bool mustExpand) +{ + // We've hit some error case and may need to return a node for the given error. + // + // When `mustExpand=false`, we are attempting to inline the intrinsic directly into another method. In this + // scenario, we need to return `nullptr` so that a GT_CALL to the intrinsic is emitted instead. This is to + // ensure that everything continues to behave correctly when optimizations are enabled (e.g. things like the + // inliner may expect the node we return to have a certain signature, and the `MustThrowException` node won't + // match that). + // + // When `mustExpand=true`, we are in a GT_CALL to the intrinsic and are attempting to JIT it. This will generally + // be in response to an indirect call (e.g. done via reflection) or in response to an earlier attempt returning + // `nullptr` (under `mustExpand=false`). In that scenario, we are safe to return the `MustThrowException` node. + + if (mustExpand) + { + for (unsigned i = 0; i < sig->numArgs; i++) + { + impPopStack(); + } + + return gtNewMustThrowException(helper, JITtype2varType(sig->retType), sig->retTypeClass); + } + else + { + return nullptr; + } +} + /*****************************************************************************/ GenTree* Compiler::impArrayAccessIntrinsic( @@ -8888,9 +8982,7 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN call->gtRetClsHnd = retClsHnd; #if FEATURE_MULTIREG_RET - // Initialize Return type descriptor of call node - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - retTypeDesc->InitializeStructReturnType(this, retClsHnd); + call->InitializeStructReturnType(this, retClsHnd); #endif // FEATURE_MULTIREG_RET #ifdef UNIX_AMD64_ABI @@ -8898,55 +8990,57 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN // Not allowed for FEATURE_CORCLR which is the only SKU available for System V OSs. assert(!call->IsVarargs() && "varargs not allowed for System V OSs."); - // The return type will remain as the incoming struct type unless normalized to a - // single eightbyte return type below. - call->gtReturnType = call->gtType; - - unsigned retRegCount = retTypeDesc->GetReturnRegCount(); - if (retRegCount != 0) + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + const unsigned retRegCount = retTypeDesc->GetReturnRegCount(); + if (retRegCount == 0) + { + // struct not returned in registers i.e returned via hiddden retbuf arg. + call->gtCallMoreFlags |= GTF_CALL_M_RETBUFFARG; + } + else if (retRegCount == 1) { - if (retRegCount == 1) + if (!compDoOldStructRetyping()) { - // See if the struct size is smaller than the return - // type size... - if (retTypeDesc->IsEnclosingType()) + return call; + } + // See if the struct size is smaller than the return + // type size... + if (retTypeDesc->IsEnclosingType()) + { + // If we know for sure this call will remain a call, + // retype and return value via a suitable temp. + if ((!call->CanTailCall()) && (!call->IsInlineCandidate())) { - // If we know for sure this call will remain a call, - // retype and return value via a suitable temp. - if ((!call->CanTailCall()) && (!call->IsInlineCandidate())) - { - call->gtReturnType = retTypeDesc->GetReturnRegType(0); - return impAssignSmallStructTypeToVar(call, retClsHnd); - } + call->gtReturnType = retTypeDesc->GetReturnRegType(0); + return impAssignSmallStructTypeToVar(call, retClsHnd); } else { - // Return type is same size as struct, so we can - // simply retype the call. - call->gtReturnType = retTypeDesc->GetReturnRegType(0); + call->gtReturnType = call->gtType; } } else { - // must be a struct returned in two registers - assert(retRegCount == 2); - - if ((!call->CanTailCall()) && (!call->IsInlineCandidate())) - { - // Force a call returning multi-reg struct to be always of the IR form - // tmp = call - // - // No need to assign a multi-reg struct to a local var if: - // - It is a tail call or - // - The call is marked for in-lining later - return impAssignMultiRegTypeToVar(call, retClsHnd); - } + // Return type is same size as struct, so we can + // simply retype the call. + call->gtReturnType = retTypeDesc->GetReturnRegType(0); } } else { - // struct not returned in registers i.e returned via hiddden retbuf arg. - call->gtCallMoreFlags |= GTF_CALL_M_RETBUFFARG; + // must be a struct returned in two registers + assert(retRegCount == 2); + + if ((!call->CanTailCall()) && (!call->IsInlineCandidate())) + { + // Force a call returning multi-reg struct to be always of the IR form + // tmp = call + // + // No need to assign a multi-reg struct to a local var if: + // - It is a tail call or + // - The call is marked for in-lining later + return impAssignMultiRegTypeToVar(call, retClsHnd); + } } #else // not UNIX_AMD64_ABI @@ -8965,10 +9059,21 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN } else { + +#if FEATURE_MULTIREG_RET + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + const unsigned retRegCount = retTypeDesc->GetReturnRegCount(); + assert(retRegCount != 0); + if (!compDoOldStructRetyping() && retRegCount == 1) + { + return call; + } +#else // !FEATURE_MULTIREG_RET if (!compDoOldStructRetyping()) { return call; } +#endif // !FEATURE_MULTIREG_RET assert(returnType != TYP_UNKNOWN); // See if the struct size is smaller than the return @@ -9001,9 +9106,6 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN } #if FEATURE_MULTIREG_RET - unsigned retRegCount = retTypeDesc->GetReturnRegCount(); - assert(retRegCount != 0); - if (retRegCount >= 2) { if ((!call->CanTailCall()) && (!call->IsInlineCandidate())) @@ -9036,12 +9138,6 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re assert(varTypeIsStruct(info.compRetType)); assert(info.compRetBuffArg == BAD_VAR_NUM); - if (!compDoOldStructRetyping() && (!op->IsCall() || !op->AsCall()->TreatAsHasRetBufArg(this))) - { - // Don't retype `struct` as a primitive type in `ret` instruction. - return op; - } - JITDUMP("\nimpFixupStructReturnType: retyping\n"); DISPTREE(op); @@ -9156,6 +9252,12 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re #endif // FEATURE_MULTIREG_RET && FEATURE_HFA + if (!compDoOldStructRetyping() && (!op->IsCall() || !op->AsCall()->TreatAsHasRetBufArg(this))) + { + // Don't retype `struct` as a primitive type in `ret` instruction. + return op; + } + REDO_RETURN_NODE: // adjust the type away from struct to integral // and no normalizing @@ -13781,7 +13883,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) bool bbIsReturn = (block->bbJumpKind == BBJ_RETURN) && (!compIsForInlining() || (impInlineInfo->iciBlock->bbJumpKind == BBJ_RETURN)); LclVarDsc* const lclDsc = lvaGetDesc(lclNum); - if (fgVarNeedsExplicitZeroInit(lclDsc, bbInALoop, bbIsReturn)) + if (fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn)) { // Append a tree to zero-out the temp newObjThisPtr = gtNewLclvNode(lclNum, lvaTable[lclNum].TypeGet()); @@ -14308,6 +14410,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert(pFldAddr == nullptr); op1 = impImportStaticReadOnlyField(fldAddr, lclTyp); + + // Widen small types since we're propagating the value + // instead of producing an indir. + // + op1->gtType = genActualType(lclTyp); + goto FIELD_DONE; } } @@ -14325,7 +14433,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_INTRINSIC_ZERO: { assert(aflags & CORINFO_ACCESS_GET); - op1 = gtNewIconNode(0, lclTyp); + // Widen to stack type + lclTyp = genActualType(lclTyp); + op1 = gtNewIconNode(0, lclTyp); goto FIELD_DONE; } break; @@ -14344,6 +14454,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN: { assert(aflags & CORINFO_ACCESS_GET); + // Widen to stack type + lclTyp = genActualType(lclTyp); #if BIGENDIAN op1 = gtNewIconNode(0, lclTyp); #else @@ -15120,6 +15232,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (!compDoOldStructRetyping()) { op1->AsCall()->gtRetClsHnd = classHandle; +#if FEATURE_MULTIREG_RET + op1->AsCall()->InitializeStructReturnType(this, classHandle); +#endif } tiRetVal = typeInfo(TI_STRUCT, classHandle); @@ -15164,6 +15279,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) op1->AsCall()->gtReturnType = GetRuntimeHandleUnderlyingType(); if (!compDoOldStructRetyping()) { +#if FEATURE_MULTIREG_RET + op1->AsCall()->InitializeStructReturnType(this, tokenType); +#endif op1->AsCall()->gtRetClsHnd = tokenType; } @@ -16267,7 +16385,7 @@ void Compiler::impMarkLclDstNotPromotable(unsigned tmpNum, GenTree* src, CORINFO GenTree* Compiler::impAssignSmallStructTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass) { - unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for small struct return.")); + unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for small struct return")); impAssignTempGen(tmpNum, op, hClass, (unsigned)CHECK_SPILL_ALL); GenTree* ret = gtNewLclvNode(tmpNum, lvaTable[tmpNum].lvType); return ret; @@ -16287,7 +16405,7 @@ GenTree* Compiler::impAssignSmallStructTypeToVar(GenTree* op, CORINFO_CLASS_HAND GenTree* Compiler::impAssignMultiRegTypeToVar(GenTree* op, CORINFO_CLASS_HANDLE hClass) { - unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for multireg return.")); + unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for multireg return")); impAssignTempGen(tmpNum, op, hClass, (unsigned)CHECK_SPILL_ALL); GenTree* ret = gtNewLclvNode(tmpNum, lvaTable[tmpNum].lvType); diff --git a/src/coreclr/src/jit/instr.cpp b/src/coreclr/src/jit/instr.cpp index 969efe5a4573d..ec776cbea9a91 100644 --- a/src/coreclr/src/jit/instr.cpp +++ b/src/coreclr/src/jit/instr.cpp @@ -57,13 +57,13 @@ const char* CodeGen::genInsName(instruction ins) #include "instrs.h" #elif defined(TARGET_ARM64) - #define INST1(id, nm, fp, ldst, fmt, e1 ) nm, - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) nm, - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) nm, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) nm, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) nm, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) nm, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) nm, + #define INST1(id, nm, ldst, fmt, e1 ) nm, + #define INST2(id, nm, ldst, fmt, e1, e2 ) nm, + #define INST3(id, nm, ldst, fmt, e1, e2, e3 ) nm, + #define INST4(id, nm, ldst, fmt, e1, e2, e3, e4 ) nm, + #define INST5(id, nm, ldst, fmt, e1, e2, e3, e4, e5 ) nm, + #define INST6(id, nm, ldst, fmt, e1, e2, e3, e4, e5, e6 ) nm, + #define INST9(id, nm, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9 ) nm, #include "instrs.h" #else diff --git a/src/coreclr/src/jit/instr.h b/src/coreclr/src/jit/instr.h index 26ba6eec4ac01..3c0404c6079e9 100644 --- a/src/coreclr/src/jit/instr.h +++ b/src/coreclr/src/jit/instr.h @@ -37,13 +37,13 @@ enum instruction : unsigned INS_lea, // Not a real instruction. It is used for load the address of stack locals #elif defined(TARGET_ARM64) - #define INST1(id, nm, fp, ldst, fmt, e1 ) INS_##id, - #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) INS_##id, - #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) INS_##id, - #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) INS_##id, - #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) INS_##id, - #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) INS_##id, - #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) INS_##id, + #define INST1(id, nm, ldst, fmt, e1 ) INS_##id, + #define INST2(id, nm, ldst, fmt, e1, e2 ) INS_##id, + #define INST3(id, nm, ldst, fmt, e1, e2, e3 ) INS_##id, + #define INST4(id, nm, ldst, fmt, e1, e2, e3, e4 ) INS_##id, + #define INST5(id, nm, ldst, fmt, e1, e2, e3, e4, e5 ) INS_##id, + #define INST6(id, nm, ldst, fmt, e1, e2, e3, e4, e5, e6 ) INS_##id, + #define INST9(id, nm, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) INS_##id, #include "instrs.h" INS_lea, // Not a real instruction. It is used for load the address of stack locals diff --git a/src/coreclr/src/jit/instrsarm64.h b/src/coreclr/src/jit/instrsarm64.h index 4569606835996..41d33443c68d3 100644 --- a/src/coreclr/src/jit/instrsarm64.h +++ b/src/coreclr/src/jit/instrsarm64.h @@ -7,14 +7,17 @@ * * id -- the enum name for the instruction * nm -- textual name (for assembly dipslay) - * fp -- floating point instruction - * ld/st/cmp -- load/store/compare instruction + * info -- miscellaneous instruction info (load/store/compare/ASIMD right shift) * fmt -- encoding format used by this instruction * e1 -- encoding 1 * e2 -- encoding 2 * e3 -- encoding 3 * e4 -- encoding 4 * e5 -- encoding 5 + * e6 -- encoding 6 + * e7 -- encoding 7 + * e8 -- encoding 8 + * e9 -- encoding 9 * ******************************************************************************/ @@ -45,7 +48,7 @@ #endif /*****************************************************************************/ -/* The following is ARM64-specific */ +/* The following is ARM64-specific */ /*****************************************************************************/ // If you're adding a new instruction: @@ -54,10 +57,10 @@ // emitInsMayWriteMultipleRegs in emitArm64.cpp. // clang-format off -INST9(invalid, "INVALID", 0, 0, IF_NONE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE) +INST9(invalid, "INVALID", 0, IF_NONE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE, BAD_CODE) -// enum name FP LD/ST DR_2E DR_2G DI_1B DI_1D DV_3C DV_2B DV_2C DV_2E DV_2F -INST9(mov, "mov", 0, 0, IF_EN9, 0x2A0003E0, 0x11000000, 0x52800000, 0x320003E0, 0x0EA01C00, 0x0E003C00, 0x4E001C00, 0x5E000400, 0x6E000400) +// enum name info DR_2E DR_2G DI_1B DI_1D DV_3C DV_2B DV_2C DV_2E DV_2F +INST9(mov, "mov", 0, IF_EN9, 0x2A0003E0, 0x11000000, 0x52800000, 0x320003E0, 0x0EA01C00, 0x0E003C00, 0x4E001C00, 0x5E000400, 0x6E000400) // mov Rd,Rm DR_2E X0101010000mmmmm 00000011111ddddd 2A00 03E0 // mov Rd,Rn DR_2G X001000100000000 000000nnnnnddddd 1100 0000 mov to/from SP only // mov Rd,imm(i16,hw) DI_1B X10100101hwiiiii iiiiiiiiiiiddddd 5280 0000 imm(i16,hw) @@ -68,8 +71,8 @@ INST9(mov, "mov", 0, 0, IF_EN9, 0x2A0003E0, 0x11000000, 0x52800000, // mov Vd,Vn[] DV_2E 01011110000iiiii 000001nnnnnddddd 5E00 0400 Vd,Vn[] (scalar by elem) // mov Vd[],Vn[] DV_2F 01101110000iiiii 0jjjj1nnnnnddddd 6E00 0400 Vd[],Vn[] (from/to elem) -// enum name FP LD/ST DR_3A DR_3B DR_3C DI_2A DV_3A DV_3E -INST6(add, "add", 0, 0, IF_EN6A, 0x0B000000, 0x0B000000, 0x0B200000, 0x11000000, 0x0E208400, 0x5EE08400) +// enum name info DR_3A DR_3B DR_3C DI_2A DV_3A DV_3E +INST6(add, "add", 0, IF_EN6A, 0x0B000000, 0x0B000000, 0x0B200000, 0x11000000, 0x0E208400, 0x5EE08400) // add Rd,Rn,Rm DR_3A X0001011000mmmmm 000000nnnnnddddd 0B00 0000 Rd,Rn,Rm // add Rd,Rn,(Rm,shk,imm) DR_3B X0001011sh0mmmmm ssssssnnnnnddddd 0B00 0000 Rm {LSL,LSR,ASR} imm(0-63) // add Rd,Rn,(Rm,ext,shl) DR_3C X0001011001mmmmm ooosssnnnnnddddd 0B20 0000 ext(Rm) LSL imm(0-4) @@ -77,7 +80,7 @@ INST6(add, "add", 0, 0, IF_EN6A, 0x0B000000, 0x0B000000, 0x0B200000, // add Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 100001nnnnnddddd 0E20 8400 Vd,Vn,Vm (vector) // add Vd,Vn,Vm DV_3E 01011110111mmmmm 100001nnnnnddddd 5EE0 8400 Vd,Vn,Vm (scalar) -INST6(sub, "sub", 0, 0, IF_EN6A, 0x4B000000, 0x4B000000, 0x4B200000, 0x51000000, 0x2E208400, 0x7EE08400) +INST6(sub, "sub", 0, IF_EN6A, 0x4B000000, 0x4B000000, 0x4B200000, 0x51000000, 0x2E208400, 0x7EE08400) // sub Rd,Rn,Rm DR_3A X1001011000mmmmm 000000nnnnnddddd 4B00 0000 Rd,Rn,Rm // sub Rd,Rn,(Rm,shk,imm) DR_3B X1001011sh0mmmmm ssssssnnnnnddddd 4B00 0000 Rm {LSL,LSR,ASR} imm(0-63) // sub Rd,Rn,(Rm,ext,shl) DR_3C X1001011001mmmmm ooosssnnnnnddddd 4B20 0000 ext(Rm) LSL imm(0-4) @@ -85,1776 +88,1772 @@ INST6(sub, "sub", 0, 0, IF_EN6A, 0x4B000000, 0x4B000000, 0x4B200000, // sub Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100001nnnnnddddd 2E20 8400 Vd,Vn,Vm (vector) // sub Vd,Vn,Vm DV_3E 01111110111mmmmm 100001nnnnnddddd 7EE0 8400 Vd,Vn,Vm (scalar) -// enum name FP LD/ST LS_2D LS_3F LS_2E LS_2F LS_3G LS_2G -INST6(ld1, "ld1", 0, LD, IF_EN6B, 0x0C407000, 0x0CC07000, 0x0CDF7000, 0x0D400000, 0x0DC00000, 0x0DDF0000) - // C7.2.170 LD1 (multiple structures, one register variant) +// enum name info LS_2D LS_3F LS_2E LS_2F LS_3G LS_2G +INST6(ld1, "ld1", LD, IF_EN6B, 0x0C407000, 0x0CC07000, 0x0CDF7000, 0x0D400000, 0x0DC00000, 0x0DDF0000) + // LD1 (multiple structures, one register variant) // ld1 {Vt},[Xn] LS_2D 0Q00110001000000 0111ssnnnnnttttt 0C40 7000 base register // ld1 {Vt},[Xn],Xm LS_3F 0Q001100110mmmmm 0111ssnnnnnttttt 0CC0 7000 post-indexed by a register // ld1 {Vt},[Xn],#imm LS_2E 0Q00110011011111 0111ssnnnnnttttt 0CDF 7000 post-indexed by an immediate - // C7.2.171 LD1 (single structure) + // LD1 (single structure) // ld1 {Vt}[],[Xn] LS_2F 0Q00110101000000 xx0Sssnnnnnttttt 0D40 0000 base register // ld1 {Vt}[],[Xn],Xm LS_3G 0Q001101110mmmmm xx0Sssnnnnnttttt 0DC0 0000 post-indexed by a register // ld1 {Vt}[],[Xn],#imm LS_2G 0Q00110111011111 xx0Sssnnnnnttttt 0DDF 0000 post-indexed by an immediate -INST6(ld2, "ld2", 0, LD, IF_EN6B, 0x0C408000, 0x0CC08000, 0x0CDF8000, 0x0D600000, 0x0DE00000, 0x0DFF0000) - // C7.2.173 LD2 (multiple structures) +INST6(ld2, "ld2", LD, IF_EN6B, 0x0C408000, 0x0CC08000, 0x0CDF8000, 0x0D600000, 0x0DE00000, 0x0DFF0000) + // LD2 (multiple structures) // ld2 {Vt,Vt2},[Xn] LS_2D 0Q00110001000000 1000ssnnnnnttttt 0C40 8000 base register // ld2 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100110mmmmm 1000ssnnnnnttttt 0CC0 8000 post-indexed by a register // ld2 {Vt,Vt2},[Xn],#imm LS_2E 0Q001100110mmmmm 1000ssnnnnnttttt 0CDF 8000 post-indexed by an immediate - // C7.2.174 LD2 (single structure) + // LD2 (single structure) // ld2 {Vt,Vt2}[],[Xn] LS_2F 0Q00110101100000 xx0Sssnnnnnttttt 0D60 0000 base register // ld2 {Vt,Vt2}[],[Xn],Xm LS_3G 0Q001101111mmmmm xx0Sssnnnnnttttt 0DE0 0000 post-indexed by a register // ld2 {Vt,Vt2}[],[Xn],#imm LS_2G 0Q00110111111111 xx0Sssnnnnnttttt 0DFF 0000 post-indexed by an immediate -INST6(ld3, "ld3", 0, LD, IF_EN6B, 0x0C404000, 0x0CC04000, 0x0CDF4000, 0x0D402000, 0x0DC02000, 0x0DDF2000) - // C7.2.176 LD3 (multiple structures) +INST6(ld3, "ld3", LD, IF_EN6B, 0x0C404000, 0x0CC04000, 0x0CDF4000, 0x0D402000, 0x0DC02000, 0x0DDF2000) + // LD3 (multiple structures) // ld3 {Vt-Vt3},[Xn] LS_2D 0Q00110001000000 0100ssnnnnnttttt 0C40 4000 base register // ld3 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100110mmmmm 0100ssnnnnnttttt 0CC0 4000 post-indexed by a register // ld3 {Vt-Vt3},[Xn],#imm LS_2E 0Q001100110mmmmm 0100ssnnnnnttttt 0CDF 4000 post-indexed by an immediate - // C7.2.177 LD3 (single structure) + // LD3 (single structure) // ld3 {Vt-Vt3}[],[Xn] LS_2F 0Q00110101000000 xx1Sssnnnnnttttt 0D40 2000 base register // ld3 {Vt-Vt3}[],[Xn],Xm LS_3G 0Q001101110mmmmm xx1Sssnnnnnttttt 0DC0 2000 post-indexed by a register // ld3 {Vt-Vt3}[],[Xn],#imm LS_2G 0Q00110111011111 xx1Sssnnnnnttttt 0DDF 2000 post-indexed by an immediate -INST6(ld4, "ld4", 0, LD, IF_EN6B, 0x0C400000, 0x0CC00000, 0x0CDF0000, 0x0D602000, 0x0DE02000, 0x0DFF2000) - // C7.2.179 LD4 (multiple structures) +INST6(ld4, "ld4", LD, IF_EN6B, 0x0C400000, 0x0CC00000, 0x0CDF0000, 0x0D602000, 0x0DE02000, 0x0DFF2000) + // LD4 (multiple structures) // ld4 {Vt-Vt4},[Xn] LS_2D 0Q00110001000000 0000ssnnnnnttttt 0C40 0000 base register // ld4 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100110mmmmm 0000ssnnnnnttttt 0CC0 0000 post-indexed by a register // ld4 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110011011111 0000ssnnnnnttttt 0CDF 0000 post-indexed by an immediate - // C7.2.180 LD4 (single structure) + // LD4 (single structure) // ld4 {Vt-Vt4}[],[Xn] LS_2F 0Q00110101100000 xx1Sssnnnnnttttt 0D60 2000 base register // ld4 {Vt-Vt4}[],[Xn],Xm LS_3G 0Q001101111mmmmm xx1Sssnnnnnttttt 0DE0 2000 post-indexed by a register // ld4 {Vt-Vt4}[],[Xn],#imm LS_2G 0Q00110111111111 xx1Sssnnnnnttttt 0DFF 2000 post-indexed by an immediate -INST6(st1, "st1", 0, LD, IF_EN6B, 0x0C007000, 0x0C807000, 0x0C9F7000, 0x0D000000, 0x0D800000, 0x0D9F0000) - // C7.2.313 ST1 (multiple structures, one register variant) +INST6(st1, "st1", LD, IF_EN6B, 0x0C007000, 0x0C807000, 0x0C9F7000, 0x0D000000, 0x0D800000, 0x0D9F0000) + // ST1 (multiple structures, one register variant) // st1 {Vt},[Xn] LS_2D 0Q00110000000000 0111ssnnnnnttttt 0C00 7000 base register // st1 {Vt},[Xn],Xm LS_3F 0Q001100100mmmmm 0111ssnnnnnttttt 0C80 7000 post-indexed by a register // st1 {Vt},[Xn],#imm LS_2E 0Q00110010011111 0111ssnnnnnttttt 0C9F 7000 post-indexed by an immediate - // C7.2.314 ST1 (single structure) + // ST1 (single structure) // st1 {Vt}[],[Xn] LS_2F 0Q00110100000000 xx0Sssnnnnnttttt 0D00 0000 base register // st1 {Vt}[],[Xn],Xm LS_3G 0Q001101100mmmmm xx0Sssnnnnnttttt 0D80 0000 post-indexed by a register // st1 {Vt}[],[Xn],#imm LS_2G 0Q00110110011111 xx0Sssnnnnnttttt 0D9F 0000 post-indexed by an immediate -INST6(st2, "st2", 0, ST, IF_EN6B, 0x0C008000, 0x0C808000, 0x0C9F8000, 0x0D200000, 0x0DA00000, 0x0DBF0000) - // C7.2.315 ST2 (multiple structures) +INST6(st2, "st2", ST, IF_EN6B, 0x0C008000, 0x0C808000, 0x0C9F8000, 0x0D200000, 0x0DA00000, 0x0DBF0000) + // ST2 (multiple structures) // st2 {Vt,Vt2},[Xn] LS_2D 0Q00110000000000 1000ssnnnnnttttt 0C00 8000 base register // st2 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100100mmmmm 1000ssnnnnnttttt 0C80 8000 post-indexed by a register // st2 {Vt,Vt2},[Xn],#imm LS_2E 0Q00110010011111 1000ssnnnnnttttt 0C9F 8000 post-indexed by an immediate - // C7.2.316 ST2 (single structure) + // ST2 (single structure) // st2 {Vt,Vt2}[],[Xn] LS_2F 0Q00110100100000 xx0Sssnnnnnttttt 0D20 0000 base register // st2 {Vt,Vt2}[],[Xn],Xm LS_3G 0Q001101101mmmmm xx0Sssnnnnnttttt 0DA0 0000 post-indexed by a register // st2 {Vt,Vt2}[],[Xn],#imm LS_2G 0Q00110110111111 xx0Sssnnnnnttttt 0DBF 0000 post-indexed by an immediate -INST6(st3, "st3", 0, ST, IF_EN6B, 0x0C004000, 0x0C804000, 0x0C9F4000, 0x0D002000, 0x0D802000, 0x0D9F2000) - // C7.2.317 ST3 (multiple structures) +INST6(st3, "st3", ST, IF_EN6B, 0x0C004000, 0x0C804000, 0x0C9F4000, 0x0D002000, 0x0D802000, 0x0D9F2000) + // ST3 (multiple structures) // st3 {Vt-Vt3},[Xn] LS_2D 0Q00110000000000 0100ssnnnnnttttt 0C00 4000 base register // st3 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100100mmmmm 0100ssnnnnnttttt 0C80 4000 post-indexed by a register // st3 {Vt-Vt3},[Xn],#imm LS_2E 0Q00110010011111 0100ssnnnnnttttt 0C9F 4000 post-indexed by an immediate - // C7.2.318 ST3 (single structure) + // ST3 (single structure) // st3 {Vt-Vt3}[],[Xn] LS_2F 0Q00110100000000 xx1Sssnnnnnttttt 0D00 2000 base register // st3 {Vt-Vt3}[],[Xn],Xm LS_3G 0Q001101100mmmmm xx1Sssnnnnnttttt 0D80 2000 post-indexed by a register // st3 {Vt-Vt3}[],[Xn],#imm LS_2G 0Q00110110011111 xx1Sssnnnnnttttt 0D9F 2000 post-indexed by an immediate -INST6(st4, "st4", 0, ST, IF_EN6B, 0x0C000000, 0x0C800000, 0x0C9F0000, 0x0D202000, 0x0DA02000, 0x0DBF2000) - // C7.2.319 ST4 (multiple structures) +INST6(st4, "st4", ST, IF_EN6B, 0x0C000000, 0x0C800000, 0x0C9F0000, 0x0D202000, 0x0DA02000, 0x0DBF2000) + // ST4 (multiple structures) // st4 {Vt-Vt4},[Xn] LS_2D 0Q00110000000000 0000ssnnnnnttttt 0C00 0000 base register // st4 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100100mmmmm 0000ssnnnnnttttt 0C80 0000 post-indexed by a register // st4 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110010011111 0000ssnnnnnttttt 0C9F 0000 post-indexed by an immediate - // C7.2.320 ST4 (single structure) + // ST4 (single structure) // st4 {Vt-Vt4}[],[Xn] LS_2F 0Q00110100100000 xx1Sssnnnnnttttt 0D20 2000 base register // st4 {Vt-Vt4}[],[Xn],Xm LS_3G 0Q001101101mmmmm xx1Sssnnnnnttttt 0DA0 2000 post-indexed by a register // st4 {Vt-Vt4}[],[Xn],#imm LS_2G 0Q00110110111111 xx1Sssnnnnnttttt 0DBF 2000 post-indexed by an immediate -// enum name FP LD/ST LS_2A LS_2B LS_2C LS_3A LS_1A -INST5(ldr, "ldr", 0,LD, IF_EN5A, 0xB9400000, 0xB9400000, 0xB8400000, 0xB8600800, 0x18000000) +// enum name info LS_2A LS_2B LS_2C LS_3A LS_1A +INST5(ldr, "ldr", LD, IF_EN5A, 0xB9400000, 0xB9400000, 0xB8400000, 0xB8600800, 0x18000000) // ldr Rt,[Xn] LS_2A 1X11100101000000 000000nnnnnttttt B940 0000 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3}) // ldr Rt,[Xn+simm9] LS_2C 1X111000010iiiii iiiiPPnnnnnttttt B840 0000 [Xn imm(-256..+255) pre/post/no inc] // ldr Rt,[Xn,(Rm,ext,shl)] LS_3A 1X111000011mmmmm oooS10nnnnnttttt B860 0800 [Xn, ext(Rm) LSL {0,2,3}] // ldr Vt/Rt,[PC+simm19<<2] LS_1A XX011V00iiiiiiii iiiiiiiiiiittttt 1800 0000 [PC +- imm(1MB)] -INST5(ldrsw, "ldrsw", 0,LD, IF_EN5A, 0xB9800000, 0xB9800000, 0xB8800000, 0xB8A00800, 0x98000000) +INST5(ldrsw, "ldrsw", LD, IF_EN5A, 0xB9800000, 0xB9800000, 0xB8800000, 0xB8A00800, 0x98000000) // ldrsw Rt,[Xn] LS_2A 1011100110000000 000000nnnnnttttt B980 0000 // ldrsw Rt,[Xn+pimm12] LS_2B 1011100110iiiiii iiiiiinnnnnttttt B980 0000 imm(0-4095<<2) // ldrsw Rt,[Xn+simm9] LS_2C 10111000100iiiii iiiiPPnnnnnttttt B880 0000 [Xn imm(-256..+255) pre/post/no inc] // ldrsw Rt,[Xn,(Rm,ext,shl)] LS_3A 10111000101mmmmm oooS10nnnnnttttt B8A0 0800 [Xn, ext(Rm) LSL {0,2}] // ldrsw Rt,[PC+simm19<<2] LS_1A 10011000iiiiiiii iiiiiiiiiiittttt 9800 0000 [PC +- imm(1MB)] -// enum name FP LD/ST DV_2G DV_2H DV_2I DV_1A DV_1B -INST5(fmov, "fmov", 0, 0, IF_EN5B, 0x1E204000, 0x1E260000, 0x1E270000, 0x1E201000, 0x0F00F400) +// enum name info DV_2G DV_2H DV_2I DV_1A DV_1B +INST5(fmov, "fmov", 0, IF_EN5B, 0x1E204000, 0x1E260000, 0x1E270000, 0x1E201000, 0x0F00F400) // fmov Vd,Vn DV_2G 000111100X100000 010000nnnnnddddd 1E20 4000 Vd,Vn (scalar) // fmov Rd,Vn DV_2H X00111100X100110 000000nnnnnddddd 1E26 0000 Rd,Vn (scalar, to general) // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn (scalar, from general) // fmov Vd,immfp DV_1A 000111100X1iiiii iii10000000ddddd 1E20 1000 Vd,immfp (scalar) // fmov Vd,immfp DV_1B 0QX0111100000iii 111101iiiiiddddd 0F00 F400 Vd,immfp (immediate vector) -// enum name FP LD/ST DR_3A DR_3B DI_2C DV_3C DV_1B -INST5(orr, "orr", 0, 0, IF_EN5C, 0x2A000000, 0x2A000000, 0x32000000, 0x0EA01C00, 0x0F001400) +// enum name info DR_3A DR_3B DI_2C DV_3C DV_1B +INST5(orr, "orr", 0, IF_EN5C, 0x2A000000, 0x2A000000, 0x32000000, 0x0EA01C00, 0x0F001400) // orr Rd,Rn,Rm DR_3A X0101010000mmmmm 000000nnnnnddddd 2A00 0000 // orr Rd,Rn,(Rm,shk,imm) DR_3B X0101010sh0mmmmm iiiiiinnnnnddddd 2A00 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) // orr Rd,Rn,imm(N,r,s) DI_2C X01100100Nrrrrrr ssssssnnnnnddddd 3200 0000 imm(N,r,s) // orr Vd,Vn,Vm DV_3C 0Q001110101mmmmm 000111nnnnnddddd 0EA0 1C00 Vd,Vn,Vm // orr Vd,imm8 DV_1B 0Q00111100000iii ---101iiiiiddddd 0F00 1400 Vd imm8 (immediate vector) -// enum name FP LD/ST LS_2A LS_2B LS_2C LS_3A -INST4(ldrb, "ldrb", 0,LD, IF_EN4A, 0x39400000, 0x39400000, 0x38400000, 0x38600800) +// enum name info LS_2A LS_2B LS_2C LS_3A +INST4(ldrb, "ldrb", LD, IF_EN4A, 0x39400000, 0x39400000, 0x38400000, 0x38600800) // ldrb Rt,[Xn] LS_2A 0011100101000000 000000nnnnnttttt 3940 0000 // ldrb Rt,[Xn+pimm12] LS_2B 0011100101iiiiii iiiiiinnnnnttttt 3940 0000 imm(0-4095) // ldrb Rt,[Xn+simm9] LS_2C 00111000010iiiii iiiiPPnnnnnttttt 3840 0000 [Xn imm(-256..+255) pre/post/no inc] // ldrb Rt,[Xn,(Rm,ext,shl)] LS_3A 00111000011mmmmm oooS10nnnnnttttt 3860 0800 [Xn, ext(Rm)] -INST4(ldrh, "ldrh", 0,LD, IF_EN4A, 0x79400000, 0x79400000, 0x78400000, 0x78600800) +INST4(ldrh, "ldrh", LD, IF_EN4A, 0x79400000, 0x79400000, 0x78400000, 0x78600800) // ldrh Rt,[Xn] LS_2A 0111100101000000 000000nnnnnttttt 7940 0000 // ldrh Rt,[Xn+pimm12] LS_2B 0111100101iiiiii iiiiiinnnnnttttt 7940 0000 imm(0-4095<<1) // ldrh Rt,[Xn+simm9] LS_2C 01111000010iiiii iiiiPPnnnnnttttt 7840 0000 [Xn imm(-256..+255) pre/post/no inc] // ldrh Rt,[Xn,(Rm,ext,shl)] LS_3A 01111000011mmmmm oooS10nnnnnttttt 7860 0800 [Xn, ext(Rm) LSL {0,1}] -INST4(ldrsb, "ldrsb", 0,LD, IF_EN4A, 0x39800000, 0x39800000, 0x38800000, 0x38A00800) +INST4(ldrsb, "ldrsb", LD, IF_EN4A, 0x39800000, 0x39800000, 0x38800000, 0x38A00800) // ldrsb Rt,[Xn] LS_2A 001110011X000000 000000nnnnnttttt 3980 0000 // ldrsb Rt,[Xn+pimm12] LS_2B 001110011Xiiiiii iiiiiinnnnnttttt 3980 0000 imm(0-4095) // ldrsb Rt,[Xn+simm9] LS_2C 001110001X0iiiii iiii01nnnnnttttt 3880 0000 [Xn imm(-256..+255) pre/post/no inc] // ldrsb Rt,[Xn,(Rm,ext,shl)] LS_3A 001110001X1mmmmm oooS10nnnnnttttt 38A0 0800 [Xn, ext(Rm)] -INST4(ldrsh, "ldrsh", 0,LD, IF_EN4A, 0x79800000, 0x79800000, 0x78800000, 0x78A00800) +INST4(ldrsh, "ldrsh", LD, IF_EN4A, 0x79800000, 0x79800000, 0x78800000, 0x78A00800) // ldrsh Rt,[Xn] LS_2A 011110011X000000 000000nnnnnttttt 7980 0000 // ldrsh Rt,[Xn+pimm12] LS_2B 011110011Xiiiiii iiiiiinnnnnttttt 7980 0000 imm(0-4095<<1) // ldrsh Rt,[Xn+simm9] LS_2C 011110001X0iiiii iiiiPPnnnnnttttt 7880 0000 [Xn imm(-256..+255) pre/post/no inc] // ldrsh Rt,[Xn,(Rm,ext,shl)] LS_3A 011110001X1mmmmm oooS10nnnnnttttt 78A0 0800 [Xn, ext(Rm) LSL {0,1}] -INST4(str, "str", 0,ST, IF_EN4A, 0xB9000000, 0xB9000000, 0xB8000000, 0xB8200800) +INST4(str, "str", ST, IF_EN4A, 0xB9000000, 0xB9000000, 0xB8000000, 0xB8200800) // str Rt,[Xn] LS_2A 1X11100100000000 000000nnnnnttttt B900 0000 // str Rt,[Xn+pimm12] LS_2B 1X11100100iiiiii iiiiiinnnnnttttt B900 0000 imm(0-4095<<{2,3}) // str Rt,[Xn+simm9] LS_2C 1X111000000iiiii iiiiPPnnnnnttttt B800 0000 [Xn imm(-256..+255) pre/post/no inc] // str Rt,[Xn,(Rm,ext,shl)] LS_3A 1X111000001mmmmm oooS10nnnnnttttt B820 0800 [Xn, ext(Rm)] -INST4(strb, "strb", 0,ST, IF_EN4A, 0x39000000, 0x39000000, 0x38000000, 0x38200800) +INST4(strb, "strb", ST, IF_EN4A, 0x39000000, 0x39000000, 0x38000000, 0x38200800) // strb Rt,[Xn] LS_2A 0011100100000000 000000nnnnnttttt 3900 0000 // strb Rt,[Xn+pimm12] LS_2B 0011100100iiiiii iiiiiinnnnnttttt 3900 0000 imm(0-4095) // strb Rt,[Xn+simm9] LS_2C 00111000000iiiii iiiiPPnnnnnttttt 3800 0000 [Xn imm(-256..+255) pre/post/no inc] // strb Rt,[Xn,(Rm,ext,shl)] LS_3A 00111000001mmmmm oooS10nnnnnttttt 3820 0800 [Xn, ext(Rm)] -INST4(strh, "strh", 0,ST, IF_EN4A, 0x79000000, 0x79000000, 0x78000000, 0x78200800) +INST4(strh, "strh", ST, IF_EN4A, 0x79000000, 0x79000000, 0x78000000, 0x78200800) // strh Rt,[Xn] LS_2A 0111100100000000 000000nnnnnttttt 7900 0000 // strh Rt,[Xn+pimm12] LS_2B 0111100100iiiiii iiiiiinnnnnttttt 7900 0000 imm(0-4095<<1) // strh Rt,[Xn+simm9] LS_2C 01111000000iiiii iiiiPPnnnnnttttt 7800 0000 [Xn imm(-256..+255) pre/post/no inc] // strh Rt,[Xn,(Rm,ext,shl)] LS_3A 01111000001mmmmm oooS10nnnnnttttt 7820 0800 [Xn, ext(Rm)] -// enum name FP LD/ST DR_3A DR_3B DR_3C DI_2A -INST4(adds, "adds", 0, 0, IF_EN4B, 0x2B000000, 0x2B000000, 0x2B200000, 0x31000000) +// enum name info DR_3A DR_3B DR_3C DI_2A +INST4(adds, "adds", 0, IF_EN4B, 0x2B000000, 0x2B000000, 0x2B200000, 0x31000000) // adds Rd,Rn,Rm DR_3A X0101011000mmmmm 000000nnnnnddddd 2B00 0000 // adds Rd,Rn,(Rm,shk,imm) DR_3B X0101011sh0mmmmm ssssssnnnnnddddd 2B00 0000 Rm {LSL,LSR,ASR} imm(0-63) // adds Rd,Rn,(Rm,ext,shl) DR_3C X0101011001mmmmm ooosssnnnnnddddd 2B20 0000 ext(Rm) LSL imm(0-4) // adds Rd,Rn,i12 DI_2A X0110001shiiiiii iiiiiinnnnnddddd 3100 0000 imm(i12,sh) -INST4(subs, "subs", 0, 0, IF_EN4B, 0x6B000000, 0x6B000000, 0x6B200000, 0x71000000) +INST4(subs, "subs", 0, IF_EN4B, 0x6B000000, 0x6B000000, 0x6B200000, 0x71000000) // subs Rd,Rn,Rm DR_3A X1101011000mmmmm 000000nnnnnddddd 6B00 0000 // subs Rd,Rn,(Rm,shk,imm) DR_3B X1101011sh0mmmmm ssssssnnnnnddddd 6B00 0000 Rm {LSL,LSR,ASR} imm(0-63) // subs Rd,Rn,(Rm,ext,shl) DR_3C X1101011001mmmmm ooosssnnnnnddddd 6B20 0000 ext(Rm) LSL imm(0-4) // subs Rd,Rn,i12 DI_2A X1110001shiiiiii iiiiiinnnnnddddd 7100 0000 imm(i12,sh) -// enum name FP LD/ST DR_2A DR_2B DR_2C DI_1A -INST4(cmp, "cmp", 0,CMP,IF_EN4C, 0x6B00001F, 0x6B00001F, 0x6B20001F, 0x7100001F) +// enum name info DR_2A DR_2B DR_2C DI_1A +INST4(cmp, "cmp", CMP, IF_EN4C, 0x6B00001F, 0x6B00001F, 0x6B20001F, 0x7100001F) // cmp Rn,Rm DR_2A X1101011000mmmmm 000000nnnnn11111 6B00 001F // cmp Rn,(Rm,shk,imm) DR_2B X1101011sh0mmmmm ssssssnnnnn11111 6B00 001F Rm {LSL,LSR,ASR} imm(0-63) // cmp Rn,(Rm,ext,shl) DR_2C X1101011001mmmmm ooosssnnnnn11111 6B20 001F ext(Rm) LSL imm(0-4) // cmp Rn,i12 DI_1A X111000100iiiiii iiiiiinnnnn11111 7100 001F imm(i12,sh) -INST4(cmn, "cmn", 0,CMP,IF_EN4C, 0x2B00001F, 0x2B00001F, 0x2B20001F, 0x3100001F) +INST4(cmn, "cmn", CMP, IF_EN4C, 0x2B00001F, 0x2B00001F, 0x2B20001F, 0x3100001F) // cmn Rn,Rm DR_2A X0101011000mmmmm 000000nnnnn11111 2B00 001F // cmn Rn,(Rm,shk,imm) DR_2B X0101011sh0mmmmm ssssssnnnnn11111 2B00 001F Rm {LSL,LSR,ASR} imm(0-63) // cmn Rn,(Rm,ext,shl) DR_2C X0101011001mmmmm ooosssnnnnn11111 2B20 001F ext(Rm) LSL imm(0-4) // cmn Rn,i12 DI_1A X0110001shiiiiii iiiiiinnnnn11111 3100 001F imm(0-4095) -// enum name FP LD/ST DV_3B DV_3D DV_3BI DV_3DI -INST4(fmul, "fmul", 0, 0, IF_EN4D, 0x2E20DC00, 0x1E200800, 0x0F809000, 0x5F809000) +// enum name info DV_3B DV_3D DV_3BI DV_3DI +INST4(fmul, "fmul", 0, IF_EN4D, 0x2E20DC00, 0x1E200800, 0x0F809000, 0x5F809000) // fmul Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 110111nnnnnddddd 2E20 DC00 Vd,Vn,Vm (vector) // fmul Vd,Vn,Vm DV_3D 000111100X1mmmmm 000010nnnnnddddd 1E20 0800 Vd,Vn,Vm (scalar) // fmul Vd,Vn,Vm[] DV_3BI 0Q0011111XLmmmmm 1001H0nnnnnddddd 0F80 9000 Vd,Vn,Vm[] (vector by elem) // fmul Vd,Vn,Vm[] DV_3DI 010111111XLmmmmm 1001H0nnnnnddddd 5F80 9000 Vd,Vn,Vm[] (scalar by elem) -INST4(fmulx, "fmulx", 0, 0, IF_EN4D, 0x0E20DC00, 0x5E20DC00, 0x2F809000, 0x7F809000) +INST4(fmulx, "fmulx", 0, IF_EN4D, 0x0E20DC00, 0x5E20DC00, 0x2F809000, 0x7F809000) // fmulx Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 110111nnnnnddddd 0E20 DC00 Vd,Vn,Vm (vector) // fmulx Vd,Vn,Vm DV_3D 010111100X1mmmmm 110111nnnnnddddd 5E20 DC00 Vd,Vn,Vm (scalar) // fmulx Vd,Vn,Vm[] DV_3BI 0Q1011111XLmmmmm 1001H0nnnnnddddd 2F80 9000 Vd,Vn,Vm[] (vector by elem) // fmulx Vd,Vn,Vm[] DV_3DI 011111111XLmmmmm 1001H0nnnnnddddd 7F80 9000 Vd,Vn,Vm[] (scalar by elem) -// enum name FP LD/ST DR_3A DR_3B DI_2C DV_3C -INST4(and, "and", 0, 0, IF_EN4E, 0x0A000000, 0x0A000000, 0x12000000, 0x0E201C00) +// enum name info DR_3A DR_3B DI_2C DV_3C +INST4(and, "and", 0, IF_EN4E, 0x0A000000, 0x0A000000, 0x12000000, 0x0E201C00) // and Rd,Rn,Rm DR_3A X0001010000mmmmm 000000nnnnnddddd 0A00 0000 // and Rd,Rn,(Rm,shk,imm) DR_3B X0001010sh0mmmmm iiiiiinnnnnddddd 0A00 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) // and Rd,Rn,imm(N,r,s) DI_2C X00100100Nrrrrrr ssssssnnnnnddddd 1200 0000 imm(N,r,s) // and Vd,Vn,Vm DV_3C 0Q001110001mmmmm 000111nnnnnddddd 0E20 1C00 Vd,Vn,Vm -INST4(eor, "eor", 0, 0, IF_EN4E, 0x4A000000, 0x4A000000, 0x52000000, 0x2E201C00) +INST4(eor, "eor", 0, IF_EN4E, 0x4A000000, 0x4A000000, 0x52000000, 0x2E201C00) // eor Rd,Rn,Rm DR_3A X1001010000mmmmm 000000nnnnnddddd 4A00 0000 // eor Rd,Rn,(Rm,shk,imm) DR_3B X1001010sh0mmmmm iiiiiinnnnnddddd 4A00 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) // eor Rd,Rn,imm(N,r,s) DI_2C X10100100Nrrrrrr ssssssnnnnnddddd 5200 0000 imm(N,r,s) // eor Vd,Vn,Vm DV_3C 0Q101110001mmmmm 000111nnnnnddddd 2E20 1C00 Vd,Vn,Vm -// enum name FP LD/ST DR_3A DR_3B DV_3C DV_1B -INST4(bic, "bic", 0, 0, IF_EN4F, 0x0A200000, 0x0A200000, 0x0E601C00, 0x2F001400) +// enum name info DR_3A DR_3B DV_3C DV_1B +INST4(bic, "bic", 0, IF_EN4F, 0x0A200000, 0x0A200000, 0x0E601C00, 0x2F001400) // bic Rd,Rn,Rm DR_3A X0001010001mmmmm 000000nnnnnddddd 0A20 0000 // bic Rd,Rn,(Rm,shk,imm) DR_3B X0001010sh1mmmmm iiiiiinnnnnddddd 0A20 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) // bic Vd,Vn,Vm DV_3C 0Q001110011mmmmm 000111nnnnnddddd 0E60 1C00 Vd,Vn,Vm // bic Vd,imm8 DV_1B 0Q10111100000iii ---101iiiiiddddd 2F00 1400 Vd imm8 (immediate vector) -// enum name FP LD/ST DR_2E DR_2F DV_2M DV_2L -INST4(neg, "neg", 0, 0, IF_EN4G, 0x4B0003E0, 0x4B0003E0, 0x2E20B800, 0x7E20B800) +// enum name info DR_2E DR_2F DV_2M DV_2L +INST4(neg, "neg", 0, IF_EN4G, 0x4B0003E0, 0x4B0003E0, 0x2E20B800, 0x7E20B800) // neg Rd,Rm DR_2E X1001011000mmmmm 00000011111ddddd 4B00 03E0 // neg Rd,(Rm,shk,imm) DR_2F X1001011sh0mmmmm ssssss11111ddddd 4B00 03E0 Rm {LSL,LSR,ASR} imm(0-63) // neg Vd,Vn DV_2M 0Q101110XX100000 101110nnnnnddddd 2E20 B800 Vd,Vn (vector) // neg Vd,Vn DV_2L 01111110XX100000 101110nnnnnddddd 7E20 B800 Vd,Vn (scalar) -// enum name FP LD/ST DV_3E DV_3A DV_2L DV_2M -INST4(cmeq, "cmeq", 0, 0, IF_EN4H, 0x7EE08C00, 0x2E208C00, 0x5E209800, 0x0E209800) +// enum name info DV_3E DV_3A DV_2L DV_2M +INST4(cmeq, "cmeq", 0, IF_EN4H, 0x7EE08C00, 0x2E208C00, 0x5E209800, 0x0E209800) // cmeq Vd,Vn,Vm DV_3E 01111110111mmmmm 100011nnnnnddddd 7EE0 8C00 Vd,Vn,Vm (scalar) // cmeq Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100011nnnnnddddd 2E20 8C00 Vd,Vn,Vm (vector) // cmeq Vd,Vn DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn (scalar) // cmeq Vd,Vn DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn (vector) -INST4(cmge, "cmge", 0, 0, IF_EN4H, 0x5EE03C00, 0x0E203C00, 0x7E208800, 0x2E208800) +INST4(cmge, "cmge", 0, IF_EN4H, 0x5EE03C00, 0x0E203C00, 0x7E208800, 0x2E208800) // cmge Vd,Vn,Vm DV_3E 01011110111mmmmm 001111nnnnnddddd 5EE0 3C00 Vd,Vn,Vm (scalar) // cmge Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 001111nnnnnddddd 0E20 3C00 Vd,Vn,Vm (vector) // cmge Vd,Vn DV_2L 01111110XX100000 100010nnnnnddddd 5E20 8800 Vd,Vn (scalar) // cmge Vd,Vn DV_2M 0Q101110XX100000 100010nnnnnddddd 2E20 8800 Vd,Vn (vector) -INST4(cmgt, "cmgt", 0, 0, IF_EN4H, 0x5EE03400, 0x0E203400, 0x5E208800, 0x0E208800) +INST4(cmgt, "cmgt", 0, IF_EN4H, 0x5EE03400, 0x0E203400, 0x5E208800, 0x0E208800) // cmgt Vd,Vn,Vm DV_3E 01011110111mmmmm 001101nnnnnddddd 5EE0 3400 Vd,Vn,Vm (scalar) // cmgt Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 001101nnnnnddddd 0E20 3400 Vd,Vn,Vm (vector) // cmgt Vd,Vn DV_2L 01011110XX100000 100010nnnnnddddd 5E20 8800 Vd,Vn (scalar) // cmgt Vd,Vn DV_2M 0Q001110XX100000 101110nnnnnddddd 0E20 8800 Vd,Vn (vector) -// enum name FP LD/ST DV_3D DV_3B DV_2G DV_2A -INST4(fcmeq, "fcmeq", 0, 0, IF_EN4I, 0x5E20E400, 0x0E20E400, 0x5EA0D800, 0x0EA0D800) +// enum name info DV_3D DV_3B DV_2G DV_2A +INST4(fcmeq, "fcmeq", 0, IF_EN4I, 0x5E20E400, 0x0E20E400, 0x5EA0D800, 0x0EA0D800) // fcmeq Vd,Vn,Vm DV_3D 010111100X1mmmmm 111001nnnnnddddd 5E20 E400 Vd Vn Vm (scalar) // fcmeq Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111001nnnnnddddd 0E20 E400 Vd,Vn,Vm (vector) // fcmeq Vd,Vn DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn (scalar) // fcmeq Vd,Vn DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn (vector) -INST4(fcmge, "fcmge", 0, 0, IF_EN4I, 0x7E20E400, 0x2E20E400, 0x7EA0C800, 0x2EA0C800) +INST4(fcmge, "fcmge", 0, IF_EN4I, 0x7E20E400, 0x2E20E400, 0x7EA0C800, 0x2EA0C800) // fcmge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111001nnnnnddddd 7E20 E400 Vd Vn Vm (scalar) // fcmge Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 111001nnnnnddddd 2E20 E400 Vd,Vn,Vm (vector) // fcmge Vd,Vn DV_2G 011111101X100000 110010nnnnnddddd 7EA0 E800 Vd Vn (scalar) // fcmge Vd,Vn DV_2A 0Q1011101X100000 110010nnnnnddddd 2EA0 C800 Vd Vn (vector) -INST4(fcmgt, "fcmgt", 0, 0, IF_EN4I, 0x7EA0E400, 0x2EA0E400, 0x5EA0C800, 0x0EA0C800) +INST4(fcmgt, "fcmgt", 0, IF_EN4I, 0x7EA0E400, 0x2EA0E400, 0x5EA0C800, 0x0EA0C800) // fcmgt Vd,Vn,Vm DV_3D 011111101X1mmmmm 111001nnnnnddddd 7EA0 E400 Vd Vn Vm (scalar) // fcmgt Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 111001nnnnnddddd 2EA0 E400 Vd,Vn,Vm (vector) // fcmgt Vd,Vn DV_2G 010111101X100000 110010nnnnnddddd 5EA0 E800 Vd Vn (scalar) // fcmgt Vd,Vn DV_2A 0Q0011101X100000 110010nnnnnddddd 0EA0 C800 Vd Vn (vector) -// enum name FP LD/ST DR_3A DR_3B DI_2C -INST3(ands, "ands", 0, 0, IF_EN3A, 0x6A000000, 0x6A000000, 0x72000000) +// enum name info DV_2N DV_2O DV_3E DV_3A +INST4(sqshl, "sqshl", 0, IF_EN4J, 0x5F007400, 0x0F007400, 0x5E204C00, 0x0E204C00) + // sqshl Vd,Vn,imm DV_2N 010111110iiiiiii 011101nnnnnddddd 5F00 7400 Vd Vn imm (left shift - scalar) + // sqshl Vd,Vn,imm DV_2O 0Q0011110iiiiiii 011101nnnnnddddd 0F00 7400 Vd Vn imm (left shift - vector) + // sqshl Vd,Vn,Vm DV_3E 01011110XX1mmmmm 010011nnnnnddddd 5E20 4C00 Vd Vn Vm (scalar) + // sqshl Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 010011nnnnnddddd 0E20 4C00 Vd Vn Vm (vector) + +INST4(uqshl, "uqshl", 0, IF_EN4J, 0x7F007400, 0x2F007400, 0x7E204C00, 0x2E204C00) + // uqshl Vd,Vn,imm DV_2N 011111110iiiiiii 011101nnnnnddddd 7F00 7400 Vd Vn imm (left shift - scalar) + // uqshl Vd,Vn,imm DV_2O 0Q1011110iiiiiii 011101nnnnnddddd 2F00 7400 Vd Vn imm (left shift - vector) + // uqshl Vd,Vn,Vm DV_3E 01111110XX1mmmmm 010011nnnnnddddd 7E20 4C00 Vd Vn Vm (scalar) + // uqshl Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 010011nnnnnddddd 2E20 4C00 Vd Vn Vm (vector) + +// enum name info DR_3A DR_3B DI_2C +INST3(ands, "ands", 0, IF_EN3A, 0x6A000000, 0x6A000000, 0x72000000) // ands Rd,Rn,Rm DR_3A X1101010000mmmmm 000000nnnnnddddd 6A00 0000 // ands Rd,Rn,(Rm,shk,imm) DR_3B X1101010sh0mmmmm iiiiiinnnnnddddd 6A00 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) // ands Rd,Rn,imm(N,r,s) DI_2C X11100100Nrrrrrr ssssssnnnnnddddd 7200 0000 imm(N,r,s) -// enum name FP LD/ST DR_2A DR_2B DI_1C -INST3(tst, "tst", 0, 0, IF_EN3B, 0x6A00001F, 0x6A00001F, 0x7200001F) +// enum name info DR_2A DR_2B DI_1C +INST3(tst, "tst", 0, IF_EN3B, 0x6A00001F, 0x6A00001F, 0x7200001F) // tst Rn,Rm DR_2A X1101010000mmmmm 000000nnnnn11111 6A00 001F // tst Rn,(Rm,shk,imm) DR_2B X1101010sh0mmmmm iiiiiinnnnn11111 6A00 001F Rm {LSL,LSR,ASR,ROR} imm(0-63) // tst Rn,imm(N,r,s) DI_1C X11100100Nrrrrrr ssssssnnnnn11111 7200 001F imm(N,r,s) -// enum name FP LD/ST DR_3A DR_3B DV_3C -INST3(orn, "orn", 0, 0, IF_EN3C, 0x2A200000, 0x2A200000, 0x0EE01C00) +// enum name info DR_3A DR_3B DV_3C +INST3(orn, "orn", 0, IF_EN3C, 0x2A200000, 0x2A200000, 0x0EE01C00) // orn Rd,Rn,Rm DR_3A X0101010001mmmmm 000000nnnnnddddd 2A20 0000 // orn Rd,Rn,(Rm,shk,imm) DR_3B X0101010sh1mmmmm iiiiiinnnnnddddd 2A20 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) // orn Vd,Vn,Vm DV_3C 0Q001110111mmmmm 000111nnnnnddddd 0EE0 1C00 Vd,Vn,Vm -// enum name FP LD/ST DV_2C DV_2D DV_2E -INST3(dup, "dup", 0, 0, IF_EN3D, 0x0E000C00, 0x0E000400, 0x5E000400) +// enum name info DV_2C DV_2D DV_2E +INST3(dup, "dup", 0, IF_EN3D, 0x0E000C00, 0x0E000400, 0x5E000400) // dup Vd,Rn DV_2C 0Q001110000iiiii 000011nnnnnddddd 0E00 0C00 Vd,Rn (vector from general) // dup Vd,Vn[] DV_2D 0Q001110000iiiii 000001nnnnnddddd 0E00 0400 Vd,Vn[] (vector by elem) // dup Vd,Vn[] DV_2E 01011110000iiiii 000001nnnnnddddd 5E00 0400 Vd,Vn[] (scalar by elem) -// enum name FP LD/ST DV_3B DV_3BI DV_3DI -INST3(fmla, "fmla", 0, 0, IF_EN3E, 0x0E20CC00, 0x0F801000, 0x5F801000) +// enum name info DV_3B DV_3BI DV_3DI +INST3(fmla, "fmla", 0, IF_EN3E, 0x0E20CC00, 0x0F801000, 0x5F801000) // fmla Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 110011nnnnnddddd 0E20 CC00 Vd,Vn,Vm (vector) // fmla Vd,Vn,Vm[] DV_3BI 0Q0011111XLmmmmm 0001H0nnnnnddddd 0F80 1000 Vd,Vn,Vm[] (vector by elem) // fmla Vd,Vn,Vm[] DV_3DI 010111111XLmmmmm 0001H0nnnnnddddd 5F80 1000 Vd,Vn,Vm[] (scalar by elem) -INST3(fmls, "fmls", 0, 0, IF_EN3E, 0x0EA0CC00, 0x0F805000, 0x5F805000) +INST3(fmls, "fmls", 0, IF_EN3E, 0x0EA0CC00, 0x0F805000, 0x5F805000) // fmls Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 110011nnnnnddddd 0EA0 CC00 Vd,Vn,Vm (vector) // fmls Vd,Vn,Vm[] DV_3BI 0Q0011111XLmmmmm 0101H0nnnnnddddd 0F80 5000 Vd,Vn,Vm[] (vector by elem) // fmls Vd,Vn,Vm[] DV_3DI 010111111XLmmmmm 0101H0nnnnnddddd 5F80 5000 Vd,Vn,Vm[] (scalar by elem) -// enum name FP LD/ST DV_2A DV_2G DV_2H -INST3(fcvtas, "fcvtas", 0, 0, IF_EN3F, 0x0E21C800, 0x5E21C800, 0x1E240000) +// enum name info DV_2A DV_2G DV_2H +INST3(fcvtas, "fcvtas", 0, IF_EN3F, 0x0E21C800, 0x5E21C800, 0x1E240000) // fcvtas Vd,Vn DV_2A 0Q0011100X100001 110010nnnnnddddd 0E21 C800 Vd,Vn (vector) // fcvtas Vd,Vn DV_2G 010111100X100001 110010nnnnnddddd 5E21 C800 Vd,Vn (scalar) // fcvtas Rd,Vn DV_2H X00111100X100100 000000nnnnnddddd 1E24 0000 Rd,Vn (scalar, to general) -INST3(fcvtau, "fcvtau", 0, 0, IF_EN3F, 0x2E21C800, 0x7E21C800, 0x1E250000) +INST3(fcvtau, "fcvtau", 0, IF_EN3F, 0x2E21C800, 0x7E21C800, 0x1E250000) // fcvtau Vd,Vn DV_2A 0Q1011100X100001 111010nnnnnddddd 2E21 C800 Vd,Vn (vector) // fcvtau Vd,Vn DV_2G 011111100X100001 111010nnnnnddddd 7E21 C800 Vd,Vn (scalar) // fcvtau Rd,Vn DV_2H X00111100X100101 000000nnnnnddddd 1E25 0000 Rd,Vn (scalar, to general) -INST3(fcvtms, "fcvtms", 0, 0, IF_EN3F, 0x0E21B800, 0x5E21B800, 0x1E300000) +INST3(fcvtms, "fcvtms", 0, IF_EN3F, 0x0E21B800, 0x5E21B800, 0x1E300000) // fcvtms Vd,Vn DV_2A 0Q0011100X100001 101110nnnnnddddd 0E21 B800 Vd,Vn (vector) // fcvtms Vd,Vn DV_2G 010111100X100001 101110nnnnnddddd 5E21 B800 Vd,Vn (scalar) // fcvtms Rd,Vn DV_2H X00111100X110000 000000nnnnnddddd 1E30 0000 Rd,Vn (scalar, to general) -INST3(fcvtmu, "fcvtmu", 0, 0, IF_EN3F, 0x2E21B800, 0x7E21B800, 0x1E310000) +INST3(fcvtmu, "fcvtmu", 0, IF_EN3F, 0x2E21B800, 0x7E21B800, 0x1E310000) // fcvtmu Vd,Vn DV_2A 0Q1011100X100001 101110nnnnnddddd 2E21 B800 Vd,Vn (vector) // fcvtmu Vd,Vn DV_2G 011111100X100001 101110nnnnnddddd 7E21 B800 Vd,Vn (scalar) // fcvtmu Rd,Vn DV_2H X00111100X110001 000000nnnnnddddd 1E31 0000 Rd,Vn (scalar, to general) -INST3(fcvtns, "fcvtns", 0, 0, IF_EN3F, 0x0E21A800, 0x5E21A800, 0x1E200000) +INST3(fcvtns, "fcvtns", 0, IF_EN3F, 0x0E21A800, 0x5E21A800, 0x1E200000) // fcvtns Vd,Vn DV_2A 0Q0011100X100001 101010nnnnnddddd 0E21 A800 Vd,Vn (vector) // fcvtns Vd,Vn DV_2G 010111100X100001 101010nnnnnddddd 5E21 A800 Vd,Vn (scalar) // fcvtns Rd,Vn DV_2H X00111100X100000 000000nnnnnddddd 1E20 0000 Rd,Vn (scalar, to general) -INST3(fcvtnu, "fcvtnu", 0, 0, IF_EN3F, 0x2E21A800, 0x7E21A800, 0x1E210000) +INST3(fcvtnu, "fcvtnu", 0, IF_EN3F, 0x2E21A800, 0x7E21A800, 0x1E210000) // fcvtnu Vd,Vn DV_2A 0Q1011100X100001 101010nnnnnddddd 2E21 A800 Vd,Vn (vector) // fcvtnu Vd,Vn DV_2G 011111100X100001 101010nnnnnddddd 7E21 A800 Vd,Vn (scalar) // fcvtnu Rd,Vn DV_2H X00111100X100001 000000nnnnnddddd 1E21 0000 Rd,Vn (scalar, to general) -INST3(fcvtps, "fcvtps", 0, 0, IF_EN3F, 0x0EA1A800, 0x5EA1A800, 0x1E280000) +INST3(fcvtps, "fcvtps", 0, IF_EN3F, 0x0EA1A800, 0x5EA1A800, 0x1E280000) // fcvtps Vd,Vn DV_2A 0Q0011101X100001 101010nnnnnddddd 0EA1 A800 Vd,Vn (vector) // fcvtps Vd,Vn DV_2G 010111101X100001 101010nnnnnddddd 5EA1 A800 Vd,Vn (scalar) // fcvtps Rd,Vn DV_2H X00111100X101000 000000nnnnnddddd 1E28 0000 Rd,Vn (scalar, to general) -INST3(fcvtpu, "fcvtpu", 0, 0, IF_EN3F, 0x2EA1A800, 0x7EA1A800, 0x1E290000) +INST3(fcvtpu, "fcvtpu", 0, IF_EN3F, 0x2EA1A800, 0x7EA1A800, 0x1E290000) // fcvtpu Vd,Vn DV_2A 0Q1011101X100001 101010nnnnnddddd 2EA1 A800 Vd,Vn (vector) // fcvtpu Vd,Vn DV_2G 011111101X100001 101010nnnnnddddd 7EA1 A800 Vd,Vn (scalar) // fcvtpu Rd,Vn DV_2H X00111100X101001 000000nnnnnddddd 1E29 0000 Rd,Vn (scalar, to general) -INST3(fcvtzs, "fcvtzs", 0, 0, IF_EN3F, 0x0EA1B800, 0x5EA1B800, 0x1E380000) +INST3(fcvtzs, "fcvtzs", 0, IF_EN3F, 0x0EA1B800, 0x5EA1B800, 0x1E380000) // fcvtzs Vd,Vn DV_2A 0Q0011101X100001 101110nnnnnddddd 0EA1 B800 Vd,Vn (vector) // fcvtzs Vd,Vn DV_2G 010111101X100001 101110nnnnnddddd 5EA1 B800 Vd,Vn (scalar) // fcvtzs Rd,Vn DV_2H X00111100X111000 000000nnnnnddddd 1E38 0000 Rd,Vn (scalar, to general) -INST3(fcvtzu, "fcvtzu", 0, 0, IF_EN3F, 0x2EA1B800, 0x7EA1B800, 0x1E390000) +INST3(fcvtzu, "fcvtzu", 0, IF_EN3F, 0x2EA1B800, 0x7EA1B800, 0x1E390000) // fcvtzu Vd,Vn DV_2A 0Q1011101X100001 101110nnnnnddddd 2EA1 B800 Vd,Vn (vector) // fcvtzu Vd,Vn DV_2G 011111101X100001 101110nnnnnddddd 7EA1 B800 Vd,Vn (scalar) // fcvtzu Rd,Vn DV_2H X00111100X111001 000000nnnnnddddd 1E39 0000 Rd,Vn (scalar, to general) -// enum name FP LD/ST DV_2A DV_2G DV_2I -INST3(scvtf, "scvtf", 0, 0, IF_EN3G, 0x0E21D800, 0x5E21D800, 0x1E220000) +// enum name info DV_2A DV_2G DV_2I +INST3(scvtf, "scvtf", 0, IF_EN3G, 0x0E21D800, 0x5E21D800, 0x1E220000) // scvtf Vd,Vn DV_2A 0Q0011100X100001 110110nnnnnddddd 0E21 D800 Vd,Vn (vector) // scvtf Vd,Vn DV_2G 010111100X100001 110110nnnnnddddd 7E21 D800 Vd,Vn (scalar) // scvtf Rd,Vn DV_2I X00111100X100010 000000nnnnnddddd 1E22 0000 Vd,Rn (scalar, from general) -INST3(ucvtf, "ucvtf", 0, 0, IF_EN3G, 0x2E21D800, 0x7E21D800, 0x1E230000) +INST3(ucvtf, "ucvtf", 0, IF_EN3G, 0x2E21D800, 0x7E21D800, 0x1E230000) // ucvtf Vd,Vn DV_2A 0Q1011100X100001 110110nnnnnddddd 2E21 D800 Vd,Vn (vector) // ucvtf Vd,Vn DV_2G 011111100X100001 110110nnnnnddddd 7E21 D800 Vd,Vn (scalar) // ucvtf Rd,Vn DV_2I X00111100X100011 000000nnnnnddddd 1E23 0000 Vd,Rn (scalar, from general) -INST3(mul, "mul", 0, 0, IF_EN3H, 0x1B007C00, 0x0E209C00, 0x0F008000) +INST3(mul, "mul", 0, IF_EN3H, 0x1B007C00, 0x0E209C00, 0x0F008000) // mul Rd,Rn,Rm DR_3A X0011011000mmmmm 011111nnnnnddddd 1B00 7C00 // mul Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 100111nnnnnddddd 0E20 9C00 Vd,Vn,Vm (vector) // mul Vd,Vn,Vm[] DV_3AI 0Q001111XXLMmmmm 1000H0nnnnnddddd 0F00 8000 Vd,Vn,Vm[] (vector by elem) -// enum name FP LD/ST DR_2E DR_2F DV_2M -INST3(mvn, "mvn", 0, 0, IF_EN3I, 0x2A2003E0, 0x2A2003E0, 0x2E205800) +// enum name info DR_2E DR_2F DV_2M +INST3(mvn, "mvn", 0, IF_EN3I, 0x2A2003E0, 0x2A2003E0, 0x2E205800) // mvn Rd,Rm DR_2E X0101010001mmmmm 00000011111ddddd 2A20 03E0 // mvn Rd,(Rm,shk,imm) DR_2F X0101010sh1mmmmm iiiiii11111ddddd 2A20 03E0 Rm {LSL,LSR,ASR} imm(0-63) // mvn Vd,Vn DV_2M 0Q10111000100000 010110nnnnnddddd 2E20 5800 Vd,Vn (vector) -// enum name FP LD/ST LS_2D LS_3F LS_2E -INST3(ld1_2regs,"ld1", 0,LD, IF_EN3J, 0x0C40A000, 0x0CC0A000, 0x0CDFA000) - // C7.2.170 LD1 (multiple structures, two registers variant) +// enum name info LS_2D LS_3F LS_2E +INST3(ld1_2regs, "ld1", LD, IF_EN3J, 0x0C40A000, 0x0CC0A000, 0x0CDFA000) + // LD1 (multiple structures, two registers variant) // ld1 {Vt,Vt2},[Xn] LS_2D 0Q00110001000000 1010ssnnnnnttttt 0C40 A000 base register // ld1 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100110mmmmm 1010ssnnnnnttttt 0CC0 A000 post-indexed by a register // ld1 {Vt,Vt2},[Xn],#imm LS_2E 0Q00110011011111 1010ssnnnnnttttt 0CDF A000 post-indexed by an immediate -INST3(ld1_3regs,"ld1", 0,LD, IF_EN3J, 0x0C406000, 0x0CC06000, 0x0CDF6000) - // C7.2.170 LD1 (multiple structures, three registers variant) +INST3(ld1_3regs, "ld1", LD, IF_EN3J, 0x0C406000, 0x0CC06000, 0x0CDF6000) + // LD1 (multiple structures, three registers variant) // ld1 {Vt-Vt3},[Xn] LS_2D 0Q00110001000000 0110ssnnnnnttttt 0C40 6000 base register // ld1 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100110mmmmm 0110ssnnnnnttttt 0CC0 6000 post-indexed by a register // ld1 {Vt-Vt3},[Xn],#imm LS_2E 0Q00110011011111 0110ssnnnnnttttt 0CDF 6000 post-indexed by an immediate -INST3(ld1_4regs,"ld1", 0,LD, IF_EN3J, 0x0C402000, 0x0CC02000, 0x0CDF2000) - // C7.2.170 LD1 (multiple structures, four registers variant) +INST3(ld1_4regs, "ld1", LD, IF_EN3J, 0x0C402000, 0x0CC02000, 0x0CDF2000) + // LD1 (multiple structures, four registers variant) // ld1 {Vt-Vt4},[Xn] LS_2D 0Q00110001000000 0010ssnnnnnttttt 0C40 2000 base register // ld1 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100110mmmmm 0010ssnnnnnttttt 0CC0 2000 post-indexed by a register // ld1 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110011011111 0010ssnnnnnttttt 0CDF 2000 post-indexed by an immediate -INST3(st1_2regs,"st1", 0,ST, IF_EN3J, 0x0C00A000, 0x0C80A000, 0x0C9FA000) - // C7.2.313 ST1 (multiple structures, two registers variant) +INST3(st1_2regs, "st1", ST, IF_EN3J, 0x0C00A000, 0x0C80A000, 0x0C9FA000) + // ST1 (multiple structures, two registers variant) // st1 {Vt,Vt2},[Xn] LS_2D 0Q00110000000000 1010ssnnnnnttttt 0C00 A000 base register // st1 {Vt,Vt2},[Xn],Xm LS_3F 0Q001100100mmmmm 1010ssnnnnnttttt 0C80 A000 post-indexed by a register // st1 {Vt,Vt2},[Xn],#imm LS_2E 0Q00110010011111 1010ssnnnnnttttt 0C9F A000 post-indexed by an immediate -INST3(st1_3regs,"st1", 0,ST, IF_EN3J, 0x0C006000, 0x0C806000, 0x0C9F6000) - // C7.2.313 ST1 (multiple structures, three registers variant) +INST3(st1_3regs, "st1", ST, IF_EN3J, 0x0C006000, 0x0C806000, 0x0C9F6000) + // ST1 (multiple structures, three registers variant) // st1 {Vt-Vt3},[Xn] LS_2D 0Q00110000000000 0110ssnnnnnttttt 0C00 6000 base register // st1 {Vt-Vt3},[Xn],Xm LS_3F 0Q001100100mmmmm 0110XXnnnnnttttt 0C80 6000 post-indexed by a register // st1 {Vt-Vt3},[Xn],#imm LS_2E 0Q00110010011111 0110XXnnnnnttttt 0C9F 6000 post-indexed by an immediate -INST3(st1_4regs,"st1", 0,ST, IF_EN3J, 0x0C002000, 0x0C802000, 0x0C9F2000) - // C7.2.313 ST1 (multiple structures, four registers variant) +INST3(st1_4regs, "st1", ST, IF_EN3J, 0x0C002000, 0x0C802000, 0x0C9F2000) + // ST1 (multiple structures, four registers variant) // st1 {Vt-Vt4},[Xn] LS_2D 0Q00110000000000 0010XXnnnnnttttt 0C00 2000 base register // st1 {Vt-Vt4},[Xn],Xm LS_3F 0Q001100100mmmmm 0010XXnnnnnttttt 0C80 2000 post-indexed by a register // st1 {Vt-Vt4},[Xn],#imm LS_2E 0Q00110010011111 0010XXnnnnnttttt 0C9F 2000 post-indexed by an immediate -INST3(ld1r, "ld1r", 0,LD, IF_EN3J, 0x0D40C000, 0x0DC0C000, 0x0DDFC000) - // C7.2.172 LD1R +INST3(ld1r, "ld1r", LD, IF_EN3J, 0x0D40C000, 0x0DC0C000, 0x0DDFC000) // ld1r {Vt},[Xn] LS_2D 0Q00110101000000 1100ssnnnnnttttt 0D40 C000 base register // ld1r {Vt},[Xn],Xm LS_3F 0Q001101110mmmmm 1100ssnnnnnttttt 0DC0 C000 post-indexed by a register // ld1r {Vt},[Xn],#1 LS_2E 0Q00110111011111 1100ssnnnnnttttt 0DDF C000 post-indexed by an immediate -INST3(ld2r, "ld2r", 0,LD, IF_EN3J, 0x0D60C000, 0x0DE0C000, 0x0DFFC000) - // C7.2.175 LD2R +INST3(ld2r, "ld2r", LD, IF_EN3J, 0x0D60C000, 0x0DE0C000, 0x0DFFC000) // ld2r {Vt,Vt2},[Xn] LS_2D 0Q00110101100000 1100ssnnnnnttttt 0D60 C000 base register // ld2r {Vt,Vt2},[Xn],Xm LS_3F 0Q001101111mmmmm 1100ssnnnnnttttt 0DE0 C000 post-indexed by a register // ld2r {Vt,Vt2},[Xn],#2 LS_2E 0Q00110111111111 1100ssnnnnnttttt 0DFF C000 post-indexed by an immediate -INST3(ld3r, "ld3r", 0,LD, IF_EN3J, 0x0D40E000, 0x0DC0E000, 0x0DDFE000) - // C7.2.178 LD3R +INST3(ld3r, "ld3r", LD, IF_EN3J, 0x0D40E000, 0x0DC0E000, 0x0DDFE000) // ld3r {Vt-Vt3},[Xn] LS_2D 0Q00110101000000 1110ssnnnnnttttt 0D40 E000 base register // ld3r {Vt-Vt3},[Xn],Xm LS_3F 0Q001101110mmmmm 1110ssnnnnnttttt 0DC0 E000 post-indexed by a register // ld3r {Vt-Vt3},[Xn],#4 LS_2E 0Q00110111011111 1110ssnnnnnttttt 0DDF E000 post-indexed by an immediate -INST3(ld4r, "ld4r", 0,LD, IF_EN3J, 0x0D60E000, 0x0DE0E000, 0x0DFFE000) - // C7.2.181 LD4R +INST3(ld4r, "ld4r", LD, IF_EN3J, 0x0D60E000, 0x0DE0E000, 0x0DFFE000) // ld4r {Vt-Vt4},[Xn] LS_2D 0Q00110101100000 1110ssnnnnnttttt 0D60 E000 base register // ld4r {Vt-Vt4},[Xn],Xm LS_3F 0Q001101111mmmmm 1110ssnnnnnttttt 0DE0 E000 post-indexed by a register // ld4r {Vt-Vt4},[Xn],#8 LS_2E 0Q00110111111111 1110ssnnnnnttttt 0DFF E000 post-indexed by an immediate -INST3(smull, "smull", 0, 0, IF_EN3K, 0x9B207C00, 0x0E20C000, 0x0F00A000) - // C6.2.243 SMULL - // C7.2.272 SMULL, SMULL2 (by element) - // C7.2.273 SMULL, SMULL2 (vector) +INST3(smull, "smull", 0, IF_EN3K, 0x9B207C00, 0x0E20C000, 0x0F00A000) // smull Rd,Rn,Rm DR_3A 10011011001mmmmm 011111nnnnnddddd 9B20 7C00 // smull Vd,Vn,Vm DV_3H 0000111000100000 1100000000000000 0E20 C000 Vd,Vn,Vm (vector) // smull Vd,Vn,Vm[] DV_3HI 00001111XXLMmmmm 1010H0nnnnnddddd 0F00 A000 Vd,Vn,Vm[] (vector by elem) -INST3(umull, "umull", 0, 0, IF_EN3K, 0x9BA07C00, 0x2E20C000, 0x2F00A000) - // C6.2.340 UMULL - // C7.2.362 UMULL, UMULL2 (by element) - // C7.2.363 UMULL, UMULL2 (vector) +INST3(umull, "umull", 0, IF_EN3K, 0x9BA07C00, 0x2E20C000, 0x2F00A000) // umull Rd,Rn,Rm DR_3A 10011011101mmmmm 011111nnnnnddddd 9BA0 7C00 // umull Vd,Vn,Vm DV_3H 00101110XX1mmmmm 110000nnnnnddddd 2E20 C000 Vd,Vn,Vm (vector) // umull Vd,Vn,Vm[] DV_3HI 00101111XXLMmmmm 1010H0nnnnnddddd 2F00 A000 Vd,Vn,Vm[] (vector by elem) -// enum name FP LD/ST DR_2E DR_2F -INST2(negs, "negs", 0, 0, IF_EN2A, 0x6B0003E0, 0x6B0003E0) +// enum name info DR_2E DR_2F +INST2(negs, "negs", 0, IF_EN2A, 0x6B0003E0, 0x6B0003E0) // negs Rd,Rm DR_2E X1101011000mmmmm 00000011111ddddd 6B00 03E0 // negs Rd,(Rm,shk,imm) DR_2F X1101011sh0mmmmm ssssss11111ddddd 6B00 03E0 Rm {LSL,LSR,ASR} imm(0-63) -// enum name FP LD/ST DR_3A DR_3B -INST2(bics, "bics", 0, 0, IF_EN2B, 0x6A200000, 0x6A200000) +// enum name info DR_3A DR_3B +INST2(bics, "bics", 0, IF_EN2B, 0x6A200000, 0x6A200000) // bics Rd,Rn,Rm DR_3A X1101010001mmmmm 000000nnnnnddddd 6A20 0000 // bics Rd,Rn,(Rm,shk,imm) DR_3B X1101010sh1mmmmm iiiiiinnnnnddddd 6A20 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) -INST2(eon, "eon", 0, 0, IF_EN2B, 0x4A200000, 0x4A200000) +INST2(eon, "eon", 0, IF_EN2B, 0x4A200000, 0x4A200000) // eon Rd,Rn,Rm DR_3A X1001010001mmmmm 000000nnnnnddddd 4A20 0000 // eon Rd,Rn,(Rm,shk,imm) DR_3B X1001010sh1mmmmm iiiiiinnnnnddddd 4A20 0000 Rm {LSL,LSR,ASR,ROR} imm(0-63) -// enum name FP LD/ST DR_3A DI_2C -INST2(lsl, "lsl", 0, 0, IF_EN2C, 0x1AC02000, 0x53000000) +// enum name info DR_3A DI_2C +INST2(lsl, "lsl", 0, IF_EN2C, 0x1AC02000, 0x53000000) // lsl Rd,Rn,Rm DR_3A X0011010110mmmmm 001000nnnnnddddd 1AC0 2000 // lsl Rd,Rn,imm6 DI_2D X10100110Xrrrrrr ssssssnnnnnddddd 5300 0000 imm(N,r,s) -INST2(lsr, "lsr", 0, 0, IF_EN2C, 0x1AC02400, 0x53000000) +INST2(lsr, "lsr", 0, IF_EN2C, 0x1AC02400, 0x53000000) // lsr Rd,Rn,Rm DR_3A X0011010110mmmmm 001001nnnnnddddd 1AC0 2400 // lsr Rd,Rn,imm6 DI_2D X10100110Xrrrrrr ssssssnnnnnddddd 5300 0000 imm(N,r,s) -INST2(asr, "asr", 0, 0, IF_EN2C, 0x1AC02800, 0x13000000) +INST2(asr, "asr", 0, IF_EN2C, 0x1AC02800, 0x13000000) // asr Rd,Rn,Rm DR_3A X0011010110mmmmm 001010nnnnnddddd 1AC0 2800 // asr Rd,Rn,imm6 DI_2D X00100110Xrrrrrr ssssssnnnnnddddd 1300 0000 imm(N,r,s) -// enum name FP LD/ST DR_3A DI_2B -INST2(ror, "ror", 0, 0, IF_EN2D, 0x1AC02C00, 0x13800000) +// enum name info DR_3A DI_2B +INST2(ror, "ror", 0, IF_EN2D, 0x1AC02C00, 0x13800000) // ror Rd,Rn,Rm DR_3A X0011010110mmmmm 001011nnnnnddddd 1AC0 2C00 // ror Rd,Rn,imm6 DI_2B X00100111X0nnnnn ssssssnnnnnddddd 1380 0000 imm(0-63) -// enum name FP LD/ST LS_3B LS_3C -INST2(ldp, "ldp", 0,LD, IF_EN2E, 0x29400000, 0x28400000) +// enum name info LS_3B LS_3C +INST2(ldp, "ldp", LD, IF_EN2E, 0x29400000, 0x28400000) // ldp Rt,Ra,[Xn] LS_3B X010100101000000 0aaaaannnnnttttt 2940 0000 [Xn imm7] // ldp Rt,Ra,[Xn+simm7] LS_3C X010100PP1iiiiii iaaaaannnnnttttt 2840 0000 [Xn imm7 LSL {} pre/post/no inc] -INST2(ldpsw, "ldpsw", 0,LD, IF_EN2E, 0x69400000, 0x68400000) +INST2(ldpsw, "ldpsw", LD, IF_EN2E, 0x69400000, 0x68400000) // ldpsw Rt,Ra,[Xn] LS_3B 0110100101000000 0aaaaannnnnttttt 6940 0000 [Xn imm7] // ldpsw Rt,Ra,[Xn+simm7] LS_3C 0110100PP1iiiiii iaaaaannnnnttttt 6840 0000 [Xn imm7 LSL {} pre/post/no inc] -INST2(stp, "stp", 0,ST, IF_EN2E, 0x29000000, 0x28000000) +INST2(stp, "stp", ST, IF_EN2E, 0x29000000, 0x28000000) // stp Rt,Ra,[Xn] LS_3B X010100100000000 0aaaaannnnnttttt 2900 0000 [Xn imm7] // stp Rt,Ra,[Xn+simm7] LS_3C X010100PP0iiiiii iaaaaannnnnttttt 2800 0000 [Xn imm7 LSL {} pre/post/no inc] -INST2(ldnp, "ldnp", 0,LD, IF_EN2E, 0x28400000, 0x28400000) +INST2(ldnp, "ldnp", LD, IF_EN2E, 0x28400000, 0x28400000) // ldnp Rt,Ra,[Xn] LS_3B X010100001000000 0aaaaannnnnttttt 2840 0000 [Xn imm7] // ldnp Rt,Ra,[Xn+simm7] LS_3C X010100001iiiiii iaaaaannnnnttttt 2840 0000 [Xn imm7 LSL {}] -INST2(stnp, "stnp", 0,ST, IF_EN2E, 0x28000000, 0x28000000) +INST2(stnp, "stnp", ST, IF_EN2E, 0x28000000, 0x28000000) // stnp Rt,Ra,[Xn] LS_3B X010100000000000 0aaaaannnnnttttt 2800 0000 [Xn imm7] // stnp Rt,Ra,[Xn+simm7] LS_3C X010100000iiiiii iaaaaannnnnttttt 2800 0000 [Xn imm7 LSL {}] -INST2(ccmp, "ccmp", 0,CMP,IF_EN2F, 0x7A400000, 0x7A400800) +INST2(ccmp, "ccmp", CMP, IF_EN2F, 0x7A400000, 0x7A400800) // ccmp Rn,Rm, nzcv,cond DR_2I X1111010010mmmmm cccc00nnnnn0nzcv 7A40 0000 nzcv, cond // ccmp Rn,imm5,nzcv,cond DI_1F X1111010010iiiii cccc10nnnnn0nzcv 7A40 0800 imm5, nzcv, cond -INST2(ccmn, "ccmn", 0,CMP,IF_EN2F, 0x3A400000, 0x3A400800) +INST2(ccmn, "ccmn", CMP, IF_EN2F, 0x3A400000, 0x3A400800) // ccmn Rn,Rm, nzcv,cond DR_2I X0111010010mmmmm cccc00nnnnn0nzcv 3A40 0000 nzcv, cond // ccmn Rn,imm5,nzcv,cond DI_1F X0111010910iiiii cccc10nnnnn0nzcv 3A40 0800 imm5, nzcv, cond -// enum name FP LD/ST DV_2C DV_2F -INST2(ins, "ins", 0, 0, IF_EN2H, 0x4E001C00, 0x6E000400) +// enum name info DV_2C DV_2F +INST2(ins, "ins", 0, IF_EN2H, 0x4E001C00, 0x6E000400) // ins Vd[],Rn DV_2C 01001110000iiiii 000111nnnnnddddd 4E00 1C00 Vd[],Rn (from general) // ins Vd[],Vn[] DV_2F 01101110000iiiii 0jjjj1nnnnnddddd 6E00 0400 Vd[],Vn[] (from/to elem) -// enum name FP LD/ST DV_3B DV_3D -INST2(fadd, "fadd", 0, 0, IF_EN2G, 0x0E20D400, 0x1E202800) +// enum name info DV_3B DV_3D +INST2(fadd, "fadd", 0, IF_EN2G, 0x0E20D400, 0x1E202800) // fadd Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 110101nnnnnddddd 0E20 D400 Vd,Vn,Vm (vector) // fadd Vd,Vn,Vm DV_3D 000111100X1mmmmm 001010nnnnnddddd 1E20 2800 Vd,Vn,Vm (scalar) -INST2(fsub, "fsub", 0, 0, IF_EN2G, 0x0EA0D400, 0x1E203800) +INST2(fsub, "fsub", 0, IF_EN2G, 0x0EA0D400, 0x1E203800) // fsub Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 110101nnnnnddddd 0EA0 D400 Vd,Vn,Vm (vector) // fsub Vd,Vn,Vm DV_3D 000111100X1mmmmm 001110nnnnnddddd 1E20 3800 Vd,Vn,Vm (scalar) -INST2(fdiv, "fdiv", 0, 0, IF_EN2G, 0x2E20FC00, 0x1E201800) +INST2(fdiv, "fdiv", 0, IF_EN2G, 0x2E20FC00, 0x1E201800) // fdiv Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 111111nnnnnddddd 2E20 FC00 Vd,Vn,Vm (vector) // fdiv Vd,Vn,Vm DV_3D 000111100X1mmmmm 000110nnnnnddddd 1E20 1800 Vd,Vn,Vm (scalar) -INST2(fmax, "fmax", 0, 0, IF_EN2G, 0x0E20F400, 0x1E204800) +INST2(fmax, "fmax", 0, IF_EN2G, 0x0E20F400, 0x1E204800) // fmax Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111101nnnnnddddd 0E20 F400 Vd,Vn,Vm (vector) // fmax Vd,Vn,Vm DV_3D 000111100X1mmmmm 010010nnnnnddddd 1E20 4800 Vd,Vn,Vm (scalar) -INST2(fmaxnm, "fmaxnm", 0, 0, IF_EN2G, 0x0E20C400, 0x1E206800) +INST2(fmaxnm, "fmaxnm", 0, IF_EN2G, 0x0E20C400, 0x1E206800) // fmaxnm Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 110001nnnnnddddd 0E20 C400 Vd,Vn,Vm (vector) // fmaxnm Vd,Vn,Vm DV_3D 000111100X1mmmmm 011010nnnnnddddd 1E20 6800 Vd,Vn,Vm (scalar) -INST2(fmin, "fmin", 0, 0, IF_EN2G, 0x0EA0F400, 0x1E205800) +INST2(fmin, "fmin", 0, IF_EN2G, 0x0EA0F400, 0x1E205800) // fmin Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 111101nnnnnddddd 0EA0 F400 Vd,Vn,Vm (vector) // fmin Vd,Vn,Vm DV_3D 000111100X1mmmmm 010110nnnnnddddd 1E20 5800 Vd,Vn,Vm (scalar) -INST2(fminnm, "fminnm", 0, 0, IF_EN2G, 0x0EA0C400, 0x1E207800) +INST2(fminnm, "fminnm", 0, IF_EN2G, 0x0EA0C400, 0x1E207800) // fminnm Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 110001nnnnnddddd 0EA0 C400 Vd,Vn,Vm (vector) // fminnm Vd,Vn,Vm DV_3D 000111100X1mmmmm 011110nnnnnddddd 1E20 7800 Vd,Vn,Vm (scalar) -INST2(fabd, "fabd", 0, 0, IF_EN2G, 0x2EA0D400, 0x7EA0D400) +INST2(fabd, "fabd", 0, IF_EN2G, 0x2EA0D400, 0x7EA0D400) // fabd Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 110101nnnnnddddd 2EA0 D400 Vd,Vn,Vm (vector) // fabd Vd,Vn,Vm DV_3D 011111101X1mmmmm 110101nnnnnddddd 7EA0 D400 Vd,Vn,Vm (scalar) -INST2(facge, "facge", 0, 0, IF_EN2G, 0x2E20EC00, 0x7E20EC00) +INST2(facge, "facge", 0, IF_EN2G, 0x2E20EC00, 0x7E20EC00) // facge Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 111011nnnnnddddd 2E20 EC00 Vd,Vn,Vm (vector) // facge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111011nnnnnddddd 7E20 EC00 Vd,Vn,Vm (scalar) -INST2(facgt, "facgt", 0, 0, IF_EN2G, 0x2EA0EC00, 0x7EA0EC00) +INST2(facgt, "facgt", 0, IF_EN2G, 0x2EA0EC00, 0x7EA0EC00) // facgt Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 111011nnnnnddddd 2EA0 EC00 Vd,Vn,Vm (vector) // facgt Vd,Vn,Vm DV_3D 011111101X1mmmmm 111011nnnnnddddd 7EA0 EC00 Vd,Vn,Vm (scalar) -INST2(frecps, "frecps", 0, 0, IF_EN2G, 0x0E20FC00, 0x5E20FC00) - // C7.2.138 FRECPS +INST2(frecps, "frecps", 0, IF_EN2G, 0x0E20FC00, 0x5E20FC00) // frecps Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111111nnnnnddddd 0E20 FC00 Vd,Vn,Vm (vector) // frecps Vd,Vn,Vm DV_3D 010111100X1mmmmm 111111nnnnnddddd 5E20 FC00 Vd,Vn,Vm (scalar) -INST2(frsqrts, "frsqrts",0, 0, IF_EN2G, 0x0EA0FC00, 0x5EA0FC00) - // C7.2.163 FRSQRTS +INST2(frsqrts, "frsqrts", 0, IF_EN2G, 0x0EA0FC00, 0x5EA0FC00) // frsqrts Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 111111nnnnnddddd 0EA0 FC00 Vd,Vn,Vm (vector) // frsqrts Vd,Vn,Vm DV_3D 010111101X1mmmmm 111111nnnnnddddd 5EA0 FC00 Vd,Vn,Vm (scalar) -// enum name FP LD/ST DV_2K DV_1C -INST2(fcmp, "fcmp", 0, 0, IF_EN2I, 0x1E202000, 0x1E202008) +// enum name info DV_2K DV_1C +INST2(fcmp, "fcmp", 0, IF_EN2I, 0x1E202000, 0x1E202008) // fcmp Vn,Vm DV_2K 000111100X1mmmmm 001000nnnnn00000 1E20 2000 Vn Vm // fcmp Vn,#0.0 DV_1C 000111100X100000 001000nnnnn01000 1E20 2008 Vn #0.0 -INST2(fcmpe, "fcmpe", 0, 0, IF_EN2I, 0x1E202010, 0x1E202018) +INST2(fcmpe, "fcmpe", 0, IF_EN2I, 0x1E202010, 0x1E202018) // fcmpe Vn,Vm DV_2K 000111100X1mmmmm 001000nnnnn10000 1E20 2010 Vn Vm // fcmpe Vn,#0.0 DV_1C 000111100X100000 001000nnnnn11000 1E20 2018 Vn #0.0 -// enum name FP LD/ST DV_2A DV_2G -INST2(fabs, "fabs", 0, 0, IF_EN2J, 0x0EA0F800, 0x1E20C000) +// enum name info DV_2A DV_2G +INST2(fabs, "fabs", 0, IF_EN2J, 0x0EA0F800, 0x1E20C000) // fabs Vd,Vn DV_2A 0Q0011101X100000 111110nnnnnddddd 0EA0 F800 Vd,Vn (vector) // fabs Vd,Vn DV_2G 000111100X100000 110000nnnnnddddd 1E20 C000 Vd,Vn (scalar) -INST2(fcmle, "fcmle", 0, 0, IF_EN2J, 0x2EA0D800, 0x7EA0D800) +INST2(fcmle, "fcmle", 0, IF_EN2J, 0x2EA0D800, 0x7EA0D800) // fcmle Vd,Vn DV_2A 0Q1011101X100000 111110nnnnnddddd 2EA0 D800 Vd,Vn (vector) // fcmle Vd,Vn DV_2G 011111101X100000 110110nnnnnddddd 7EA0 D800 Vd,Vn (scalar) -INST2(fcmlt, "fcmlt", 0, 0, IF_EN2J, 0x0EA0E800, 0x5EA0E800) +INST2(fcmlt, "fcmlt", 0, IF_EN2J, 0x0EA0E800, 0x5EA0E800) // fcmlt Vd,Vn DV_2A 0Q0011101X100000 111110nnnnnddddd 0EA0 E800 Vd,Vn (vector) // fcmlt Vd,Vn DV_2G 010111101X100000 111010nnnnnddddd 5EA0 E800 Vd,Vn (scalar) -INST2(fneg, "fneg", 0, 0, IF_EN2J, 0x2EA0F800, 0x1E214000) +INST2(fneg, "fneg", 0, IF_EN2J, 0x2EA0F800, 0x1E214000) // fneg Vd,Vn DV_2A 0Q1011101X100000 111110nnnnnddddd 2EA0 F800 Vd,Vn (vector) // fneg Vd,Vn DV_2G 000111100X100001 010000nnnnnddddd 1E21 4000 Vd,Vn (scalar) -INST2(frecpe, "frecpe", 0, 0, IF_EN2J, 0x0EA1D800, 0x5EA1D800) +INST2(frecpe, "frecpe", 0, IF_EN2J, 0x0EA1D800, 0x5EA1D800) // frecpe Vd,Vn DV_2A 0Q0011101X100001 110110nnnnnddddd 0EA1 D800 Vd,Vn (vector) // frecpe Vd,Vn DV_2G 010111101X100001 110110nnnnnddddd 5EA1 D800 Vd,Vn (scalar) -INST2(frintn, "frintn", 0, 0, IF_EN2J, 0x0E218800, 0x1E244000) +INST2(frintn, "frintn", 0, IF_EN2J, 0x0E218800, 0x1E244000) // frintn Vd,Vn DV_2A 0Q0011100X100001 100010nnnnnddddd 0E21 8800 Vd,Vn (vector) // frintn Vd,Vn DV_2G 000111100X100100 010000nnnnnddddd 1E24 4000 Vd,Vn (scalar) -INST2(frintp, "frintp", 0, 0, IF_EN2J, 0x0EA18800, 0x1E24C000) +INST2(frintp, "frintp", 0, IF_EN2J, 0x0EA18800, 0x1E24C000) // frintp Vd,Vn DV_2A 0Q0011101X100001 100010nnnnnddddd 0EA1 8800 Vd,Vn (vector) // frintp Vd,Vn DV_2G 000111100X100100 110000nnnnnddddd 1E24 C000 Vd,Vn (scalar) -INST2(frintm, "frintm", 0, 0, IF_EN2J, 0x0E219800, 0x1E254000) +INST2(frintm, "frintm", 0, IF_EN2J, 0x0E219800, 0x1E254000) // frintm Vd,Vn DV_2A 0Q0011100X100001 100110nnnnnddddd 0E21 9800 Vd,Vn (vector) // frintm Vd,Vn DV_2G 000111100X100101 010000nnnnnddddd 1E25 4000 Vd,Vn (scalar) -INST2(frintz, "frintz", 0, 0, IF_EN2J, 0x0EA19800, 0x1E25C000) +INST2(frintz, "frintz", 0, IF_EN2J, 0x0EA19800, 0x1E25C000) // frintz Vd,Vn DV_2A 0Q0011101X100001 100110nnnnnddddd 0EA1 9800 Vd,Vn (vector) // frintz Vd,Vn DV_2G 000111100X100101 110000nnnnnddddd 1E25 C000 Vd,Vn (scalar) -INST2(frinta, "frinta", 0, 0, IF_EN2J, 0x2E218800, 0x1E264000) +INST2(frinta, "frinta", 0, IF_EN2J, 0x2E218800, 0x1E264000) // frinta Vd,Vn DV_2A 0Q1011100X100001 100010nnnnnddddd 2E21 8800 Vd,Vn (vector) // frinta Vd,Vn DV_2G 000111100X100110 010000nnnnnddddd 1E26 4000 Vd,Vn (scalar) -INST2(frintx, "frintx", 0, 0, IF_EN2J, 0x2E219800, 0x1E274000) +INST2(frintx, "frintx", 0, IF_EN2J, 0x2E219800, 0x1E274000) // frintx Vd,Vn DV_2A 0Q1011100X100001 100110nnnnnddddd 2E21 9800 Vd,Vn (vector) // frintx Vd,Vn DV_2G 000111100X100111 010000nnnnnddddd 1E27 4000 Vd,Vn (scalar) -INST2(frinti, "frinti", 0, 0, IF_EN2J, 0x2EA19800, 0x1E27C000) +INST2(frinti, "frinti", 0, IF_EN2J, 0x2EA19800, 0x1E27C000) // frinti Vd,Vn DV_2A 0Q1011101X100001 100110nnnnnddddd 2EA1 9800 Vd,Vn (vector) // frinti Vd,Vn DV_2G 000111100X100111 110000nnnnnddddd 1E27 C000 Vd,Vn (scalar) -INST2(frsqrte, "frsqrte",0, 0, IF_EN2J, 0x2EA1D800, 0x7EA1D800) - // C7.2.162 FRSQRTE +INST2(frsqrte, "frsqrte", 0, IF_EN2J, 0x2EA1D800, 0x7EA1D800) // frsqrte Vd,Vn DV_2A 0Q1011101X100001 110110nnnnnddddd 2EA1 D800 Vd,Vn (vector) // frsqrte Vd,Vn DV_2G 011111101X100001 110110nnnnnddddd 7EA1 D800 Vd,Vn (scalar) -INST2(fsqrt, "fsqrt", 0, 0, IF_EN2J, 0x2EA1F800, 0x1E21C000) - // C7.2.164 FSQRT (vector) +INST2(fsqrt, "fsqrt", 0, IF_EN2J, 0x2EA1F800, 0x1E21C000) // fsqrt Vd,Vn DV_2A 0Q1011101X100001 111110nnnnnddddd 2EA1 F800 Vd,Vn (vector) - // C7.2.165 FSQRT (scalar) // fsqrt Vd,Vn DV_2G 000111100X100001 110000nnnnnddddd 1E21 C000 Vd,Vn (scalar) -// enum name FP LD/ST DV_2M DV_2L -INST2(abs, "abs", 0, 0, IF_EN2K, 0x0E20B800, 0x5E20B800) +// enum name info DV_2M DV_2L +INST2(abs, "abs", 0, IF_EN2K, 0x0E20B800, 0x5E20B800) // abs Vd,Vn DV_2M 0Q001110XX100000 101110nnnnnddddd 0E20 B800 Vd,Vn (vector) // abs Vd,Vn DV_2L 01011110XX100000 101110nnnnnddddd 5E20 B800 Vd,Vn (scalar) -INST2(cmle, "cmle", 0, 0, IF_EN2K, 0x2E209800, 0x7E209800) +INST2(cmle, "cmle", 0, IF_EN2K, 0x2E209800, 0x7E209800) // cmle Vd,Vn DV_2M 0Q101110XX100000 100110nnnnnddddd 2E20 9800 Vd,Vn (vector) // cmle Vd,Vn DV_2L 01111110XX100000 100110nnnnnddddd 7E20 9800 Vd,Vn (scalar) -INST2(cmlt, "cmlt", 0, 0, IF_EN2K, 0x0E20A800, 0x5E20A800) +INST2(cmlt, "cmlt", 0, IF_EN2K, 0x0E20A800, 0x5E20A800) // cmlt Vd,Vn DV_2M 0Q101110XX100000 101010nnnnnddddd 0E20 A800 Vd,Vn (vector) // cmlt Vd,Vn DV_2L 01011110XX100000 101010nnnnnddddd 5E20 A800 Vd,Vn (scalar) -// enum name FP LD/ST DR_2G DV_2M -INST2(cls, "cls", 0, 0, IF_EN2L, 0x5AC01400, 0x0E204800) +// enum name info DR_2G DV_2M +INST2(cls, "cls", 0, IF_EN2L, 0x5AC01400, 0x0E204800) // cls Rd,Rm DR_2G X101101011000000 000101nnnnnddddd 5AC0 1400 Rd Rn (general) // cls Vd,Vn DV_2M 0Q00111000100000 010010nnnnnddddd 0E20 4800 Vd,Vn (vector) -INST2(clz, "clz", 0, 0, IF_EN2L, 0x5AC01000, 0x2E204800) +INST2(clz, "clz", 0, IF_EN2L, 0x5AC01000, 0x2E204800) // clz Rd,Rm DR_2G X101101011000000 000100nnnnnddddd 5AC0 1000 Rd Rn (general) // clz Vd,Vn DV_2M 0Q10111000100000 010010nnnnnddddd 2E20 4800 Vd,Vn (vector) -INST2(rbit, "rbit", 0, 0, IF_EN2L, 0x5AC00000, 0x2E605800) +INST2(rbit, "rbit", 0, IF_EN2L, 0x5AC00000, 0x2E605800) // rbit Rd,Rm DR_2G X101101011000000 000000nnnnnddddd 5AC0 0000 Rd Rn (general) // rbit Vd,Vn DV_2M 0Q10111001100000 010110nnnnnddddd 2E60 5800 Vd,Vn (vector) -INST2(rev16, "rev16", 0, 0, IF_EN2L, 0x5AC00400, 0x0E201800) +INST2(rev16, "rev16", 0, IF_EN2L, 0x5AC00400, 0x0E201800) // rev16 Rd,Rm DR_2G X101101011000000 000001nnnnnddddd 5AC0 0400 Rd Rn (general) // rev16 Vd,Vn DV_2M 0Q001110XX100000 000110nnnnnddddd 0E20 1800 Vd,Vn (vector) -INST2(rev32, "rev32", 0, 0, IF_EN2L, 0xDAC00800, 0x2E200800) +INST2(rev32, "rev32", 0, IF_EN2L, 0xDAC00800, 0x2E200800) // rev32 Rd,Rm DR_2G 1101101011000000 000010nnnnnddddd DAC0 0800 Rd Rn (general) // rev32 Vd,Vn DV_2M 0Q101110XX100000 000010nnnnnddddd 2E20 0800 Vd,Vn (vector) -// enum name FP LD/ST DV_3A DV_3AI -INST2(mla, "mla", 0, 0, IF_EN2M, 0x0E209400, 0x2F000000) +// enum name info DV_3A DV_3AI +INST2(mla, "mla", 0, IF_EN2M, 0x0E209400, 0x2F000000) // mla Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 100101nnnnnddddd 0E20 9400 Vd,Vn,Vm (vector) // mla Vd,Vn,Vm[] DV_3AI 0Q101111XXLMmmmm 0000H0nnnnnddddd 2F00 0000 Vd,Vn,Vm[] (vector by elem) -INST2(mls, "mls", 0, 0, IF_EN2M, 0x2E209400, 0x2F004000) +INST2(mls, "mls", 0, IF_EN2M, 0x2E209400, 0x2F004000) // mls Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100101nnnnnddddd 2E20 9400 Vd,Vn,Vm (vector) // mls Vd,Vn,Vm[] DV_3AI 0Q101111XXLMmmmm 0100H0nnnnnddddd 2F00 4000 Vd,Vn,Vm[] (vector by elem) -INST2(smlal, "smlal", 0, 0, IF_EN2R, 0x0E208000, 0x0F002000) - // C7.2.267 SMLAL, SMLAL2 (by element) - // C7.2.268 SMLAL, SMLAL2 (vector) +INST2(smlal, "smlal", 0, IF_EN2R, 0x0E208000, 0x0F002000) // smlal Vd,Vn,Vm DV_3H 00001110XX1mmmmm 100000nnnnnddddd 0E20 8000 Vd,Vn,Vm (vector) // smlal Vd,Vn,Vm[] DV_3HI 00001111XXLMmmmm 0010H0nnnnnddddd 0F00 2000 Vd,Vn,Vm[] (vector by elem) -INST2(smlal2, "smlal2", 0, 0, IF_EN2R, 0x4E208000, 0x4F002000) - // C7.2.267 SMLAL, SMLAL2 (by element) - // C7.2.268 SMLAL, SMLAL2 (vector) +INST2(smlal2, "smlal2", 0, IF_EN2R, 0x4E208000, 0x4F002000) // smlal2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 100000nnnnnddddd 4E20 8000 Vd,Vn,Vm (vector) // smlal2 Vd,Vn,Vm[] DV_3HI 01001111XXLMmmmm 0010H0nnnnnddddd 4F00 2000 Vd,Vn,Vm[] (vector by elem) -INST2(smlsl, "smlsl", 0, 0, IF_EN2R, 0x0E20A000, 0x0F006000) - // C7.2.269 SMLSL, SMLSL2 (by element) - // C7.2.270 SMLSL, SMLSL2 (vector) +INST2(smlsl, "smlsl", 0, IF_EN2R, 0x0E20A000, 0x0F006000) // smlsl Vd,Vn,Vm DV_3H 00001110XX1mmmmm 101000nnnnnddddd 0E20 A000 Vd,Vn,Vm (vector) // smlsl Vd,Vn,Vm[] DV_3HI 00001111XXLMmmmm 0110H0nnnnnddddd 0F00 6000 Vd,Vn,Vm[] (vector by elem) -INST2(smlsl2, "smlsl2", 0, 0, IF_EN2R, 0x4E20A000, 0x4F006000) - // C7.2.269 SMLSL, SMLSL2 (by element) - // C7.2.270 SMLSL, SMLSL2 (vector) +INST2(smlsl2, "smlsl2", 0, IF_EN2R, 0x4E20A000, 0x4F006000) // smlsl2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 101000nnnnnddddd 4E20 A000 Vd,Vn,Vm (vector) // smlsl2 Vd,Vn,Vm[] DV_3HI 01001111XXLMmmmm 0110H0nnnnnddddd 4F00 6000 Vd,Vn,Vm[] (vector by elem) -INST2(smull2, "smull2", 0, 0, IF_EN2R, 0x4E20C000, 0x4F00A000) - // C7.2.272 SMULL, SMULL2 (by element) - // C7.2.273 SMULL, SMULL2 (vector) +INST2(smull2, "smull2", 0, IF_EN2R, 0x4E20C000, 0x4F00A000) // smull2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 110000nnnnnddddd 4E20 C000 Vd,Vn,Vm (vector) // smull2 Vd,Vn,Vm[] DV_3HI 01001111XXLMmmmm 1010H0nnnnnddddd 4F00 A000 Vd,Vn,Vm[] (vector by elem) -INST2(umlal, "umlal", 0, 0, IF_EN2R, 0x2E208000, 0x2F002000) - // C7.2.357 UMLAL, UMLAL2 (by element) - // C7.2.358 UMLAL, UMLAL2 (vector) +INST2(umlal, "umlal", 0, IF_EN2R, 0x2E208000, 0x2F002000) // umlal Vd,Vn,Vm DV_3H 00101110XX1mmmmm 100000nnnnnddddd 2E20 8000 Vd,Vn,Vm (vector) // umlal Vd,Vn,Vm[] DV_3HI 00101111XXLMmmmm 0010H0nnnnnddddd 2F00 2000 Vd,Vn,Vm[] (vector by elem) -INST2(umlal2, "umlal2", 0, 0, IF_EN2R, 0x6E208000, 0x6F002000) - // C7.2.357 UMLAL, UMLAL2 (by element) - // C7.2.358 UMLAL, UMLAL2 (vector) +INST2(umlal2, "umlal2", 0, IF_EN2R, 0x6E208000, 0x6F002000) // umlal2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 100000nnnnnddddd 6E20 8000 Vd,Vn,Vm (vector) // umlal2 Vd,Vn,Vm[] DV_3HI 01101111XXLMmmmm 0010H0nnnnnddddd 6F00 2000 Vd,Vn,Vm[] (vector by elem) -INST2(umlsl, "umlsl", 0, 0, IF_EN2R, 0x2E20A000, 0x2F006000) - // C7.2.359 UMLSL, UMLSL2 (by element) - // C7.2.360 UMLSL, UMLSL2 (vector) +INST2(umlsl, "umlsl", 0, IF_EN2R, 0x2E20A000, 0x2F006000) // umlsl Vd,Vn,Vm DV_3H 00101110XX1mmmmm 101000nnnnnddddd 2E20 A000 Vd,Vn,Vm (vector) // umlsl Vd,Vn,Vm[] DV_3HI 00101111XXLMmmmm 0110H0nnnnnddddd 2F00 6000 Vd,Vn,Vm[] (vector by elem) -INST2(umlsl2, "umlsl2", 0, 0, IF_EN2R, 0x6E20A000, 0x6F006000) - // C7.2.359 UMLSL, UMLSL2 (by element) - // C7.2.360 UMLSL, UMLSL2 (vector) +INST2(umlsl2, "umlsl2", 0, IF_EN2R, 0x6E20A000, 0x6F006000) // umlsl2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 101000nnnnnddddd 6E20 A000 Vd,Vn,Vm (vector) // umlsl2 Vd,Vn,Vm[] DV_3HI 01101111XXLMmmmm 0110H0nnnnnddddd 6F00 6000 Vd,Vn,Vm[] (vector by elem) -INST2(umull2, "umull2", 0, 0, IF_EN2R, 0x6E20C000, 0x6F00A000) - // C7.2.362 UMULL, UMULL2 (by element) - // C7.2.363 UMULL, UMULL2 (vector) +INST2(umull2, "umull2", 0, IF_EN2R, 0x6E20C000, 0x6F00A000) // umull2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 110000nnnnnddddd 6E20 C000 Vd,Vn,Vm (vector) // umull2 Vd,Vn,Vm[] DV_3HI 01101111XXLMmmmm 1010H0nnnnnddddd 6F00 A000 Vd,Vn,Vm[] (vector by elem) -// enum name FP LD/ST DV_2N DV_2O -INST2(sshr, "sshr", 0, 0, IF_EN2N, 0x5F000400, 0x0F000400) - // sshr Vd,Vn,imm DV_2N 010111110iiiiiii 000001nnnnnddddd 5F00 0400 Vd Vn imm (shift - scalar) - // sshr Vd,Vn,imm DV_2O 0Q0011110iiiiiii 000001nnnnnddddd 0F00 0400 Vd,Vn imm (shift - vector) +// enum name info DV_2N DV_2O +INST2(sshr, "sshr", RSH, IF_EN2N, 0x5F000400, 0x0F000400) + // sshr Vd,Vn,imm DV_2N 010111110iiiiiii 000001nnnnnddddd 5F00 0400 Vd Vn imm (right shift - scalar) + // sshr Vd,Vn,imm DV_2O 0Q0011110iiiiiii 000001nnnnnddddd 0F00 0400 Vd,Vn imm (right shift - vector) -INST2(ssra, "ssra", 0, 0, IF_EN2N, 0x5F001400, 0x0F001400) - // ssra Vd,Vn,imm DV_2N 010111110iiiiiii 000101nnnnnddddd 5F00 1400 Vd Vn imm (shift - scalar) - // ssra Vd,Vn,imm DV_2O 0Q0011110iiiiiii 000101nnnnnddddd 0F00 1400 Vd,Vn imm (shift - vector) +INST2(ssra, "ssra", RSH, IF_EN2N, 0x5F001400, 0x0F001400) + // ssra Vd,Vn,imm DV_2N 010111110iiiiiii 000101nnnnnddddd 5F00 1400 Vd Vn imm (right shift - scalar) + // ssra Vd,Vn,imm DV_2O 0Q0011110iiiiiii 000101nnnnnddddd 0F00 1400 Vd,Vn imm (right shift - vector) -INST2(srshr, "srshr", 0, 0, IF_EN2N, 0x5F002400, 0x0F002400) - // srshr Vd,Vn,imm DV_2N 010111110iiiiiii 001001nnnnnddddd 5F00 0400 Vd Vn imm (shift - scalar) - // srshr Vd,Vn,imm DV_2O 0Q0011110iiiiiii 001001nnnnnddddd 0F00 0400 Vd,Vn imm (shift - vector) +INST2(srshr, "srshr", RSH, IF_EN2N, 0x5F002400, 0x0F002400) + // srshr Vd,Vn,imm DV_2N 010111110iiiiiii 001001nnnnnddddd 5F00 0400 Vd Vn imm (right shift - scalar) + // srshr Vd,Vn,imm DV_2O 0Q0011110iiiiiii 001001nnnnnddddd 0F00 0400 Vd,Vn imm (right shift - vector) -INST2(srsra, "srsra", 0, 0, IF_EN2N, 0x5F003400, 0x0F003400) - // srsra Vd,Vn,imm DV_2N 010111110iiiiiii 001101nnnnnddddd 5F00 1400 Vd Vn imm (shift - scalar) - // srsra Vd,Vn,imm DV_2O 0Q0011110iiiiiii 001101nnnnnddddd 0F00 1400 Vd,Vn imm (shift - vector) +INST2(srsra, "srsra", RSH, IF_EN2N, 0x5F003400, 0x0F003400) + // srsra Vd,Vn,imm DV_2N 010111110iiiiiii 001101nnnnnddddd 5F00 1400 Vd Vn imm (right shift - scalar) + // srsra Vd,Vn,imm DV_2O 0Q0011110iiiiiii 001101nnnnnddddd 0F00 1400 Vd,Vn imm (right shift - vector) -INST2(shl, "shl", 0, 0, IF_EN2N, 0x5F005400, 0x0F005400) - // shl Vd,Vn,imm DV_2N 010111110iiiiiii 010101nnnnnddddd 5F00 5400 Vd Vn imm (shift - scalar) - // shl Vd,Vn,imm DV_2O 0Q0011110iiiiiii 010101nnnnnddddd 0F00 5400 Vd,Vn imm (shift - vector) +INST2(shl, "shl", 0, IF_EN2N, 0x5F005400, 0x0F005400) + // shl Vd,Vn,imm DV_2N 010111110iiiiiii 010101nnnnnddddd 5F00 5400 Vd Vn imm (left shift - scalar) + // shl Vd,Vn,imm DV_2O 0Q0011110iiiiiii 010101nnnnnddddd 0F00 5400 Vd,Vn imm (left shift - vector) -INST2(ushr, "ushr", 0, 0, IF_EN2N, 0x7F000400, 0x2F000400) - // ushr Vd,Vn,imm DV_2N 011111110iiiiiii 000001nnnnnddddd 7F00 0400 Vd Vn imm (shift - scalar) - // ushr Vd,Vn,imm DV_2O 0Q1011110iiiiiii 000001nnnnnddddd 2F00 0400 Vd,Vn imm (shift - vector) +INST2(ushr, "ushr", RSH, IF_EN2N, 0x7F000400, 0x2F000400) + // ushr Vd,Vn,imm DV_2N 011111110iiiiiii 000001nnnnnddddd 7F00 0400 Vd Vn imm (right shift - scalar) + // ushr Vd,Vn,imm DV_2O 0Q1011110iiiiiii 000001nnnnnddddd 2F00 0400 Vd,Vn imm (right shift - vector) -INST2(usra, "usra", 0, 0, IF_EN2N, 0x7F001400, 0x2F001400) - // usra Vd,Vn,imm DV_2N 011111110iiiiiii 000101nnnnnddddd 7F00 1400 Vd Vn imm (shift - scalar) - // usra Vd,Vn,imm DV_2O 0Q1011110iiiiiii 000101nnnnnddddd 2F00 1400 Vd,Vn imm (shift - vector) +INST2(usra, "usra", RSH, IF_EN2N, 0x7F001400, 0x2F001400) + // usra Vd,Vn,imm DV_2N 011111110iiiiiii 000101nnnnnddddd 7F00 1400 Vd Vn imm (right shift - scalar) + // usra Vd,Vn,imm DV_2O 0Q1011110iiiiiii 000101nnnnnddddd 2F00 1400 Vd,Vn imm (right shift - vector) -INST2(urshr, "urshr", 0, 0, IF_EN2N, 0x7F002400, 0x2F002400) - // urshr Vd,Vn,imm DV_2N 011111110iiiiiii 001001nnnnnddddd 7F00 2400 Vd Vn imm (shift - scalar) - // urshr Vd,Vn,imm DV_2O 0Q1011110iiiiiii 001001nnnnnddddd 2F00 2400 Vd,Vn imm (shift - vector) +INST2(urshr, "urshr", RSH, IF_EN2N, 0x7F002400, 0x2F002400) + // urshr Vd,Vn,imm DV_2N 011111110iiiiiii 001001nnnnnddddd 7F00 2400 Vd Vn imm (right shift - scalar) + // urshr Vd,Vn,imm DV_2O 0Q1011110iiiiiii 001001nnnnnddddd 2F00 2400 Vd,Vn imm (right shift - vector) -INST2(ursra, "ursra", 0, 0, IF_EN2N, 0x7F003400, 0x2F003400) - // ursra Vd,Vn,imm DV_2N 011111110iiiiiii 001101nnnnnddddd 7F00 3400 Vd Vn imm (shift - scalar) - // ursra Vd,Vn,imm DV_2O 0Q1011110iiiiiii 001101nnnnnddddd 2F00 3400 Vd,Vn imm (shift - vector) +INST2(ursra, "ursra", RSH, IF_EN2N, 0x7F003400, 0x2F003400) + // ursra Vd,Vn,imm DV_2N 011111110iiiiiii 001101nnnnnddddd 7F00 3400 Vd Vn imm (right shift - scalar) + // ursra Vd,Vn,imm DV_2O 0Q1011110iiiiiii 001101nnnnnddddd 2F00 3400 Vd,Vn imm (right shift - vector) -INST2(sri, "sri", 0, 0, IF_EN2N, 0x7F004400, 0x2F004400) - // sri Vd,Vn,imm DV_2N 011111110iiiiiii 010001nnnnnddddd 7F00 4400 Vd Vn imm (shift - scalar) - // sri Vd,Vn,imm DV_2O 0Q1011110iiiiiii 010001nnnnnddddd 2F00 4400 Vd,Vn imm (shift - vector) +INST2(sri, "sri", RSH, IF_EN2N, 0x7F004400, 0x2F004400) + // sri Vd,Vn,imm DV_2N 011111110iiiiiii 010001nnnnnddddd 7F00 4400 Vd Vn imm (right shift - scalar) + // sri Vd,Vn,imm DV_2O 0Q1011110iiiiiii 010001nnnnnddddd 2F00 4400 Vd,Vn imm (right shift - vector) -INST2(sli, "sli", 0, 0, IF_EN2N, 0x7F005400, 0x2F005400) - // sli Vd,Vn,imm DV_2N 011111110iiiiiii 010101nnnnnddddd 7F00 5400 Vd Vn imm (shift - scalar) - // sli Vd,Vn,imm DV_2O 0Q1011110iiiiiii 010101nnnnnddddd 2F00 5400 Vd,Vn imm (shift - vector) +INST2(sli, "sli", 0, IF_EN2N, 0x7F005400, 0x2F005400) + // sli Vd,Vn,imm DV_2N 011111110iiiiiii 010101nnnnnddddd 7F00 5400 Vd Vn imm (left shift - scalar) + // sli Vd,Vn,imm DV_2O 0Q1011110iiiiiii 010101nnnnnddddd 2F00 5400 Vd,Vn imm (left shift - vector) -// enum name FP LD/ST DV_3E DV_3A -INST2(cmhi, "cmhi", 0, 0, IF_EN2O, 0x7EE03400, 0x2E203400) +INST2(sqshlu, "sqshlu", 0, IF_EN2N, 0x7F006400, 0x2F006400) + // sqshlu Vd,Vn,imm DV_2N 011111110iiiiiii 011001nnnnnddddd 7F00 6400 Vd Vn imm (left shift - scalar) + // sqshlu Vd,Vn,imm DV_2O 0Q1011110iiiiiii 011001nnnnnddddd 2F00 6400 Vd Vn imm (left shift - vector) + +INST2(sqrshrn, "sqrshrn", RSH, IF_EN2N, 0x5F009C00, 0x0F009C00) + // sqrshrn Vd,Vn,imm DV_2N 010111110iiiiiii 100111nnnnnddddd 5F00 9C00 Vd Vn imm (right shift - scalar) + // sqrshrn Vd,Vn,imm DV_2O 0Q0011110iiiiiii 100111nnnnnddddd 0F00 9C00 Vd Vn imm (right shift - vector) + +INST2(sqrshrun, "sqrshrun", RSH, IF_EN2N, 0x7F008C00, 0x2F008C00) + // sqrshrun Vd,Vn,imm DV_2N 011111110iiiiiii 100011nnnnnddddd 7F00 8C00 Vd Vn imm (right shift - scalar) + // sqrshrun Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100011nnnnnddddd 2F00 8C00 Vd Vn imm (right shift - vector) + +INST2(sqshrn, "sqshrn", RSH, IF_EN2N, 0x5F009400, 0x0F009400) + // sqshrn Vd,Vn,imm DV_2N 010111110iiiiiii 100101nnnnnddddd 5F00 9400 Vd Vn imm (right shift - scalar) + // sqshrn Vd,Vn,imm DV_2O 0Q0011110iiiiiii 100101nnnnnddddd 0F00 9400 Vd Vn imm (right shift - vector) + +INST2(sqshrun, "sqshrun", RSH, IF_EN2N, 0x7F008400, 0x2F008400) + // sqshrun Vd,Vn,imm DV_2N 011111110iiiiiii 100001nnnnnddddd 7F00 8400 Vd Vn imm (right shift - scalar) + // sqshrun Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100001nnnnnddddd 2F00 8400 Vd Vn imm (right shift - vector) + +INST2(uqrshrn, "uqrshrn", RSH, IF_EN2N, 0x7F009C00, 0x2F009C00) + // uqrshrn Vd,Vn,imm DV_2N 011111110iiiiiii 100111nnnnnddddd 7F00 9C00 Vd Vn imm (right shift - scalar) + // uqrshrn Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100111nnnnnddddd 2F00 9C00 Vd Vn imm (right shift - vector) + +INST2(uqshrn, "uqshrn", RSH, IF_EN2N, 0x7F009400, 0x2F009400) + // usqhrn Vd,Vn,imm DV_2N 011111110iiiiiii 100101nnnnnddddd 7F00 9400 Vd Vn imm (right shift - scalar) + // usqhrn Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100101nnnnnddddd 2F00 9400 Vd Vn imm (right shift - vector) + +// enum name info DV_3E DV_3A +INST2(cmhi, "cmhi", 0, IF_EN2O, 0x7EE03400, 0x2E203400) // cmhi Vd,Vn,Vm DV_3E 01111110111mmmmm 001101nnnnnddddd 7EE0 3400 Vd,Vn,Vm (scalar) // cmhi Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 001101nnnnnddddd 2E20 3400 Vd,Vn,Vm (vector) -INST2(cmhs, "cmhs", 0, 0, IF_EN2O, 0x7EE03C00, 0x2E203C00) +INST2(cmhs, "cmhs", 0, IF_EN2O, 0x7EE03C00, 0x2E203C00) // cmhs Vd,Vn,Vm DV_3E 01111110111mmmmm 001111nnnnnddddd 7EE0 3C00 Vd,Vn,Vm (scalar) // cmhs Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 001111nnnnnddddd 2E20 3C00 Vd,Vn,Vm (vector) -INST2(cmtst, "cmtst", 0, 0, IF_EN2O, 0x5EE08C00, 0x0E208C00) +INST2(cmtst, "cmtst", 0, IF_EN2O, 0x5EE08C00, 0x0E208C00) // cmtst Vd,Vn,Vm DV_3E 01011110111mmmmm 100011nnnnnddddd 5EE0 8C00 Vd,Vn,Vm (scalar) // cmtst Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 100011nnnnnddddd 0E20 8C00 Vd,Vn,Vm (vector) -INST2(sqadd, "sqadd", 0, 0, IF_EN2O, 0x5E200C00, 0x0E200C00) - // C7.2.275 SQADD +INST2(sqadd, "sqadd", 0, IF_EN2O, 0x5E200C00, 0x0E200C00) // sqadd Vd,Vn,Vm DV_3E 01011110XX1mmmmm 000011nnnnnddddd 5E20 0C00 Vd,Vn,Vm (scalar) // sqadd Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 000011nnnnnddddd 0E20 0C00 Vd,Vn,Vm (vector) -INST2(sqsub, "sqsub", 0, 0, IF_EN2O, 0x5E202C00, 0x0E202C00) - // C7.2.299 SQSUB +INST2(sqrshl, "sqrshl", 0, IF_EN2O, 0x5E205C00, 0x0E205C00) + // sqrshl Vd,Vn,Vm DV_3E 01011110XX1mmmmm 010111nnnnnddddd 5E20 5C00 Vd,Vn,Vm (scalar) + // sqrshl Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 010111nnnnnddddd 0E20 5C00 Vd,Vn,Vm (vector) + +INST2(sqsub, "sqsub", 0, IF_EN2O, 0x5E202C00, 0x0E202C00) // sqsub Vd,Vn,Vm DV_3E 01011110XX1mmmmm 001011nnnnnddddd 5E20 2C00 Vd,Vn,Vm (scalar) // sqsub Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 001011nnnnnddddd 0E20 2C00 Vd,Vn,Vm (vector) -INST2(uqadd, "uqadd", 0, 0, IF_EN2O, 0x7E200C00, 0x2E200C00) - // C7.2.364 UQADD +INST2(srshl, "srshl", 0, IF_EN2O, 0x5E205400, 0x0E205400) + // srshl Vd,Vn,Vm DV_3E 01011110XX1mmmmm 010101nnnnnddddd 5E20 5400 Vd,Vn,Vm (scalar) + // srshl Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 010101nnnnnddddd 0E20 5400 Vd,Vn,Vm (vector) + +INST2(sshl, "sshl", 0, IF_EN2O, 0x5E204400, 0x0E204400) + // sshl Vd,Vn,Vm DV_3E 01011110XX1mmmmm 010001nnnnnddddd 5E20 4400 Vd,Vn,Vm (scalar) + // sshl Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 010001nnnnnddddd 0E20 4400 Vd,Vn,Vm (vector) + +INST2(uqadd, "uqadd", 0, IF_EN2O, 0x7E200C00, 0x2E200C00) // uqadd Vd,Vn,Vm DV_3E 01111110XX1mmmmm 000011nnnnnddddd 7E20 0C00 Vd,Vn,Vm (scalar) // uqadd Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 000011nnnnnddddd 2E20 0C00 Vd,Vn,Vm (vector) -INST2(uqsub, "uqsub", 0, 0, IF_EN2O, 0x7E202C00, 0x2E202C00) - // C7.2.370 UQSUB +INST2(uqrshl, "uqrshl", 0, IF_EN2O, 0x7E205C00, 0x2E205C00) + // uqrshl Vd,Vn,Vm DV_3E 01111110XX1mmmmm 010111nnnnnddddd 7E20 5C00 Vd,Vn,Vm (scalar) + // uqrshl Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 010111nnnnnddddd 2E20 5C00 Vd,Vn,Vm (vector) + +INST2(uqsub, "uqsub", 0, IF_EN2O, 0x7E202C00, 0x2E202C00) // uqsub Vd,Vn,Vm DV_3E 01111110XX1mmmmm 001011nnnnnddddd 7E20 2C00 Vd,Vn,Vm (scalar) // uqsub Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 001011nnnnnddddd 2E20 2C00 Vd,Vn,Vm (vector) -// enum name FP LD/ST DV_2Q DV_3B -INST2(faddp, "faddp", 0, 0, IF_EN2P, 0x7E30D800, 0x2E20D400) +INST2(urshl, "urshl", 0, IF_EN2O, 0x7E205400, 0x2E205400) + // urshl Vd,Vn,Vm DV_3E 01111110XX1mmmmm 010101nnnnnddddd 7E20 5400 Vd,Vn,Vm (scalar) + // urshl Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 010101nnnnnddddd 2E20 5400 Vd,Vn,Vm (vector) + +INST2(ushl, "ushl", 0, IF_EN2O, 0x7E204400, 0x2E204400) + // ushl Vd,Vn,Vm DV_3E 01111110XX1mmmmm 010001nnnnnddddd 7E20 4400 Vd,Vn,Vm (scalar) + // ushl Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 010001nnnnnddddd 2E20 4400 Vd,Vn,Vm (vector) + +// enum name info DV_2Q DV_3B +INST2(faddp, "faddp", 0, IF_EN2P, 0x7E30D800, 0x2E20D400) // faddp Vd,Vn DV_2Q 011111100X110000 110110nnnnnddddd 7E30 D800 Vd,Vn (scalar) // faddp Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 110101nnnnnddddd 2E20 D400 Vd,Vn,Vm (vector) -INST2(fmaxnmp, "fmaxnmp",0, 0, IF_EN2P, 0x7E30C800, 0x2E20C400) +INST2(fmaxnmp, "fmaxnmp", 0, IF_EN2P, 0x7E30C800, 0x2E20C400) // fmaxnmp Vd,Vn DV_2Q 011111100X110000 110010nnnnnddddd 7E30 C800 Vd,Vn (scalar) // fmaxnmp Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 110001nnnnnddddd 2E20 C400 Vd,Vn,Vm (vector) -INST2(fmaxp, "fmaxp", 0, 0, IF_EN2P, 0x7E30F800, 0x2E20F400) +INST2(fmaxp, "fmaxp", 0, IF_EN2P, 0x7E30F800, 0x2E20F400) // fmaxp Vd,Vn DV_2Q 011111100X110000 111110nnnnnddddd 7E30 F800 Vd,Vn (scalar) // fmaxp Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 111101nnnnnddddd 2E20 F400 Vd,Vn,Vm (vector) -INST2(fminnmp, "fminnmp",0, 0, IF_EN2P, 0x7EB0C800, 0x2EA0C400) +INST2(fminnmp, "fminnmp", 0, IF_EN2P, 0x7EB0C800, 0x2EA0C400) // fminnmp Vd,Vn DV_2Q 011111101X110000 110010nnnnnddddd 7EB0 C800 Vd,Vn (scalar) // fminnmp Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 110001nnnnnddddd 2EA0 C400 Vd,Vn,Vm (vector) -INST2(fminp, "fminp", 0, 0, IF_EN2P, 0x7EB0F800, 0x2EA0F400) +INST2(fminp, "fminp", 0, IF_EN2P, 0x7EB0F800, 0x2EA0F400) // fminp Vd,Vn DV_2Q 011111101X110000 111110nnnnnddddd 7EB0 F800 Vd,Vn (scalar) // fminp Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 111101nnnnnddddd 2EA0 F400 Vd,Vn,Vm (vector) -INST2(addp, "addp", 0, 0, IF_EN2Q, 0x5E31B800, 0x0E20BC00) +INST2(addp, "addp", 0, IF_EN2Q, 0x5E31B800, 0x0E20BC00) // addp Vd,Vn DV_2S 01011110XX110001 101110nnnnnddddd 5E31 B800 Vd,Vn (scalar) // addp Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 101111nnnnnddddd 0E20 BC00 Vd,Vn,Vm (vector) -INST1(ldar, "ldar", 0,LD, IF_LS_2A, 0x88DFFC00) +INST1(ldar, "ldar", LD, IF_LS_2A, 0x88DFFC00) // ldar Rt,[Xn] LS_2A 1X00100011011111 111111nnnnnttttt 88DF FC00 -INST1(ldarb, "ldarb", 0,LD, IF_LS_2A, 0x08DFFC00) +INST1(ldarb, "ldarb", LD, IF_LS_2A, 0x08DFFC00) // ldarb Rt,[Xn] LS_2A 0000100011011111 111111nnnnnttttt 08DF FC00 -INST1(ldarh, "ldarh", 0,LD, IF_LS_2A, 0x48DFFC00) +INST1(ldarh, "ldarh", LD, IF_LS_2A, 0x48DFFC00) // ldarh Rt,[Xn] LS_2A 0100100011011111 111111nnnnnttttt 48DF FC00 -INST1(ldxr, "ldxr", 0,LD, IF_LS_2A, 0x885F7C00) +INST1(ldxr, "ldxr", LD, IF_LS_2A, 0x885F7C00) // ldxr Rt,[Xn] LS_2A 1X00100001011111 011111nnnnnttttt 885F 7C00 -INST1(ldxrb, "ldxrb", 0,LD, IF_LS_2A, 0x085F7C00) +INST1(ldxrb, "ldxrb", LD, IF_LS_2A, 0x085F7C00) // ldxrb Rt,[Xn] LS_2A 0000100001011111 011111nnnnnttttt 085F 7C00 -INST1(ldxrh, "ldxrh", 0,LD, IF_LS_2A, 0x485F7C00) +INST1(ldxrh, "ldxrh", LD, IF_LS_2A, 0x485F7C00) // ldxrh Rt,[Xn] LS_2A 0100100001011111 011111nnnnnttttt 485F 7C00 -INST1(ldaxr, "ldaxr", 0,LD, IF_LS_2A, 0x885FFC00) +INST1(ldaxr, "ldaxr", LD, IF_LS_2A, 0x885FFC00) // ldaxr Rt,[Xn] LS_2A 1X00100001011111 111111nnnnnttttt 885F FC00 -INST1(ldaxrb, "ldaxrb", 0,LD, IF_LS_2A, 0x085FFC00) +INST1(ldaxrb, "ldaxrb", LD, IF_LS_2A, 0x085FFC00) // ldaxrb Rt,[Xn] LS_2A 0000100001011111 111111nnnnnttttt 085F FC00 -INST1(ldaxrh, "ldaxrh", 0,LD, IF_LS_2A, 0x485FFC00) +INST1(ldaxrh, "ldaxrh", LD, IF_LS_2A, 0x485FFC00) // ldaxrh Rt,[Xn] LS_2A 0100100001011111 111111nnnnnttttt 485F FC00 -INST1(ldur, "ldur", 0,LD, IF_LS_2C, 0xB8400000) +INST1(ldur, "ldur", LD, IF_LS_2C, 0xB8400000) // ldur Rt,[Xn+simm9] LS_2C 1X111000010iiiii iiii00nnnnnttttt B840 0000 [Xn imm(-256..+255)] -INST1(ldurb, "ldurb", 0,LD, IF_LS_2C, 0x38400000) +INST1(ldurb, "ldurb", LD, IF_LS_2C, 0x38400000) // ldurb Rt,[Xn+simm9] LS_2C 00111000010iiiii iiii00nnnnnttttt 3840 0000 [Xn imm(-256..+255)] -INST1(ldurh, "ldurh", 0,LD, IF_LS_2C, 0x78400000) +INST1(ldurh, "ldurh", LD, IF_LS_2C, 0x78400000) // ldurh Rt,[Xn+simm9] LS_2C 01111000010iiiii iiii00nnnnnttttt 7840 0000 [Xn imm(-256..+255)] -INST1(ldursb, "ldursb", 0,LD, IF_LS_2C, 0x38800000) +INST1(ldursb, "ldursb", LD, IF_LS_2C, 0x38800000) // ldursb Rt,[Xn+simm9] LS_2C 001110001X0iiiii iiii00nnnnnttttt 3880 0000 [Xn imm(-256..+255)] -INST1(ldursh, "ldursh", 0,LD, IF_LS_2C, 0x78800000) +INST1(ldursh, "ldursh", LD, IF_LS_2C, 0x78800000) // ldursh Rt,[Xn+simm9] LS_2C 011110001X0iiiii iiii00nnnnnttttt 7880 0000 [Xn imm(-256..+255)] -INST1(ldursw, "ldursw", 0,LD, IF_LS_2C, 0xB8800000) +INST1(ldursw, "ldursw", LD, IF_LS_2C, 0xB8800000) // ldursw Rt,[Xn+simm9] LS_2C 10111000100iiiii iiii00nnnnnttttt B880 0000 [Xn imm(-256..+255)] -INST1(stlr, "stlr", 0,ST, IF_LS_2A, 0x889FFC00) +INST1(stlr, "stlr", ST, IF_LS_2A, 0x889FFC00) // stlr Rt,[Xn] LS_2A 1X00100010011111 111111nnnnnttttt 889F FC00 -INST1(stlrb, "stlrb", 0,ST, IF_LS_2A, 0x089FFC00) +INST1(stlrb, "stlrb", ST, IF_LS_2A, 0x089FFC00) // stlrb Rt,[Xn] LS_2A 0000100010011111 111111nnnnnttttt 089F FC00 -INST1(stlrh, "stlrh", 0,ST, IF_LS_2A, 0x489FFC00) +INST1(stlrh, "stlrh", ST, IF_LS_2A, 0x489FFC00) // stlrh Rt,[Xn] LS_2A 0100100010011111 111111nnnnnttttt 489F FC00 -INST1(stxr, "stxr", 0,ST, IF_LS_3D, 0x88007C00) +INST1(stxr, "stxr", ST, IF_LS_3D, 0x88007C00) // stxr Ws, Rt,[Xn] LS_3D 1X001000000sssss 011111nnnnnttttt 8800 7C00 -INST1(stxrb, "stxrb", 0,ST, IF_LS_3D, 0x08007C00) +INST1(stxrb, "stxrb", ST, IF_LS_3D, 0x08007C00) // stxrb Ws, Rt,[Xn] LS_3D 00001000000sssss 011111nnnnnttttt 0800 7C00 -INST1(stxrh, "stxrh", 0,ST, IF_LS_3D, 0x48007C00) +INST1(stxrh, "stxrh", ST, IF_LS_3D, 0x48007C00) // stxrh Ws, Rt,[Xn] LS_3D 01001000000sssss 011111nnnnnttttt 4800 7C00 -INST1(stlxr, "stlxr", 0,ST, IF_LS_3D, 0x8800FC00) +INST1(stlxr, "stlxr", ST, IF_LS_3D, 0x8800FC00) // stlxr Ws, Rt,[Xn] LS_3D 1X001000000sssss 111111nnnnnttttt 8800 FC00 -INST1(stlxrb, "stlxrb", 0,ST, IF_LS_3D, 0x0800FC00) +INST1(stlxrb, "stlxrb", ST, IF_LS_3D, 0x0800FC00) // stlxrb Ws, Rt,[Xn] LS_3D 00001000000sssss 111111nnnnnttttt 0800 FC00 -INST1(stlxrh, "stlxrh", 0,ST, IF_LS_3D, 0x4800FC00) +INST1(stlxrh, "stlxrh", ST, IF_LS_3D, 0x4800FC00) // stlxrh Ws, Rt,[Xn] LS_3D 01001000000sssss 111111nnnnnttttt 4800 FC00 -INST1(stur, "stur", 0,ST, IF_LS_2C, 0xB8000000) +INST1(stur, "stur", ST, IF_LS_2C, 0xB8000000) // stur Rt,[Xn+simm9] LS_2C 1X111000000iiiii iiii00nnnnnttttt B800 0000 [Xn imm(-256..+255)] -INST1(sturb, "sturb", 0,ST, IF_LS_2C, 0x38000000) +INST1(sturb, "sturb", ST, IF_LS_2C, 0x38000000) // sturb Rt,[Xn+simm9] LS_2C 00111000000iiiii iiii00nnnnnttttt 3800 0000 [Xn imm(-256..+255)] -INST1(sturh, "sturh", 0,ST, IF_LS_2C, 0x78000000) +INST1(sturh, "sturh", ST, IF_LS_2C, 0x78000000) // sturh Rt,[Xn+simm9] LS_2C 01111000000iiiii iiii00nnnnnttttt 7800 0000 [Xn imm(-256..+255)] -INST1(casb, "casb", 0, LD|ST, IF_LS_3E, 0x08A07C00) +INST1(casb, "casb", LD|ST, IF_LS_3E, 0x08A07C00) // casb Wm, Wt, [Xn] LS_3E 00001000101mmmmm 011111nnnnnttttt 08A0 7C00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casab, "casab", 0, LD|ST, IF_LS_3E, 0x08E07C00) +INST1(casab, "casab", LD|ST, IF_LS_3E, 0x08E07C00) // casab Wm, Wt, [Xn] LS_3E 00001000111mmmmm 011111nnnnnttttt 08E0 7C00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casalb, "casalb", 0, LD|ST, IF_LS_3E, 0x08E0FC00) +INST1(casalb, "casalb", LD|ST, IF_LS_3E, 0x08E0FC00) // casalb Wm, Wt, [Xn] LS_3E 00001000111mmmmm 111111nnnnnttttt 08E0 FC00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(caslb, "caslb", 0, LD|ST, IF_LS_3E, 0x08A0FC00) +INST1(caslb, "caslb", LD|ST, IF_LS_3E, 0x08A0FC00) // caslb Wm, Wt, [Xn] LS_3E 00001000101mmmmm 111111nnnnnttttt 08A0 FC00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(cash, "cash", 0, LD|ST, IF_LS_3E, 0x48A07C00) +INST1(cash, "cash", LD|ST, IF_LS_3E, 0x48A07C00) // cash Wm, Wt, [Xn] LS_3E 01001000101mmmmm 011111nnnnnttttt 48A0 7C00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casah, "casah", 0, LD|ST, IF_LS_3E, 0x48E07C00) +INST1(casah, "casah", LD|ST, IF_LS_3E, 0x48E07C00) // casah Wm, Wt, [Xn] LS_3E 01001000111mmmmm 011111nnnnnttttt 48E0 7C00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casalh, "casalh", 0, LD|ST, IF_LS_3E, 0x48E0FC00) +INST1(casalh, "casalh", LD|ST, IF_LS_3E, 0x48E0FC00) // casalh Wm, Wt, [Xn] LS_3E 01001000111mmmmm 111111nnnnnttttt 48E0 FC00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(caslh, "caslh", 0, LD|ST, IF_LS_3E, 0x48A0FC00) +INST1(caslh, "caslh", LD|ST, IF_LS_3E, 0x48A0FC00) // caslh Wm, Wt, [Xn] LS_3E 01001000101mmmmm 111111nnnnnttttt 48A0 FC00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(cas, "cas", 0, LD|ST, IF_LS_3E, 0x88A07C00) +INST1(cas, "cas", LD|ST, IF_LS_3E, 0x88A07C00) // cas Rm, Rt, [Xn] LS_3E 1X001000101mmmmm 011111nnnnnttttt 88A0 7C00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casa, "casa", 0, LD|ST, IF_LS_3E, 0x88E07C00) +INST1(casa, "casa", LD|ST, IF_LS_3E, 0x88E07C00) // casa Rm, Rt, [Xn] LS_3E 1X001000111mmmmm 011111nnnnnttttt 88E0 7C00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casal, "casal", 0, LD|ST, IF_LS_3E, 0x88E0FC00) +INST1(casal, "casal", LD|ST, IF_LS_3E, 0x88E0FC00) // casal Rm, Rt, [Xn] LS_3E 1X001000111mmmmm 111111nnnnnttttt 88E0 FC00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(casl, "casl", 0, LD|ST, IF_LS_3E, 0x88A0FC00) +INST1(casl, "casl", LD|ST, IF_LS_3E, 0x88A0FC00) // casl Rm, Rt, [Xn] LS_3E 1X001000101mmmmm 111111nnnnnttttt 88A0 FC00 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddb, "ldaddb", 0, LD|ST, IF_LS_3E, 0x38200000) +INST1(ldaddb, "ldaddb", LD|ST, IF_LS_3E, 0x38200000) // ldaddb Wm, Wt, [Xn] LS_3E 00111000001mmmmm 000000nnnnnttttt 3820 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddab, "ldaddab", 0, LD|ST, IF_LS_3E, 0x38A00000) +INST1(ldaddab, "ldaddab", LD|ST, IF_LS_3E, 0x38A00000) // ldaddab Wm, Wt, [Xn] LS_3E 00111000101mmmmm 000000nnnnnttttt 38A0 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddalb,"ldaddalb",0, LD|ST, IF_LS_3E, 0x38E00000) +INST1(ldaddalb, "ldaddalb", LD|ST, IF_LS_3E, 0x38E00000) // ldaddalb Wm, Wt, [Xn] LS_3E 00111000111mmmmm 000000nnnnnttttt 38E0 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddlb, "ldaddlb", 0, LD|ST, IF_LS_3E, 0x38600000) +INST1(ldaddlb, "ldaddlb", LD|ST, IF_LS_3E, 0x38600000) // ldaddlb Wm, Wt, [Xn] LS_3E 00111000011mmmmm 000000nnnnnttttt 3860 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddh, "ldaddh", 0, LD|ST, IF_LS_3E, 0x78200000) +INST1(ldaddh, "ldaddh", LD|ST, IF_LS_3E, 0x78200000) // ldaddh Wm, Wt, [Xn] LS_3E 01111000001mmmmm 000000nnnnnttttt 7820 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddah, "ldaddah", 0, LD|ST, IF_LS_3E, 0x78A00000) +INST1(ldaddah, "ldaddah", LD|ST, IF_LS_3E, 0x78A00000) // ldaddah Wm, Wt, [Xn] LS_3E 01111000101mmmmm 000000nnnnnttttt 78A0 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddalh,"ldaddalh",0, LD|ST, IF_LS_3E, 0x78E00000) +INST1(ldaddalh, "ldaddalh", LD|ST, IF_LS_3E, 0x78E00000) // ldaddalh Wm, Wt, [Xn] LS_3E 01111000111mmmmm 000000nnnnnttttt 78E0 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddlh, "ldaddlh", 0, LD|ST, IF_LS_3E, 0x78600000) +INST1(ldaddlh, "ldaddlh", LD|ST, IF_LS_3E, 0x78600000) // ldaddlh Wm, Wt, [Xn] LS_3E 01111000011mmmmm 000000nnnnnttttt 7860 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldadd, "ldadd", 0, LD|ST, IF_LS_3E, 0xB8200000) +INST1(ldadd, "ldadd", LD|ST, IF_LS_3E, 0xB8200000) // ldadd Rm, Rt, [Xn] LS_3E 1X111000001mmmmm 000000nnnnnttttt B820 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldadda, "ldadda", 0, LD|ST, IF_LS_3E, 0xB8A00000) +INST1(ldadda, "ldadda", LD|ST, IF_LS_3E, 0xB8A00000) // ldadda Rm, Rt, [Xn] LS_3E 1X111000101mmmmm 000000nnnnnttttt B8A0 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddal, "ldaddal", 0, LD|ST, IF_LS_3E, 0xB8E00000) +INST1(ldaddal, "ldaddal", LD|ST, IF_LS_3E, 0xB8E00000) // ldaddal Rm, Rt, [Xn] LS_3E 1X111000111mmmmm 000000nnnnnttttt B8E0 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(ldaddl, "ldaddl", 0, LD|ST, IF_LS_3E, 0xB8600000) +INST1(ldaddl, "ldaddl", LD|ST, IF_LS_3E, 0xB8600000) // ldaddl Rm, Rt, [Xn] LS_3E 1X111000011mmmmm 000000nnnnnttttt B860 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(staddb, "staddb", 0, ST, IF_LS_3E, 0x38200000) +INST1(staddb, "staddb", ST, IF_LS_3E, 0x38200000) // staddb Wm, [Xn] LS_3E 00111000001mmmmm 000000nnnnnttttt 3820 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(staddlb, "staddlb", 0, ST, IF_LS_3E, 0x38600000) +INST1(staddlb, "staddlb", ST, IF_LS_3E, 0x38600000) // staddlb Wm, [Xn] LS_3E 00111000011mmmmm 000000nnnnnttttt 3860 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(staddh, "staddh", 0, ST, IF_LS_3E, 0x78200000) +INST1(staddh, "staddh", ST, IF_LS_3E, 0x78200000) // staddh Wm, [Xn] LS_3E 01111000001mmmmm 000000nnnnnttttt 7820 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(staddlh, "staddlh", 0, ST, IF_LS_3E, 0x78600000) +INST1(staddlh, "staddlh", ST, IF_LS_3E, 0x78600000) // staddlh Wm, [Xn] LS_3E 01111000011mmmmm 000000nnnnnttttt 7860 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(stadd, "stadd", 0, ST, IF_LS_3E, 0xB8200000) +INST1(stadd, "stadd", ST, IF_LS_3E, 0xB8200000) // stadd Rm, [Xn] LS_3E 1X111000001mmmmm 000000nnnnnttttt B820 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(staddl, "staddl", 0, ST, IF_LS_3E, 0xB8600000) +INST1(staddl, "staddl", ST, IF_LS_3E, 0xB8600000) // staddl Rm, [Xn] LS_3E 1X111000011mmmmm 000000nnnnnttttt B860 0000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpb, "swpb", 0, LD|ST, IF_LS_3E, 0x38208000) +INST1(swpb, "swpb", LD|ST, IF_LS_3E, 0x38208000) // swpb Wm, Wt, [Xn] LS_3E 00111000001mmmmm 100000nnnnnttttt 3820 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpab, "swpab", 0, LD|ST, IF_LS_3E, 0x38A08000) +INST1(swpab, "swpab", LD|ST, IF_LS_3E, 0x38A08000) // swpab Wm, Wt, [Xn] LS_3E 00111000101mmmmm 100000nnnnnttttt 38A0 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpalb, "swpalb", 0, LD|ST, IF_LS_3E, 0x38E08000) +INST1(swpalb, "swpalb", LD|ST, IF_LS_3E, 0x38E08000) // swpalb Wm, Wt, [Xn] LS_3E 00111000111mmmmm 100000nnnnnttttt 38E0 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swplb, "swplb", 0, LD|ST, IF_LS_3E, 0x38608000) +INST1(swplb, "swplb", LD|ST, IF_LS_3E, 0x38608000) // swplb Wm, Wt, [Xn] LS_3E 00111000011mmmmm 100000nnnnnttttt 3860 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swph, "swph", 0, LD|ST, IF_LS_3E, 0x78208000) +INST1(swph, "swph", LD|ST, IF_LS_3E, 0x78208000) // swph Wm, Wt, [Xn] LS_3E 01111000001mmmmm 100000nnnnnttttt 7820 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpah, "swpah", 0, LD|ST, IF_LS_3E, 0x78A08000) +INST1(swpah, "swpah", LD|ST, IF_LS_3E, 0x78A08000) // swpah Wm, Wt, [Xn] LS_3E 01111000101mmmmm 100000nnnnnttttt 78A0 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpalh, "swpalh", 0, LD|ST, IF_LS_3E, 0x78E08000) +INST1(swpalh, "swpalh", LD|ST, IF_LS_3E, 0x78E08000) // swpalh Wm, Wt, [Xn] LS_3E 01111000111mmmmm 100000nnnnnttttt 78E0 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swplh, "swplh", 0, LD|ST, IF_LS_3E, 0x78608000) +INST1(swplh, "swplh", LD|ST, IF_LS_3E, 0x78608000) // swplh Wm, Wt, [Xn] LS_3E 01111000011mmmmm 100000nnnnnttttt 7860 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swp, "swp", 0, LD|ST, IF_LS_3E, 0xB8208000) +INST1(swp, "swp", LD|ST, IF_LS_3E, 0xB8208000) // swp Rm, Rt, [Xn] LS_3E 1X111000001mmmmm 100000nnnnnttttt B820 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpa, "swpa", 0, LD|ST, IF_LS_3E, 0xB8A08000) +INST1(swpa, "swpa", LD|ST, IF_LS_3E, 0xB8A08000) // swpa Rm, Rt, [Xn] LS_3E 1X111000101mmmmm 100000nnnnnttttt B8A0 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpal, "swpal", 0, LD|ST, IF_LS_3E, 0xB8E08000) +INST1(swpal, "swpal", LD|ST, IF_LS_3E, 0xB8E08000) // swpal Rm, Rt, [Xn] LS_3E 1X111000111mmmmm 100000nnnnnttttt B8E0 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(swpl, "swpl", 0, LD|ST, IF_LS_3E, 0xB8608000) +INST1(swpl, "swpl", LD|ST, IF_LS_3E, 0xB8608000) // swpl Rm, Rt, [Xn] LS_3E 1X111000011mmmmm 100000nnnnnttttt B860 8000 Rm Rt Rn ARMv8.1 LSE Atomics -INST1(adr, "adr", 0, 0, IF_DI_1E, 0x10000000) +INST1(adr, "adr", 0, IF_DI_1E, 0x10000000) // adr Rd, simm21 DI_1E 0ii10000iiiiiiii iiiiiiiiiiiddddd 1000 0000 Rd simm21 -INST1(adrp, "adrp", 0, 0, IF_DI_1E, 0x90000000) +INST1(adrp, "adrp", 0, IF_DI_1E, 0x90000000) // adrp Rd, simm21 DI_1E 1ii10000iiiiiiii iiiiiiiiiiiddddd 9000 0000 Rd simm21 -INST1(b, "b", 0, 0, IF_BI_0A, 0x14000000) +INST1(b, "b", 0, IF_BI_0A, 0x14000000) // b simm26 BI_0A 000101iiiiiiiiii iiiiiiiiiiiiiiii 1400 0000 simm26:00 -INST1(b_tail, "b", 0, 0, IF_BI_0C, 0x14000000) +INST1(b_tail, "b", 0, IF_BI_0C, 0x14000000) // b simm26 BI_0A 000101iiiiiiiiii iiiiiiiiiiiiiiii 1400 0000 simm26:00, same as b representing a tail call of bl. -INST1(bl_local,"bl", 0, 0, IF_BI_0A, 0x94000000) +INST1(bl_local, "bl", 0, IF_BI_0A, 0x94000000) // bl simm26 BI_0A 100101iiiiiiiiii iiiiiiiiiiiiiiii 9400 0000 simm26:00, same as bl, but with a BasicBlock target. -INST1(bl, "bl", 0, 0, IF_BI_0C, 0x94000000) +INST1(bl, "bl", 0, IF_BI_0C, 0x94000000) // bl simm26 BI_0C 100101iiiiiiiiii iiiiiiiiiiiiiiii 9400 0000 simm26:00 -INST1(br, "br", 0, 0, IF_BR_1A, 0xD61F0000) +INST1(br, "br", 0, IF_BR_1A, 0xD61F0000) // br Rn BR_1A 1101011000011111 000000nnnnn00000 D61F 0000, an indirect branch like switch expansion -INST1(br_tail, "br", 0, 0, IF_BR_1B, 0xD61F0000) +INST1(br_tail, "br", 0, IF_BR_1B, 0xD61F0000) // br Rn BR_1B 1101011000011111 000000nnnnn00000 D61F 0000, same as br representing a tail call of blr. Encode target with Reg3. -INST1(blr, "blr", 0, 0, IF_BR_1B, 0xD63F0000) +INST1(blr, "blr", 0, IF_BR_1B, 0xD63F0000) // blr Rn BR_1B 1101011000111111 000000nnnnn00000 D63F 0000, Encode target with Reg3. -INST1(ret, "ret", 0, 0, IF_BR_1A, 0xD65F0000) +INST1(ret, "ret", 0, IF_BR_1A, 0xD65F0000) // ret Rn BR_1A 1101011001011111 000000nnnnn00000 D65F 0000 -INST1(beq, "beq", 0, 0, IF_BI_0B, 0x54000000) +INST1(beq, "beq", 0, IF_BI_0B, 0x54000000) // beq simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00000 5400 0000 simm19:00 -INST1(bne, "bne", 0, 0, IF_BI_0B, 0x54000001) +INST1(bne, "bne", 0, IF_BI_0B, 0x54000001) // bne simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00001 5400 0001 simm19:00 -INST1(bhs, "bhs", 0, 0, IF_BI_0B, 0x54000002) +INST1(bhs, "bhs", 0, IF_BI_0B, 0x54000002) // bhs simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00010 5400 0002 simm19:00 -INST1(blo, "blo", 0, 0, IF_BI_0B, 0x54000003) +INST1(blo, "blo", 0, IF_BI_0B, 0x54000003) // blo simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00011 5400 0003 simm19:00 -INST1(bmi, "bmi", 0, 0, IF_BI_0B, 0x54000004) +INST1(bmi, "bmi", 0, IF_BI_0B, 0x54000004) // bmi simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00100 5400 0004 simm19:00 -INST1(bpl, "bpl", 0, 0, IF_BI_0B, 0x54000005) +INST1(bpl, "bpl", 0, IF_BI_0B, 0x54000005) // bpl simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00101 5400 0005 simm19:00 -INST1(bvs, "bvs", 0, 0, IF_BI_0B, 0x54000006) +INST1(bvs, "bvs", 0, IF_BI_0B, 0x54000006) // bvs simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00110 5400 0006 simm19:00 -INST1(bvc, "bvc", 0, 0, IF_BI_0B, 0x54000007) +INST1(bvc, "bvc", 0, IF_BI_0B, 0x54000007) // bvc simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii00111 5400 0007 simm19:00 -INST1(bhi, "bhi", 0, 0, IF_BI_0B, 0x54000008) +INST1(bhi, "bhi", 0, IF_BI_0B, 0x54000008) // bhi simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii01000 5400 0008 simm19:00 -INST1(bls, "bls", 0, 0, IF_BI_0B, 0x54000009) +INST1(bls, "bls", 0, IF_BI_0B, 0x54000009) // bls simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii01001 5400 0009 simm19:00 -INST1(bge, "bge", 0, 0, IF_BI_0B, 0x5400000A) +INST1(bge, "bge", 0, IF_BI_0B, 0x5400000A) // bge simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii01010 5400 000A simm19:00 -INST1(blt, "blt", 0, 0, IF_BI_0B, 0x5400000B) +INST1(blt, "blt", 0, IF_BI_0B, 0x5400000B) // blt simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii01011 5400 000B simm19:00 -INST1(bgt, "bgt", 0, 0, IF_BI_0B, 0x5400000C) +INST1(bgt, "bgt", 0, IF_BI_0B, 0x5400000C) // bgt simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii01100 5400 000C simm19:00 -INST1(ble, "ble", 0, 0, IF_BI_0B, 0x5400000D) +INST1(ble, "ble", 0, IF_BI_0B, 0x5400000D) // ble simm19 BI_0B 01010100iiiiiiii iiiiiiiiiii01101 5400 000D simm19:00 -INST1(cbz, "cbz", 0, 0, IF_BI_1A, 0x34000000) +INST1(cbz, "cbz", 0, IF_BI_1A, 0x34000000) // cbz Rt, simm19 BI_1A X0110100iiiiiiii iiiiiiiiiiittttt 3400 0000 Rt simm19:00 -INST1(cbnz, "cbnz", 0, 0, IF_BI_1A, 0x35000000) +INST1(cbnz, "cbnz", 0, IF_BI_1A, 0x35000000) // cbnz Rt, simm19 BI_1A X0110101iiiiiiii iiiiiiiiiiittttt 3500 0000 Rt simm19:00 -INST1(tbz, "tbz", 0, 0, IF_BI_1B, 0x36000000) +INST1(tbz, "tbz", 0, IF_BI_1B, 0x36000000) // tbz Rt, imm6, simm14 BI_1B B0110110bbbbbiii iiiiiiiiiiittttt 3600 0000 Rt imm6, simm14:00 -INST1(tbnz, "tbnz", 0, 0, IF_BI_1B, 0x37000000) +INST1(tbnz, "tbnz", 0, IF_BI_1B, 0x37000000) // tbnz Rt, imm6, simm14 BI_1B B0110111bbbbbiii iiiiiiiiiiittttt 3700 0000 Rt imm6, simm14:00 -INST1(movk, "movk", 0, 0, IF_DI_1B, 0x72800000) +INST1(movk, "movk", 0, IF_DI_1B, 0x72800000) // movk Rd,imm(i16,hw) DI_1B X11100101hwiiiii iiiiiiiiiiiddddd 7280 0000 imm(i16,hw) -INST1(movn, "movn", 0, 0, IF_DI_1B, 0x12800000) +INST1(movn, "movn", 0, IF_DI_1B, 0x12800000) // movn Rd,imm(i16,hw) DI_1B X00100101hwiiiii iiiiiiiiiiiddddd 1280 0000 imm(i16,hw) -INST1(movz, "movz", 0, 0, IF_DI_1B, 0x52800000) +INST1(movz, "movz", 0, IF_DI_1B, 0x52800000) // movz Rd,imm(i16,hw) DI_1B X10100101hwiiiii iiiiiiiiiiiddddd 5280 0000 imm(i16,hw) -INST1(csel, "csel", 0, 0, IF_DR_3D, 0x1A800000) +INST1(csel, "csel", 0, IF_DR_3D, 0x1A800000) // csel Rd,Rn,Rm,cond DR_3D X0011010100mmmmm cccc00nnnnnddddd 1A80 0000 cond -INST1(csinc, "csinc", 0, 0, IF_DR_3D, 0x1A800400) +INST1(csinc, "csinc", 0, IF_DR_3D, 0x1A800400) // csinc Rd,Rn,Rm,cond DR_3D X0011010100mmmmm cccc01nnnnnddddd 1A80 0400 cond -INST1(csinv, "csinv", 0, 0, IF_DR_3D, 0x5A800000) +INST1(csinv, "csinv", 0, IF_DR_3D, 0x5A800000) // csinv Rd,Rn,Rm,cond DR_3D X1011010100mmmmm cccc00nnnnnddddd 5A80 0000 cond -INST1(csneg, "csneg", 0, 0, IF_DR_3D, 0x5A800400) +INST1(csneg, "csneg", 0, IF_DR_3D, 0x5A800400) // csneg Rd,Rn,Rm,cond DR_3D X1011010100mmmmm cccc01nnnnnddddd 5A80 0400 cond -INST1(cinc, "cinc", 0, 0, IF_DR_2D, 0x1A800400) +INST1(cinc, "cinc", 0, IF_DR_2D, 0x1A800400) // cinc Rd,Rn,cond DR_2D X0011010100nnnnn cccc01nnnnnddddd 1A80 0400 cond -INST1(cinv, "cinv", 0, 0, IF_DR_2D, 0x5A800000) +INST1(cinv, "cinv", 0, IF_DR_2D, 0x5A800000) // cinv Rd,Rn,cond DR_2D X1011010100nnnnn cccc00nnnnnddddd 5A80 0000 cond -INST1(cneg, "cneg", 0, 0, IF_DR_2D, 0x5A800400) +INST1(cneg, "cneg", 0, IF_DR_2D, 0x5A800400) // cneg Rd,Rn,cond DR_2D X1011010100nnnnn cccc01nnnnnddddd 5A80 0400 cond -INST1(cset, "cset", 0, 0, IF_DR_1D, 0x1A9F07E0) +INST1(cset, "cset", 0, IF_DR_1D, 0x1A9F07E0) // cset Rd,cond DR_1D X001101010011111 cccc0111111ddddd 1A9F 07E0 Rd cond -INST1(csetm, "csetm", 0, 0, IF_DR_1D, 0x5A9F03E0) +INST1(csetm, "csetm", 0, IF_DR_1D, 0x5A9F03E0) // csetm Rd,cond DR_1D X101101010011111 cccc0011111ddddd 5A9F 03E0 Rd cond -INST1(aese, "aese", 0, 0, IF_DV_2P, 0x4E284800) +INST1(aese, "aese", 0, IF_DV_2P, 0x4E284800) // aese Vd.16B,Vn.16B DV_2P 0100111000101000 010010nnnnnddddd 4E28 4800 Vd.16B Vn.16B (vector) -INST1(aesd, "aesd", 0, 0, IF_DV_2P, 0x4E285800) +INST1(aesd, "aesd", 0, IF_DV_2P, 0x4E285800) // aesd Vd.16B,Vn.16B DV_2P 0100111000101000 010110nnnnnddddd 4E28 5800 Vd.16B Vn.16B (vector) -INST1(aesmc, "aesmc", 0, 0, IF_DV_2P, 0x4E286800) +INST1(aesmc, "aesmc", 0, IF_DV_2P, 0x4E286800) // aesmc Vd.16B,Vn.16B DV_2P 0100111000101000 011010nnnnnddddd 4E28 6800 Vd.16B Vn.16B (vector) -INST1(aesimc, "aesimc", 0, 0, IF_DV_2P, 0x4E287800) +INST1(aesimc, "aesimc", 0, IF_DV_2P, 0x4E287800) // aesimc Vd.16B,Vn.16B DV_2P 0100111000101000 011110nnnnnddddd 4E28 7800 Vd.16B Vn.16B (vector) -INST1(rev, "rev", 0, 0, IF_DR_2G, 0x5AC00800) +INST1(rev, "rev", 0, IF_DR_2G, 0x5AC00800) // rev Rd,Rm DR_2G X101101011000000 00001Xnnnnnddddd 5AC0 0800 Rd Rn -INST1(rev64, "rev64", 0, 0, IF_DV_2M, 0x0E200800) +INST1(rev64, "rev64", 0, IF_DV_2M, 0x0E200800) // rev64 Vd,Vn DV_2M 0Q001110XX100000 000010nnnnnddddd 0E20 0800 Vd,Vn (vector) -INST1(adc, "adc", 0, 0, IF_DR_3A, 0x1A000000) +INST1(adc, "adc", 0, IF_DR_3A, 0x1A000000) // adc Rd,Rn,Rm DR_3A X0011010000mmmmm 000000nnnnnddddd 1A00 0000 -INST1(adcs, "adcs", 0, 0, IF_DR_3A, 0x3A000000) +INST1(adcs, "adcs", 0, IF_DR_3A, 0x3A000000) // adcs Rd,Rn,Rm DR_3A X0111010000mmmmm 000000nnnnnddddd 3A00 0000 -INST1(sbc, "sbc", 0, 0, IF_DR_3A, 0x5A000000) +INST1(sbc, "sbc", 0, IF_DR_3A, 0x5A000000) // sdc Rd,Rn,Rm DR_3A X1011010000mmmmm 000000nnnnnddddd 5A00 0000 -INST1(sbcs, "sbcs", 0, 0, IF_DR_3A, 0x7A000000) +INST1(sbcs, "sbcs", 0, IF_DR_3A, 0x7A000000) // sdcs Rd,Rn,Rm DR_3A X1111010000mmmmm 000000nnnnnddddd 7A00 0000 -INST1(udiv, "udiv", 0, 0, IF_DR_3A, 0x1AC00800) +INST1(udiv, "udiv", 0, IF_DR_3A, 0x1AC00800) // udiv Rd,Rn,Rm DR_3A X0011010110mmmmm 000010nnnnnddddd 1AC0 0800 -INST1(sdiv, "sdiv", 0, 0, IF_DR_3A, 0x1AC00C00) +INST1(sdiv, "sdiv", 0, IF_DR_3A, 0x1AC00C00) // sdiv Rd,Rn,Rm DR_3A X0011010110mmmmm 000011nnnnnddddd 1AC0 0C00 -INST1(mneg, "mneg", 0, 0, IF_DR_3A, 0x1B00FC00) +INST1(mneg, "mneg", 0, IF_DR_3A, 0x1B00FC00) // mneg Rd,Rn,Rm DR_3A X0011011000mmmmm 111111nnnnnddddd 1B00 FC00 -INST1(madd, "madd", 0, 0, IF_DR_4A, 0x1B000000) +INST1(madd, "madd", 0, IF_DR_4A, 0x1B000000) // madd Rd,Rn,Rm,Ra DR_4A X0011011000mmmmm 0aaaaannnnnddddd 1B00 0000 -INST1(msub, "msub", 0, 0, IF_DR_4A, 0x1B008000) +INST1(msub, "msub", 0, IF_DR_4A, 0x1B008000) // msub Rd,Rn,Rm,Ra DR_4A X0011011000mmmmm 1aaaaannnnnddddd 1B00 8000 -INST1(smaddl, "smaddl", 0, 0, IF_DR_4A, 0x9B200000) +INST1(smaddl, "smaddl", 0, IF_DR_4A, 0x9B200000) // smaddl Rd,Rn,Rm,Ra DR_4A 10011011001mmmmm 0aaaaannnnnddddd 9B20 0000 -INST1(smnegl, "smnegl", 0, 0, IF_DR_3A, 0x9B20FC00) +INST1(smnegl, "smnegl", 0, IF_DR_3A, 0x9B20FC00) // smnegl Rd,Rn,Rm DR_3A 10011011001mmmmm 111111nnnnnddddd 9B20 FC00 -INST1(smsubl, "smsubl", 0, 0, IF_DR_4A, 0x9B208000) +INST1(smsubl, "smsubl", 0, IF_DR_4A, 0x9B208000) // smsubl Rd,Rn,Rm,Ra DR_4A 10011011001mmmmm 1aaaaannnnnddddd 9B20 8000 -INST1(smulh, "smulh", 0, 0, IF_DR_3A, 0x9B407C00) +INST1(smulh, "smulh", 0, IF_DR_3A, 0x9B407C00) // smulh Rd,Rn,Rm DR_3A 10011011010mmmmm 011111nnnnnddddd 9B40 7C00 -INST1(umaddl, "umaddl", 0, 0, IF_DR_4A, 0x9BA00000) +INST1(umaddl, "umaddl", 0, IF_DR_4A, 0x9BA00000) // umaddl Rd,Rn,Rm,Ra DR_4A 10011011101mmmmm 0aaaaannnnnddddd 9BA0 0000 -INST1(umnegl, "umnegl", 0, 0, IF_DR_3A, 0x9BA0FC00) +INST1(umnegl, "umnegl", 0, IF_DR_3A, 0x9BA0FC00) // umnegl Rd,Rn,Rm DR_3A 10011011101mmmmm 111111nnnnnddddd 9BA0 FC00 -INST1(umsubl, "umsubl", 0, 0, IF_DR_4A, 0x9BA08000) +INST1(umsubl, "umsubl", 0, IF_DR_4A, 0x9BA08000) // umsubl Rd,Rn,Rm,Ra DR_4A 10011011101mmmmm 1aaaaannnnnddddd 9BA0 8000 -INST1(umulh, "umulh", 0, 0, IF_DR_3A, 0x9BC07C00) +INST1(umulh, "umulh", 0, IF_DR_3A, 0x9BC07C00) // umulh Rd,Rn,Rm DR_3A 10011011110mmmmm 011111nnnnnddddd 9BC0 7C00 -INST1(extr, "extr", 0, 0, IF_DR_3E, 0x13800000) +INST1(extr, "extr", 0, IF_DR_3E, 0x13800000) // extr Rd,Rn,Rm,imm6 DR_3E X00100111X0mmmmm ssssssnnnnnddddd 1380 0000 imm(0-63) -INST1(lslv, "lslv", 0, 0, IF_DR_3A, 0x1AC02000) +INST1(lslv, "lslv", 0, IF_DR_3A, 0x1AC02000) // lslv Rd,Rn,Rm DR_3A X0011010110mmmmm 001000nnnnnddddd 1AC0 2000 -INST1(lsrv, "lsrv", 0, 0, IF_DR_3A, 0x1AC02400) +INST1(lsrv, "lsrv", 0, IF_DR_3A, 0x1AC02400) // lsrv Rd,Rn,Rm DR_3A X0011010110mmmmm 001001nnnnnddddd 1AC0 2400 -INST1(asrv, "asrv", 0, 0, IF_DR_3A, 0x1AC02800) +INST1(asrv, "asrv", 0, IF_DR_3A, 0x1AC02800) // asrv Rd,Rn,Rm DR_3A X0011010110mmmmm 001010nnnnnddddd 1AC0 2800 -INST1(rorv, "rorv", 0, 0, IF_DR_3A, 0x1AC02C00) +INST1(rorv, "rorv", 0, IF_DR_3A, 0x1AC02C00) // rorv Rd,Rn,Rm DR_3A X0011010110mmmmm 001011nnnnnddddd 1AC0 2C00 -INST1(crc32b, "crc32b", 0, 0, IF_DR_3A, 0x1AC04000) +INST1(crc32b, "crc32b", 0, IF_DR_3A, 0x1AC04000) // crc32b Rd,Rn,Rm DR_3A 00011010110mmmmm 010000nnnnnddddd 1AC0 4000 -INST1(crc32h, "crc32h", 0, 0, IF_DR_3A, 0x1AC04400) +INST1(crc32h, "crc32h", 0, IF_DR_3A, 0x1AC04400) // crc32h Rd,Rn,Rm DR_3A 00011010110mmmmm 010001nnnnnddddd 1AC0 4400 -INST1(crc32w, "crc32w", 0, 0, IF_DR_3A, 0x1AC04800) +INST1(crc32w, "crc32w", 0, IF_DR_3A, 0x1AC04800) // crc32w Rd,Rn,Rm DR_3A 00011010110mmmmm 010010nnnnnddddd 1AC0 4800 -INST1(crc32x, "crc32x", 0, 0, IF_DR_3A, 0x9AC04C00) +INST1(crc32x, "crc32x", 0, IF_DR_3A, 0x9AC04C00) // crc32x Rd,Rn,Xm DR_3A 10011010110mmmmm 010011nnnnnddddd 9AC0 4C00 -INST1(crc32cb, "crc32cb",0, 0, IF_DR_3A, 0x1AC05000) +INST1(crc32cb, "crc32cb", 0, IF_DR_3A, 0x1AC05000) // crc32cb Rd,Rn,Rm DR_3A 00011010110mmmmm 010100nnnnnddddd 1AC0 5000 -INST1(crc32ch, "crc32ch",0, 0, IF_DR_3A, 0x1AC05400) +INST1(crc32ch, "crc32ch", 0, IF_DR_3A, 0x1AC05400) // crc32ch Rd,Rn,Rm DR_3A 00011010110mmmmm 010101nnnnnddddd 1AC0 5400 -INST1(crc32cw, "crc32cw",0, 0, IF_DR_3A, 0x1AC05800) +INST1(crc32cw, "crc32cw", 0, IF_DR_3A, 0x1AC05800) // crc32cw Rd,Rn,Rm DR_3A 00011010110mmmmm 010110nnnnnddddd 1AC0 5800 -INST1(crc32cx, "crc32cx",0, 0, IF_DR_3A, 0x9AC05C00) +INST1(crc32cx, "crc32cx", 0, IF_DR_3A, 0x9AC05C00) // crc32cx Rd,Rn,Xm DR_3A 10011010110mmmmm 010111nnnnnddddd 9AC0 5C00 -INST1(sha1c, "sha1c", 0, 0, IF_DV_3F, 0x5E000000) +INST1(sha1c, "sha1c", 0, IF_DV_3F, 0x5E000000) // sha1c Qd, Sn Vm.4S DV_3F 01011110000mmmmm 000000nnnnnddddd 5E00 0000 Qd Sn Vm.4S (vector) -INST1(sha1m, "sha1m", 0, 0, IF_DV_3F, 0x5E002000) +INST1(sha1m, "sha1m", 0, IF_DV_3F, 0x5E002000) // sha1m Qd, Sn Vm.4S DV_3F 01011110000mmmmm 001000nnnnnddddd 5E00 0000 Qd Sn Vm.4S (vector) -INST1(sha1p, "sha1p", 0, 0, IF_DV_3F, 0x5E001000) +INST1(sha1p, "sha1p", 0, IF_DV_3F, 0x5E001000) // sha1m Qd, Sn Vm.4S DV_3F 01011110000mmmmm 000100nnnnnddddd 5E00 0000 Qd Sn Vm.4S (vector) -INST1(sha1h, "sha1h", 0, 0, IF_DV_2U, 0x5E280800) +INST1(sha1h, "sha1h", 0, IF_DV_2U, 0x5E280800) // sha1h Sd, Sn DV_2U 0101111000101000 000010nnnnnddddd 5E28 0800 Sn Sn -INST1(sha1su0, "sha1su0", 0, 0, IF_DV_3F, 0x5E003000) +INST1(sha1su0, "sha1su0", 0, IF_DV_3F, 0x5E003000) // sha1su0 Vd.4S,Vn.4S,Vm.4S DV_3F 01011110000mmmmm 001100nnnnnddddd 5E00 3000 Vd.4S Vn.4S Vm.4S (vector) -INST1(sha1su1, "sha1su1", 0, 0, IF_DV_2P, 0x5E281800) +INST1(sha1su1, "sha1su1", 0, IF_DV_2P, 0x5E281800) // sha1su1 Vd.4S, Vn.4S DV_2P 0101111000101000 000110nnnnnddddd 5E28 1800 Vd.4S Vn.4S (vector) -INST1(sha256h, "sha256h", 0, 0, IF_DV_3F, 0x5E004000) +INST1(sha256h, "sha256h", 0, IF_DV_3F, 0x5E004000) // sha256h Qd,Qn,Vm.4S DV_3F 01011110000mmmmm 010000nnnnnddddd 5E00 4000 Qd Qn Vm.4S (vector) -INST1(sha256h2, "sha256h2", 0, 0, IF_DV_3F, 0x5E005000) +INST1(sha256h2, "sha256h2", 0, IF_DV_3F, 0x5E005000) // sha256h Qd,Qn,Vm.4S DV_3F 01011110000mmmmm 010100nnnnnddddd 5E00 5000 Qd Qn Vm.4S (vector) -INST1(sha256su0, "sha256su0", 0, 0, IF_DV_2P, 0x5E282800) +INST1(sha256su0, "sha256su0", 0, IF_DV_2P, 0x5E282800) // sha256su0 Vd.4S,Vn.4S DV_2P 0101111000101000 001010nnnnnddddd 5E28 2800 Vd.4S Vn.4S (vector) -INST1(sha256su1, "sha256su1", 0, 0, IF_DV_3F, 0x5E006000) +INST1(sha256su1, "sha256su1", 0, IF_DV_3F, 0x5E006000) // sha256su1 Vd.4S,Vn.4S,Vm.4S DV_3F 01011110000mmmmm 011000nnnnnddddd 5E00 6000 Vd.4S Vn.4S Vm.4S (vector) -INST1(ext, "ext", 0, 0, IF_DV_3G, 0x2E000000) - // C7.2.36 EXT +INST1(ext, "ext", 0, IF_DV_3G, 0x2E000000) // ext Vd,Vn,Vm,index DV_3G 0Q101110000mmmmm 0iiii0nnnnnddddd 2E00 0000 Vd Vn Vm index (vector) -INST1(sbfm, "sbfm", 0, 0, IF_DI_2D, 0x13000000) +INST1(sbfm, "sbfm", 0, IF_DI_2D, 0x13000000) // sbfm Rd,Rn,imr,ims DI_2D X00100110Nrrrrrr ssssssnnnnnddddd 1300 0000 imr, ims -INST1(bfm, "bfm", 0, 0, IF_DI_2D, 0x33000000) +INST1(bfm, "bfm", 0, IF_DI_2D, 0x33000000) // bfm Rd,Rn,imr,ims DI_2D X01100110Nrrrrrr ssssssnnnnnddddd 3300 0000 imr, ims -INST1(ubfm, "ubfm", 0, 0, IF_DI_2D, 0x53000000) +INST1(ubfm, "ubfm", 0, IF_DI_2D, 0x53000000) // ubfm Rd,Rn,imr,ims DI_2D X10100110Nrrrrrr ssssssnnnnnddddd 5300 0000 imr, ims -INST1(sbfiz, "sbfiz", 0, 0, IF_DI_2D, 0x13000000) +INST1(sbfiz, "sbfiz", 0, IF_DI_2D, 0x13000000) // sbfiz Rd,Rn,lsb,width DI_2D X00100110Nrrrrrr ssssssnnnnnddddd 1300 0000 imr, ims -INST1(bfi, "bfi", 0, 0, IF_DI_2D, 0x33000000) +INST1(bfi, "bfi", 0, IF_DI_2D, 0x33000000) // bfi Rd,Rn,lsb,width DI_2D X01100110Nrrrrrr ssssssnnnnnddddd 3300 0000 imr, ims -INST1(ubfiz, "ubfiz", 0, 0, IF_DI_2D, 0x53000000) +INST1(ubfiz, "ubfiz", 0, IF_DI_2D, 0x53000000) // ubfiz Rd,Rn,lsb,width DI_2D X10100110Nrrrrrr ssssssnnnnnddddd 5300 0000 imr, ims -INST1(sbfx, "sbfx", 0, 0, IF_DI_2D, 0x13000000) +INST1(sbfx, "sbfx", 0, IF_DI_2D, 0x13000000) // sbfx Rd,Rn,lsb,width DI_2D X00100110Nrrrrrr ssssssnnnnnddddd 1300 0000 imr, ims -INST1(bfxil, "bfxil", 0, 0, IF_DI_2D, 0x33000000) +INST1(bfxil, "bfxil", 0, IF_DI_2D, 0x33000000) // bfxil Rd,Rn,lsb,width DI_2D X01100110Nrrrrrr ssssssnnnnnddddd 3300 0000 imr, ims -INST1(ubfx, "ubfx", 0, 0, IF_DI_2D, 0x53000000) +INST1(ubfx, "ubfx", 0, IF_DI_2D, 0x53000000) // ubfx Rd,Rn,lsb,width DI_2D X10100110Nrrrrrr ssssssnnnnnddddd 5300 0000 imr, ims -INST1(sxtb, "sxtb", 0, 0, IF_DR_2H, 0x13001C00) +INST1(sxtb, "sxtb", 0, IF_DR_2H, 0x13001C00) // sxtb Rd,Rn DR_2H X00100110X000000 000111nnnnnddddd 1300 1C00 -INST1(sxth, "sxth", 0, 0, IF_DR_2H, 0x13003C00) +INST1(sxth, "sxth", 0, IF_DR_2H, 0x13003C00) // sxth Rd,Rn DR_2H X00100110X000000 001111nnnnnddddd 1300 3C00 -INST1(sxtw, "sxtw", 0, 0, IF_DR_2H, 0x13007C00) +INST1(sxtw, "sxtw", 0, IF_DR_2H, 0x13007C00) // sxtw Rd,Rn DR_2H X00100110X000000 011111nnnnnddddd 1300 7C00 -INST1(uxtb, "uxtb", 0, 0, IF_DR_2H, 0x53001C00) +INST1(uxtb, "uxtb", 0, IF_DR_2H, 0x53001C00) // uxtb Rd,Rn DR_2H 0101001100000000 000111nnnnnddddd 5300 1C00 -INST1(uxth, "uxth", 0, 0, IF_DR_2H, 0x53003C00) +INST1(uxth, "uxth", 0, IF_DR_2H, 0x53003C00) // uxth Rd,Rn DR_2H 0101001100000000 001111nnnnnddddd 5300 3C00 -INST1(nop, "nop", 0, 0, IF_SN_0A, 0xD503201F) +INST1(nop, "nop", 0, IF_SN_0A, 0xD503201F) // nop SN_0A 1101010100000011 0010000000011111 D503 201F -INST1(bkpt, "bkpt", 0, 0, IF_SN_0A, 0xD43E0000) +INST1(bkpt, "bkpt", 0, IF_SN_0A, 0xD43E0000) // brpt SN_0A 1101010000111110 0000000000000000 D43E 0000 0xF000 -INST1(brk, "brk", 0, 0, IF_SI_0A, 0xD4200000) +INST1(brk, "brk", 0, IF_SI_0A, 0xD4200000) // brk imm16 SI_0A 11010100001iiiii iiiiiiiiiii00000 D420 0000 imm16 -INST1(dsb, "dsb", 0, 0, IF_SI_0B, 0xD503309F) +INST1(dsb, "dsb", 0, IF_SI_0B, 0xD503309F) // dsb barrierKind SI_0B 1101010100000011 0011bbbb10011111 D503 309F imm4 - barrier kind -INST1(dmb, "dmb", 0, 0, IF_SI_0B, 0xD50330BF) +INST1(dmb, "dmb", 0, IF_SI_0B, 0xD50330BF) // dmb barrierKind SI_0B 1101010100000011 0011bbbb10111111 D503 30BF imm4 - barrier kind -INST1(isb, "isb", 0, 0, IF_SI_0B, 0xD50330DF) +INST1(isb, "isb", 0, IF_SI_0B, 0xD50330DF) // isb barrierKind SI_0B 1101010100000011 0011bbbb11011111 D503 30DF imm4 - barrier kind -INST1(umov, "umov", 0, 0, IF_DV_2B, 0x0E003C00) +INST1(umov, "umov", 0, IF_DV_2B, 0x0E003C00) // umov Rd,Vn[] DV_2B 0Q001110000iiiii 001111nnnnnddddd 0E00 3C00 Rd,Vn[] -INST1(smov, "smov", 0, 0, IF_DV_2B, 0x0E002C00) +INST1(smov, "smov", 0, IF_DV_2B, 0x0E002C00) // smov Rd,Vn[] DV_2B 0Q001110000iiiii 001011nnnnnddddd 0E00 3C00 Rd,Vn[] -INST1(movi, "movi", 0, 0, IF_DV_1B, 0x0F000400) +INST1(movi, "movi", 0, IF_DV_1B, 0x0F000400) // movi Vd,imm8 DV_1B 0QX0111100000iii cmod01iiiiiddddd 0F00 0400 Vd imm8 (immediate vector) -INST1(mvni, "mvni", 0, 0, IF_DV_1B, 0x2F000400) +INST1(mvni, "mvni", 0, IF_DV_1B, 0x2F000400) // mvni Vd,imm8 DV_1B 0Q10111100000iii cmod01iiiiiddddd 2F00 0400 Vd imm8 (immediate vector) -INST1(urecpe, "urecpe", 0, 0, IF_DV_2A, 0x0EA1C800) - // C7.2.372 URECPE +INST1(urecpe, "urecpe", 0, IF_DV_2A, 0x0EA1C800) // urecpe Vd,Vn DV_2A 0Q0011101X100001 110010nnnnnddddd 0EA1 C800 Vd,Vn (vector) -INST1(ursqrte, "ursqrte",0, 0, IF_DV_2A, 0x2EA1C800) - // C7.2.376 URSQRTE +INST1(ursqrte, "ursqrte", 0, IF_DV_2A, 0x2EA1C800) // ursqrte Vd,Vn DV_2A 0Q1011101X100001 110010nnnnnddddd 2EA1 C800 Vd,Vn (vector) -INST1(bsl, "bsl", 0, 0, IF_DV_3C, 0x2E601C00) +INST1(bsl, "bsl", 0, IF_DV_3C, 0x2E601C00) // bsl Vd,Vn,Vm DV_3C 0Q101110011mmmmm 000111nnnnnddddd 2E60 1C00 Vd,Vn,Vm -INST1(bit, "bit", 0, 0, IF_DV_3C, 0x2EA01C00) +INST1(bit, "bit", 0, IF_DV_3C, 0x2EA01C00) // bit Vd,Vn,Vm DV_3C 0Q101110101mmmmm 000111nnnnnddddd 2EA0 1C00 Vd,Vn,Vm -INST1(bif, "bif", 0, 0, IF_DV_3C, 0x2EE01C00) +INST1(bif, "bif", 0, IF_DV_3C, 0x2EE01C00) // bif Vd,Vn,Vm DV_3C 0Q101110111mmmmm 000111nnnnnddddd 2EE0 1C00 Vd,Vn,Vm -INST1(addv, "addv", 0, 0, IF_DV_2T, 0x0E31B800) +INST1(addv, "addv", 0, IF_DV_2T, 0x0E31B800) // addv Vd,Vn DV_2T 0Q001110XX110001 101110nnnnnddddd 0E31 B800 Vd,Vn (vector) -INST1(cnt, "cnt", 0, 0, IF_DV_2M, 0x0E205800) +INST1(cnt, "cnt", 0, IF_DV_2M, 0x0E205800) // cnt Vd,Vn DV_2M 0Q00111000100000 010110nnnnnddddd 0E20 5800 Vd,Vn (vector) -INST1(not, "not", 0, 0, IF_DV_2M, 0x2E205800) +INST1(not, "not", 0, IF_DV_2M, 0x2E205800) // not Vd,Vn DV_2M 0Q10111000100000 010110nnnnnddddd 2E20 5800 Vd,Vn (vector) -INST1(saddlv, "saddlv", 0, 0, IF_DV_2T, 0x0E303800) +INST1(saddlv, "saddlv", 0, IF_DV_2T, 0x0E303800) // saddlv Vd,Vn DV_2T 0Q001110XX110000 001110nnnnnddddd 0E30 3800 Vd,Vn (vector) -INST1(smaxv, "smaxv", 0, 0, IF_DV_2T, 0x0E30A800) +INST1(smaxv, "smaxv", 0, IF_DV_2T, 0x0E30A800) // smaxv Vd,Vn DV_2T 0Q001110XX110000 101010nnnnnddddd 0E30 A800 Vd,Vn (vector) -INST1(sminv, "sminv", 0, 0, IF_DV_2T, 0x0E31A800) +INST1(sminv, "sminv", 0, IF_DV_2T, 0x0E31A800) // sminv Vd,Vn DV_2T 0Q001110XX110001 101010nnnnnddddd 0E31 A800 Vd,Vn (vector) -INST1(uaddlv, "uaddlv", 0, 0, IF_DV_2T, 0x2E303800) +INST1(uaddlv, "uaddlv", 0, IF_DV_2T, 0x2E303800) // uaddlv Vd,Vn DV_2T 0Q101110XX110000 001110nnnnnddddd 2E30 3800 Vd,Vn (vector) -INST1(umaxv, "umaxv", 0, 0, IF_DV_2T, 0x2E30A800) +INST1(umaxv, "umaxv", 0, IF_DV_2T, 0x2E30A800) // umaxv Vd,Vn DV_2T 0Q101110XX110000 101010nnnnnddddd 2E30 A800 Vd,Vn (vector) -INST1(uminv, "uminv", 0, 0, IF_DV_2T, 0x2E31A800) +INST1(uminv, "uminv", 0, IF_DV_2T, 0x2E31A800) // uminv Vd,Vn DV_2T 0Q101110XX110001 101010nnnnnddddd 2E31 A800 Vd,Vn (vector) -INST1(fmaxnmv, "fmaxnmv",0, 0, IF_DV_2R, 0x2E30C800) +INST1(fmaxnmv, "fmaxnmv", 0, IF_DV_2R, 0x2E30C800) // fmaxnmv Vd,Vn DV_2R 0Q1011100X110000 110010nnnnnddddd 2E30 C800 Vd,Vn (vector) -INST1(fmaxv, "fmaxv", 0, 0, IF_DV_2R, 0x2E30F800) +INST1(fmaxv, "fmaxv", 0, IF_DV_2R, 0x2E30F800) // fmaxv Vd,Vn DV_2R 0Q1011100X110000 111110nnnnnddddd 2E30 F800 Vd,Vn (vector) -INST1(fminnmv, "fminnmv",0, 0, IF_DV_2R, 0x2EB0C800) +INST1(fminnmv, "fminnmv", 0, IF_DV_2R, 0x2EB0C800) // fminnmv Vd,Vn DV_2R 0Q1011101X110000 110010nnnnnddddd 2EB0 C800 Vd,Vn (vector) -INST1(fminv, "fminv", 0, 0, IF_DV_2R, 0x2EB0F800) +INST1(fminv, "fminv", 0, IF_DV_2R, 0x2EB0F800) // fminv Vd,Vn DV_2R 0Q1011101X110000 111110nnnnnddddd 2EB0 F800 Vd,Vn (vector) -INST1(uzp1, "uzp1", 0, 0, IF_DV_3A, 0x0E001800) +INST1(uzp1, "uzp1", 0, IF_DV_3A, 0x0E001800) // uzp1 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 000110nnnnnddddd 0E00 1800 Vd,Vn,Vm (vector) -INST1(uzp2, "uzp2", 0, 0, IF_DV_3A, 0x0E005800) +INST1(uzp2, "uzp2", 0, IF_DV_3A, 0x0E005800) // upz2 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 010110nnnnnddddd 0E00 5800 Vd,Vn,Vm (vector) -INST1(zip1, "zip1", 0, 0, IF_DV_3A, 0x0E003800) +INST1(zip1, "zip1", 0, IF_DV_3A, 0x0E003800) // zip1 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 011110nnnnnddddd 0E00 3800 Vd,Vn,Vm (vector) -INST1(zip2, "zip2", 0, 0, IF_DV_3A, 0x0E007800) +INST1(zip2, "zip2", 0, IF_DV_3A, 0x0E007800) // zip2 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 001110nnnnnddddd 0E00 7800 Vd,Vn,Vm (vector) -INST1(trn1, "trn1", 0, 0, IF_DV_3A, 0x0E002800) +INST1(trn1, "trn1", 0, IF_DV_3A, 0x0E002800) // trn1 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 001010nnnnnddddd 0E00 2800 Vd,Vn,Vm (vector) -INST1(trn2, "trn2", 0, 0, IF_DV_3A, 0x0E006800) +INST1(trn2, "trn2", 0, IF_DV_3A, 0x0E006800) // trn2 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 011010nnnnnddddd 0E00 6800 Vd,Vn,Vm (vector) -INST1(xtn, "xtn", 0, 0, IF_DV_2M, 0x0E212800) +INST1(xtn, "xtn", 0, IF_DV_2M, 0x0E212800) // xtn Vd,Vn DV_2M 00101110XX110000 001110nnnnnddddd 0E21 2800 Vd,Vn (vector) -INST1(xtn2, "xtn2", 0, 0, IF_DV_2M, 0x4E212800) +INST1(xtn2, "xtn2", 0, IF_DV_2M, 0x4E212800) // xtn2 Vd,Vn DV_2M 01101110XX110000 001110nnnnnddddd 4E21 2800 Vd,Vn (vector) -INST1(fnmul, "fnmul", 0, 0, IF_DV_3D, 0x1E208800) +INST1(fnmul, "fnmul", 0, IF_DV_3D, 0x1E208800) // fnmul Vd,Vn,Vm DV_3D 000111100X1mmmmm 100010nnnnnddddd 1E20 8800 Vd,Vn,Vm (scalar) -INST1(fmadd, "fmadd", 0, 0, IF_DV_4A, 0x1F000000) +INST1(fmadd, "fmadd", 0, IF_DV_4A, 0x1F000000) // fmadd Vd,Va,Vn,Vm DV_4A 000111110X0mmmmm 0aaaaannnnnddddd 1F00 0000 Vd Vn Vm Va (scalar) -INST1(fmsub, "fmsub", 0, 0, IF_DV_4A, 0x1F008000) +INST1(fmsub, "fmsub", 0, IF_DV_4A, 0x1F008000) // fmsub Vd,Va,Vn,Vm DV_4A 000111110X0mmmmm 1aaaaannnnnddddd 1F00 8000 Vd Vn Vm Va (scalar) -INST1(fnmadd, "fnmadd", 0, 0, IF_DV_4A, 0x1F200000) +INST1(fnmadd, "fnmadd", 0, IF_DV_4A, 0x1F200000) // fnmadd Vd,Va,Vn,Vm DV_4A 000111110X1mmmmm 0aaaaannnnnddddd 1F20 0000 Vd Vn Vm Va (scalar) -INST1(fnmsub, "fnmsub", 0, 0, IF_DV_4A, 0x1F208000) +INST1(fnmsub, "fnmsub", 0, IF_DV_4A, 0x1F208000) // fnmsub Vd,Va,Vn,Vm DV_4A 000111110X1mmmmm 1aaaaannnnnddddd 1F20 8000 Vd Vn Vm Va (scalar) -INST1(fcvt, "fcvt", 0, 0, IF_DV_2J, 0x1E224000) +INST1(fcvt, "fcvt", 0, IF_DV_2J, 0x1E224000) // fcvt Vd,Vn DV_2J 00011110SS10001D D10000nnnnnddddd 1E22 4000 Vd,Vn -INST1(pmul, "pmul", 0, 0, IF_DV_3A, 0x2E209C00) +INST1(pmul, "pmul", 0, IF_DV_3A, 0x2E209C00) // pmul Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100111nnnnnddddd 2E20 9C00 Vd,Vn,Vm (vector) -INST1(saba, "saba", 0, 0, IF_DV_3A, 0x0E207C00) +INST1(saba, "saba", 0, IF_DV_3A, 0x0E207C00) // saba Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 011111nnnnnddddd 0E20 7C00 Vd,Vn,Vm (vector) -INST1(sabd, "sabd", 0, 0, IF_DV_3A, 0x0E207400) +INST1(sabd, "sabd", 0, IF_DV_3A, 0x0E207400) // sabd Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 011101nnnnnddddd 0E20 7400 Vd,Vn,Vm (vector) -INST1(smax, "smax", 0, 0, IF_DV_3A, 0x0E206400) +INST1(smax, "smax", 0, IF_DV_3A, 0x0E206400) // smax Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 011001nnnnnddddd 0E20 6400 Vd,Vn,Vm (vector) -INST1(smaxp, "smaxp", 0, 0, IF_DV_3A, 0x0E20A400) +INST1(smaxp, "smaxp", 0, IF_DV_3A, 0x0E20A400) // smaxp Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 101001nnnnnddddd 0E20 A400 Vd,Vn,Vm (vector) -INST1(smin, "smin", 0, 0, IF_DV_3A, 0x0E206C00) +INST1(smin, "smin", 0, IF_DV_3A, 0x0E206C00) // smax Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 011011nnnnnddddd 0E20 6C00 Vd,Vn,Vm (vector) -INST1(sminp, "sminp", 0, 0, IF_DV_3A, 0x0E20AC00) +INST1(sminp, "sminp", 0, IF_DV_3A, 0x0E20AC00) // smax Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 101011nnnnnddddd 0E20 AC00 Vd,Vn,Vm (vector) -INST1(uaba, "uaba", 0, 0, IF_DV_3A, 0x2E207C00) +INST1(uaba, "uaba", 0, IF_DV_3A, 0x2E207C00) // uaba Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011111nnnnnddddd 2E20 7C00 Vd,Vn,Vm (vector) -INST1(uabd, "uabd", 0, 0, IF_DV_3A, 0x2E207400) +INST1(uabd, "uabd", 0, IF_DV_3A, 0x2E207400) // uabd Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011101nnnnnddddd 2E20 7400 Vd,Vn,Vm (vector) -INST1(umax, "umax", 0, 0, IF_DV_3A, 0x2E206400) +INST1(umax, "umax", 0, IF_DV_3A, 0x2E206400) // umax Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011001nnnnnddddd 2E20 6400 Vd,Vn,Vm (vector) -INST1(umaxp, "umaxp", 0, 0, IF_DV_3A, 0x2E20A400) +INST1(umaxp, "umaxp", 0, IF_DV_3A, 0x2E20A400) // umaxp Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 101001nnnnnddddd 2E20 A400 Vd,Vn,Vm (vector) -INST1(umin, "umin", 0, 0, IF_DV_3A, 0x2E206C00) +INST1(umin, "umin", 0, IF_DV_3A, 0x2E206C00) // umin Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011011nnnnnddddd 2E20 6C00 Vd,Vn,Vm (vector) -INST1(uminp, "uminp", 0, 0, IF_DV_3A, 0x2E20AC00) +INST1(uminp, "uminp", 0, IF_DV_3A, 0x2E20AC00) // umin Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 101011nnnnnddddd 2E20 AC00 Vd,Vn,Vm (vector) -INST1(fcvtl, "fcvtl", 0, 0, IF_DV_2G, 0x0E217800) - // fcvtl Vd,Vn DV_2G 000011100X100001 011110nnnnnddddd 0E21 7800 Vd,Vn (scalar) +INST1(fcvtl, "fcvtl", 0, IF_DV_2A, 0x0E217800) + // fcvtl Vd,Vn DV_2A 000011100X100001 011110nnnnnddddd 0E21 7800 Vd,Vn (vector) -INST1(fcvtl2, "fcvtl2", 0, 0, IF_DV_2G, 0x4E217800) - // fcvtl2 Vd,Vn DV_2G 040011100X100001 011110nnnnnddddd 4E21 7800 Vd,Vn (scalar) +INST1(fcvtl2, "fcvtl2", 0, IF_DV_2A, 0x4E217800) + // fcvtl2 Vd,Vn DV_2A 040011100X100001 011110nnnnnddddd 4E21 7800 Vd,Vn (vector) -INST1(fcvtn, "fcvtn", 0, 0, IF_DV_2G, 0x0E216800) - // fcvtn Vd,Vn DV_2G 000011100X100001 011010nnnnnddddd 0E21 6800 Vd,Vn (scalar) +INST1(fcvtn, "fcvtn", 0, IF_DV_2A, 0x0E216800) + // fcvtn Vd,Vn DV_2A 000011100X100001 011010nnnnnddddd 0E21 6800 Vd,Vn (vector) -INST1(fcvtn2, "fcvtn2", 0, 0, IF_DV_2G, 0x4E216800) - // fcvtn2 Vd,Vn DV_2G 040011100X100001 011010nnnnnddddd 4E21 6800 Vd,Vn (scalar) +INST1(fcvtn2, "fcvtn2", 0, IF_DV_2A, 0x4E216800) + // fcvtn2 Vd,Vn DV_2A 040011100X100001 011010nnnnnddddd 4E21 6800 Vd,Vn (vector) -INST1(frecpx, "frecpx", 0, 0, IF_DV_2G, 0x5EA1F800) - // C7.2.139 FRECPX +INST1(frecpx, "frecpx", 0, IF_DV_2G, 0x5EA1F800) // frecpx Vd,Vn DV_2G 010111101X100001 111110nnnnnddddd 5EA1 F800 Vd,Vn (scalar) -INST1(addhn, "addhn", 0, 0, IF_DV_3H, 0x0E204000) - // C7.2.3 ADDHN, ADDHN2 +INST1(addhn, "addhn", 0, IF_DV_3H, 0x0E204000) // addhn Vd,Vn,Vm DV_3H 00001110XX1mmmmm 010000nnnnnddddd 0E20 4000 Vd,Vn,Vm (vector) -INST1(addhn2, "addhn2", 0, 0, IF_DV_3H, 0x4E204000) - // C7.2.3 ADDHN, ADDHN2 +INST1(addhn2, "addhn2", 0, IF_DV_3H, 0x4E204000) // addhn2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 010000nnnnnddddd 4E20 4000 Vd,Vn,Vm (vector) -INST1(pmull, "pmull", 0, 0, IF_DV_3H, 0x0E20E000) - // C7.2.208 PMULL, PMULL2 +INST1(pmull, "pmull", 0, IF_DV_3H, 0x0E20E000) // pmull Vd,Vn,Vm DV_3H 00001110XX1mmmmm 111000nnnnnddddd 0E20 E000 Vd,Vn,Vm (vector) -INST1(pmull2, "pmull2", 0, 0, IF_DV_3H, 0x4E20E000) - // C7.2.208 PMULL, PMULL2 +INST1(pmull2, "pmull2", 0, IF_DV_3H, 0x4E20E000) // pmull2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 111000nnnnnddddd 4E20 E000 Vd,Vn,Vm (vector) -INST1(raddhn, "raddhn", 0, 0, IF_DV_3H, 0x2E204000) - // C7.2.209 RADDHN, RADDHN2 +INST1(raddhn, "raddhn", 0, IF_DV_3H, 0x2E204000) // raddhn Vd,Vn,Vm DV_3H 00101110XX1mmmmm 010000nnnnnddddd 2E20 4000 Vd,Vn,Vm (vector) -INST1(raddhn2, "raddhn2",0, 0, IF_DV_3H, 0x6E204000) - // C7.2.209 RADDHN, RADDHN2 +INST1(raddhn2, "raddhn2", 0, IF_DV_3H, 0x6E204000) // raddhn2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 010000nnnnnddddd 6E20 4000 Vd,Vn,Vm (vector) -INST1(rsubhn, "rsubhn", 0, 0, IF_DV_3H, 0x2E206000) - // C7.2.216 RSUBHN, RSUBHN2 +INST1(rsubhn, "rsubhn", 0, IF_DV_3H, 0x2E206000) // rsubhn Vd,Vn,Vm DV_3H 00101110XX1mmmmm 011000nnnnnddddd 2E20 6000 Vd,Vn,Vm (vector) -INST1(rsubhn2, "rsubhn2",0, 0, IF_DV_3H, 0x6E206000) - // C7.2.216 RSUBHN, RSUBHN2 +INST1(rsubhn2, "rsubhn2", 0, IF_DV_3H, 0x6E206000) // rsubhn2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 011000nnnnnddddd 6E20 6000 Vd,Vn,Vm (vector) -INST1(sabal, "sabal", 0, 0, IF_DV_3H, 0x0E205000) - // C7.2.218 SABAL, SABAL2 +INST1(sabal, "sabal", 0, IF_DV_3H, 0x0E205000) // sabal Vd,Vn,Vm DV_3H 00001110XX1mmmmm 010100nnnnnddddd 0E20 5000 Vd,Vn,Vm (vector) -INST1(sabal2, "sabal2", 0, 0, IF_DV_3H, 0x4E205000) - // C7.2.218 SABAL, SABAL2 +INST1(sabal2, "sabal2", 0, IF_DV_3H, 0x4E205000) // sabal2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 010100nnnnnddddd 4E20 5000 Vd,Vn,Vm (vector) -INST1(sabdl, "sabdl", 0, 0, IF_DV_3H, 0x0E207000) - // C7.2.220 SABDL, SABDL2 +INST1(sabdl, "sabdl", 0, IF_DV_3H, 0x0E207000) // sabdl Vd,Vn,Vm DV_3H 00001110XX1mmmmm 011100nnnnnddddd 0E20 7000 Vd,Vn,Vm (vector) -INST1(sabdl2, "sabdl2", 0, 0, IF_DV_3H, 0x4E207000) - // C7.2.220 SABDL, SABDL2 +INST1(sabdl2, "sabdl2", 0, IF_DV_3H, 0x4E207000) // sabdl2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 011100nnnnnddddd 4E20 7000 Vd,Vn,Vm (vector) -INST1(sadalp, "sadalp", 0, 0, IF_DV_2T, 0x0E206800) - // C7.2.221 SADALP +INST1(sadalp, "sadalp", 0, IF_DV_2T, 0x0E206800) // sadalp Vd,Vn DV_2T 0Q001110XX100000 011010nnnnnddddd 0E20 6800 Vd,Vn (vector) -INST1(saddl, "saddl", 0, 0, IF_DV_3H, 0x0E200000) - // C7.2.222 SADDL, SADDL2 +INST1(saddl, "saddl", 0, IF_DV_3H, 0x0E200000) // saddl Vd,Vn,Vm DV_3H 00001110XX1mmmmm 000000nnnnnddddd 0E20 0000 Vd,Vn,Vm (vector) -INST1(saddl2, "saddl2", 0, 0, IF_DV_3H, 0x4E200000) - // C7.2.222 SADDL, SADDL2 +INST1(saddl2, "saddl2", 0, IF_DV_3H, 0x4E200000) // saddl2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 000000nnnnnddddd 4E20 0000 Vd,Vn,Vm (vector) -INST1(saddlp, "saddlp", 0, 0, IF_DV_2T, 0x0E202800) - // C7.2.223 SADDLP +INST1(saddlp, "saddlp", 0, IF_DV_2T, 0x0E202800) // saddlp Vd,Vn DV_2T 0Q001110XX100000 001010nnnnnddddd 0E20 2800 Vd,Vn (vector) -INST1(saddw, "saddw", 0, 0, IF_DV_3H, 0x0E201000) - // C7.2.225 SADDW, SADDW2 +INST1(saddw, "saddw", 0, IF_DV_3H, 0x0E201000) // saddw Vd,Vn,Vm DV_3H 00001110XX1mmmmm 000100nnnnnddddd 0E20 1000 Vd,Vn,Vm (vector) -INST1(saddw2, "saddw2", 0, 0, IF_DV_3H, 0x4E201000) - // C7.2.225 SADDW, SADDW2 +INST1(saddw2, "saddw2", 0, IF_DV_3H, 0x4E201000) // saddw2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 000100nnnnnddddd 4E20 1000 Vd,Vn,Vm (vector) -INST1(shadd, "shadd", 0, 0, IF_DV_3A, 0x0E200400) - // C7.2.246 SHADD +INST1(shadd, "shadd", 0, IF_DV_3A, 0x0E200400) // shadd Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 000001nnnnnddddd 0E20 0400 Vd,Vn,Vm (vector) -INST1(shsub, "shsub", 0, 0, IF_DV_3A, 0x0E202400) - // C7.2.250 SHSUB +INST1(shsub, "shsub", 0, IF_DV_3A, 0x0E202400) // shsub Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 001001nnnnnddddd 0E20 2400 Vd,Vn,Vm (vector) -INST1(srhadd, "srhadd", 0, 0, IF_DV_3A, 0x0E201400) - // C7.2.302 SRHADD +INST1(srhadd, "srhadd", 0, IF_DV_3A, 0x0E201400) // srhadd Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 000101nnnnnddddd 0E20 1400 Vd,Vn,Vm (vector) -INST1(ssubl, "ssubl", 0, 0, IF_DV_3H, 0x0E202000) - // C7.2.311 SSUBL, SSUBL2 +INST1(ssubl, "ssubl", 0, IF_DV_3H, 0x0E202000) // ssubl Vd,Vn,Vm DV_3H 00001110XX1mmmmm 001000nnnnnddddd 0E20 2000 Vd,Vn,Vm (vector) -INST1(ssubl2, "ssubl2", 0, 0, IF_DV_3H, 0x4E202000) - // C7.2.311 SSUBL, SSUBL2 +INST1(ssubl2, "ssubl2", 0, IF_DV_3H, 0x4E202000) // ssubl2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 001000nnnnnddddd 4E20 2000 Vd,Vn,Vm (vector) -INST1(ssubw, "ssubw", 0, 0, IF_DV_3H, 0x0E203000) - // C7.2.312 SSUBW, SSUBW2 +INST1(ssubw, "ssubw", 0, IF_DV_3H, 0x0E203000) // ssubw Vd,Vn,Vm DV_3H 00001110XX1mmmmm 001100nnnnnddddd 0E20 3000 Vd,Vn,Vm (vector) -INST1(ssubw2, "ssubw2", 0, 0, IF_DV_3H, 0x4E203000) - // C7.2.312 SSUBW, SSUBW2 +INST1(ssubw2, "ssubw2", 0, IF_DV_3H, 0x4E203000) // ssubw2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 001100nnnnnddddd 4E20 3000 Vd,Vn,Vm (vector) -INST1(subhn, "subhn", 0, 0, IF_DV_3H, 0x0E206000) - // C7.2.327 SUBHN, SUBHN2 +INST1(subhn, "subhn", 0, IF_DV_3H, 0x0E206000) // subhn Vd,Vn,Vm DV_3H 00001110XX1mmmmm 011000nnnnnddddd 0E20 6000 Vd,Vn,Vm (vector) -INST1(subhn2, "subhn2",0, 0, IF_DV_3H, 0x4E206000) - // C7.2.327 SUBHN, SUBHN2 +INST1(subhn2, "subhn2", 0, IF_DV_3H, 0x4E206000) // subhn2 Vd,Vn,Vm DV_3H 01001110XX1mmmmm 011000nnnnnddddd 4E20 6000 Vd,Vn,Vm (vector) -INST1(uabal, "uabal", 0, 0, IF_DV_3H, 0x2E205000) - // C7.2.335 UABAL, UABAL2 +INST1(uabal, "uabal", 0, IF_DV_3H, 0x2E205000) // uabal Vd,Vn,Vm DV_3H 00101110XX1mmmmm 010100nnnnnddddd 2E20 5000 Vd,Vn,Vm (vector) -INST1(uabal2, "uabal2", 0, 0, IF_DV_3H, 0x6E205000) - // C7.2.335 UABAL, UABAL2 +INST1(uabal2, "uabal2", 0, IF_DV_3H, 0x6E205000) // uabal2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 010100nnnnnddddd 6E20 5000 Vd,Vn,Vm (vector) -INST1(uabdl, "uabdl", 0, 0, IF_DV_3H, 0x2E207000) - // C7.2.337 UABDL, UABDL2 +INST1(uabdl, "uabdl", 0, IF_DV_3H, 0x2E207000) // uabdl Vd,Vn,Vm DV_3H 00101110XX1mmmmm 011100nnnnnddddd 2E20 7000 Vd,Vn,Vm (vector) -INST1(uabdl2, "uabdl2", 0, 0, IF_DV_3H, 0x6E207000) - // C7.2.337 UABDL, UABDL2 +INST1(uabdl2, "uabdl2", 0, IF_DV_3H, 0x6E207000) // uabdl2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 011100nnnnnddddd 6E20 7000 Vd,Vn,Vm (vector) -INST1(uadalp, "uadalp", 0, 0, IF_DV_2T, 0x2E206800) - // C7.2.338 UADALP +INST1(uadalp, "uadalp", 0, IF_DV_2T, 0x2E206800) // uadalp Vd,Vn DV_2T 0Q101110XX100000 011010nnnnnddddd 2E20 6800 Vd,Vn (vector) -INST1(uaddl, "uaddl", 0, 0, IF_DV_3H, 0x2E200000) - // C7.2.339 UADDL, UADDL2 +INST1(uaddl, "uaddl", 0, IF_DV_3H, 0x2E200000) // uaddl Vd,Vn,Vm DV_3H 00101110XX1mmmmm 000000nnnnnddddd 2E20 0000 Vd,Vn,Vm (vector) -INST1(uaddl2, "uaddl2", 0, 0, IF_DV_3H, 0x6E200000) - // C7.2.339 UADDL, UADDL2 +INST1(uaddl2, "uaddl2", 0, IF_DV_3H, 0x6E200000) // uaddl2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 000000nnnnnddddd 6E20 0000 Vd,Vn,Vm (vector) -INST1(uaddlp, "uaddlp", 0, 0, IF_DV_2T, 0x2E202800) - // C7.2.340 UADDLP +INST1(uaddlp, "uaddlp", 0, IF_DV_2T, 0x2E202800) // uaddlp Vd,Vn DV_2T 0Q101110XX100000 001010nnnnnddddd 2E20 2800 Vd,Vn (vector) -INST1(uaddw, "uaddw", 0, 0, IF_DV_3H, 0x2E201000) - // C7.2.342 UADDW, UADDW2 +INST1(uaddw, "uaddw", 0, IF_DV_3H, 0x2E201000) // uaddw Vd,Vn,Vm DV_3H 00101110XX1mmmmm 000100nnnnnddddd 2E20 1000 Vd,Vn,Vm (vector) -INST1(uaddw2, "uaddw2", 0, 0, IF_DV_3H, 0x6E201000) - // C7.2.342 UADDW, UADDW2 +INST1(uaddw2, "uaddw2", 0, IF_DV_3H, 0x6E201000) // uaddw2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 000100nnnnnddddd 6E20 1000 Vd,Vn,Vm (vector) -INST1(uhadd, "uhadd", 0, 0, IF_DV_3A, 0x2E200400) - // C7.2.349 UHADD +INST1(uhadd, "uhadd", 0, IF_DV_3A, 0x2E200400) // uhadd Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 000001nnnnnddddd 2E20 0400 Vd,Vn,Vm (vector) -INST1(uhsub, "uhsub", 0, 0, IF_DV_3A, 0x2E202400) - // C7.2.350 UHSUB +INST1(uhsub, "uhsub", 0, IF_DV_3A, 0x2E202400) // uhsub Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 001001nnnnnddddd 2E20 2400 Vd,Vn,Vm (vector) -INST1(urhadd, "urhadd", 0, 0, IF_DV_3A, 0x2E201400) - // C7.2.373 URHADD +INST1(urhadd, "urhadd", 0, IF_DV_3A, 0x2E201400) // urhadd Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 000101nnnnnddddd 2E20 1400 Vd,Vn,Vm (vector) -INST1(usubl, "usubl", 0, 0, IF_DV_3H, 0x2E202000) - // C7.2.383 USUBL, USUBL2 +INST1(usubl, "usubl", 0, IF_DV_3H, 0x2E202000) // usubl Vd,Vn,Vm DV_3H 00101110XX1mmmmm 001000nnnnnddddd 2E20 2000 Vd,Vn,Vm (vector) -INST1(usubl2, "usubl2", 0, 0, IF_DV_3H, 0x6E202000) - // C7.2.383 USUBL, USUBL2 +INST1(usubl2, "usubl2", 0, IF_DV_3H, 0x6E202000) // usubl2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 001000nnnnnddddd 6E20 2000 Vd,Vn,Vm (vector) -INST1(usubw, "usubw", 0, 0, IF_DV_3H, 0x2E203000) - // C7.2.384 USUBW, USUBW2 +INST1(usubw, "usubw", 0, IF_DV_3H, 0x2E203000) // usubw Vd,Vn,Vm DV_3H 00101110XX1mmmmm 001100nnnnnddddd 2E20 3000 Vd,Vn,Vm (vector) -INST1(usubw2, "usubw2", 0, 0, IF_DV_3H, 0x6E203000) - // C7.2.384 USUBW, USUBW2 +INST1(usubw2, "usubw2", 0, IF_DV_3H, 0x6E203000) // usubw2 Vd,Vn,Vm DV_3H 01101110XX1mmmmm 001100nnnnnddddd 6E20 3000 Vd,Vn,Vm (vector) -INST1(shll, "shll", 0, 0, IF_DV_2M, 0x2F00A400) +INST1(shll, "shll", 0, IF_DV_2M, 0x2F00A400) // shll Vd,Vn,imm DV_2M 0Q101110XX100001 001110nnnnnddddd 2E21 3800 Vd,Vn, {8/16/32} -INST1(shll2, "shll2", 0, 0, IF_DV_2M, 0x6F00A400) +INST1(shll2, "shll2", 0, IF_DV_2M, 0x6F00A400) // shll Vd,Vn,imm DV_2M 0Q101110XX100001 001110nnnnnddddd 2E21 3800 Vd,Vn, {8/16/32} -INST1(sshll, "sshll", 0, 0, IF_DV_2O, 0x0F00A400) - // sshll Vd,Vn,imm DV_2O 000011110iiiiiii 101001nnnnnddddd 0F00 A400 Vd,Vn imm (shift - vector) +INST1(sshll, "sshll", 0, IF_DV_2O, 0x0F00A400) + // sshll Vd,Vn,imm DV_2O 000011110iiiiiii 101001nnnnnddddd 0F00 A400 Vd,Vn imm (left shift - vector) + +INST1(sshll2, "sshll2", 0, IF_DV_2O, 0x4F00A400) + // sshll2 Vd,Vn,imm DV_2O 010011110iiiiiii 101001nnnnnddddd 4F00 A400 Vd,Vn imm (left shift - vector) + +INST1(ushll, "ushll", 0, IF_DV_2O, 0x2F00A400) + // ushll Vd,Vn,imm DV_2O 001011110iiiiiii 101001nnnnnddddd 2F00 A400 Vd,Vn imm (left shift - vector) + +INST1(ushll2, "ushll2", 0, IF_DV_2O, 0x6F00A400) + // ushll2 Vd,Vn,imm DV_2O 011011110iiiiiii 101001nnnnnddddd 6F00 A400 Vd,Vn imm (left shift - vector) + +INST1(shrn, "shrn", RSH, IF_DV_2O, 0x0F008400) + // shrn Vd,Vn,imm DV_2O 000011110iiiiiii 100001nnnnnddddd 0F00 8400 Vd,Vn imm (right shift - vector) + +INST1(shrn2, "shrn2", RSH, IF_DV_2O, 0x4F008400) + // shrn2 Vd,Vn,imm DV_2O 010011110iiiiiii 100001nnnnnddddd 4F00 8400 Vd,Vn imm (right shift - vector) + +INST1(rshrn, "rshrn", RSH, IF_DV_2O, 0x0F008C00) + // rshrn Vd,Vn,imm DV_2O 000011110iiiiiii 100011nnnnnddddd 0F00 8C00 Vd,Vn imm (right shift - vector) -INST1(sshll2, "sshll2", 0, 0, IF_DV_2O, 0x4F00A400) - // sshll2 Vd,Vn,imm DV_2O 010011110iiiiiii 101001nnnnnddddd 4F00 A400 Vd,Vn imm (shift - vector) +INST1(rshrn2, "rshrn2", RSH, IF_DV_2O, 0x4F008C00) + // rshrn2 Vd,Vn,imm DV_2O 010011110iiiiiii 100011nnnnnddddd 4F00 8C00 Vd,Vn imm (right shift - vector) -INST1(ushll, "ushll", 0, 0, IF_DV_2O, 0x2F00A400) - // ushll Vd,Vn,imm DV_2O 001011110iiiiiii 101001nnnnnddddd 2F00 A400 Vd,Vn imm (shift - vector) +INST1(sqrshrn2, "sqrshrn2", RSH, IF_DV_2O, 0x0F009C00) + // sqrshrn2 Vd,Vn,imm DV_2O 0Q0011110iiiiiii 100111nnnnnddddd 0F00 9C00 Vd Vn imm (right shift - vector) -INST1(ushll2, "ushll2", 0, 0, IF_DV_2O, 0x6F00A400) - // ushll2 Vd,Vn,imm DV_2O 011011110iiiiiii 101001nnnnnddddd 6F00 A400 Vd,Vn imm (shift - vector) +INST1(sqrshrun2, "sqrshrun2", RSH, IF_DV_2O, 0x2F008C00) + // sqrshrun2 Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100011nnnnnddddd 2F00 8C00 Vd Vn imm (right shift - vector) -INST1(shrn, "shrn", 0, 0, IF_DV_2O, 0x0F008400) - // shrn Vd,Vn,imm DV_2O 000011110iiiiiii 100001nnnnnddddd 0F00 8400 Vd,Vn imm (shift - vector) +INST1(sqshrn2, "sqshrn2", RSH, IF_DV_2O, 0x0F009400) + // sqshrn2 Vd,Vn,imm DV_2O 0Q0011110iiiiiii 100101nnnnnddddd 0F00 9400 Vd Vn imm (right shift - vector) -INST1(shrn2, "shrn2", 0, 0, IF_DV_2O, 0x4F008400) - // shrn2 Vd,Vn,imm DV_2O 010011110iiiiiii 100001nnnnnddddd 4F00 8400 Vd,Vn imm (shift - vector) +INST1(sqshrun2, "sqshrun2", RSH, IF_DV_2O, 0x2F008400) + // sqshrun2 Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100001nnnnnddddd 2F00 8400 Vd Vn imm (right shift - vector) -INST1(rshrn, "rshrn", 0, 0, IF_DV_2O, 0x0F008C00) - // rshrn Vd,Vn,imm DV_2O 000011110iiiiiii 100011nnnnnddddd 0F00 8C00 Vd,Vn imm (shift - vector) +INST1(uqrshrn2, "uqrshrn2", RSH, IF_DV_2O, 0x2F009C00) + // uqrshrn2 Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100111nnnnnddddd 2F00 9C00 Vd Vn imm (right shift - vector) -INST1(rshrn2, "rshrn2", 0, 0, IF_DV_2O, 0x4F008C00) - // rshrn2 Vd,Vn,imm DV_2O 010011110iiiiiii 100011nnnnnddddd 4F00 8C00 Vd,Vn imm (shift - vector) +INST1(uqshrn2, "uqshrn2", RSH, IF_DV_2O, 0x2F009400) + // uqshrn2 Vd,Vn,imm DV_2O 0Q1011110iiiiiii 100101nnnnnddddd 2F00 9400 Vd Vn imm (right shift - vector) -INST1(sxtl, "sxtl", 0, 0, IF_DV_2O, 0x0F00A400) - // sxtl Vd,Vn DV_2O 000011110iiiiiii 101001nnnnnddddd 0F00 A400 Vd,Vn (shift - vector) +INST1(sxtl, "sxtl", 0, IF_DV_2O, 0x0F00A400) + // sxtl Vd,Vn DV_2O 000011110iiiiiii 101001nnnnnddddd 0F00 A400 Vd,Vn (left shift - vector) -INST1(sxtl2, "sxtl2", 0, 0, IF_DV_2O, 0x4F00A400) - // sxtl2 Vd,Vn DV_2O 010011110iiiiiii 101001nnnnnddddd 4F00 A400 Vd,Vn (shift - vector) +INST1(sxtl2, "sxtl2", 0, IF_DV_2O, 0x4F00A400) + // sxtl2 Vd,Vn DV_2O 010011110iiiiiii 101001nnnnnddddd 4F00 A400 Vd,Vn (left shift - vector) -INST1(uxtl, "uxtl", 0, 0, IF_DV_2O, 0x2F00A400) - // uxtl Vd,Vn DV_2O 001011110iiiiiii 101001nnnnnddddd 2F00 A400 Vd,Vn (shift - vector) +INST1(uxtl, "uxtl", 0, IF_DV_2O, 0x2F00A400) + // uxtl Vd,Vn DV_2O 001011110iiiiiii 101001nnnnnddddd 2F00 A400 Vd,Vn (left shift - vector) -INST1(uxtl2, "uxtl2", 0, 0, IF_DV_2O, 0x6F00A400) - // uxtl2 Vd,Vn DV_2O 011011110iiiiiii 101001nnnnnddddd 6F00 A400 Vd,Vn (shift - vector) +INST1(uxtl2, "uxtl2", 0, IF_DV_2O, 0x6F00A400) + // uxtl2 Vd,Vn DV_2O 011011110iiiiiii 101001nnnnnddddd 6F00 A400 Vd,Vn (left shift - vector) -INST1(tbl, "tbl", 0, 0, IF_DV_3C, 0x0E000000) +INST1(tbl, "tbl", 0, IF_DV_3C, 0x0E000000) // tbl Vd,{Vn},Vm DV_3C 0Q001110000mmmmm 000000nnnnnddddd 0E00 0000 Vd,Vn,Vm (vector) -INST1(tbl_2regs, "tbl", 0, 0, IF_DV_3C, 0x0E002000) +INST1(tbl_2regs, "tbl", 0, IF_DV_3C, 0x0E002000) // tbl Vd,{Vn,Vn+1},Vm DV_3C 0Q001110000mmmmm 001000nnnnnddddd 0E00 2000 Vd,Vn,Vm (vector) -INST1(tbl_3regs, "tbl", 0, 0, IF_DV_3C, 0x0E004000) +INST1(tbl_3regs, "tbl", 0, IF_DV_3C, 0x0E004000) // tbl Vd,{Vn,Vn+1,Vn+2},Vm DV_3C 0Q001110000mmmmm 010000nnnnnddddd 0E00 4000 Vd,Vn,Vm (vector) -INST1(tbl_4regs, "tbl", 0, 0, IF_DV_3C, 0x0E006000) +INST1(tbl_4regs, "tbl", 0, IF_DV_3C, 0x0E006000) // tbl Vd,{Vn,Vn+1,Vn+2,Vn+3},Vm DV_3C 0Q001110000mmmmm 011000nnnnnddddd 0E00 6000 Vd,Vn,Vm (vector) -INST1(tbx, "tbx", 0, 0, IF_DV_3C, 0x0E001000) +INST1(tbx, "tbx", 0, IF_DV_3C, 0x0E001000) // tbx Vd,{Vn},Vm DV_3C 0Q001110000mmmmm 000100nnnnnddddd 0E00 1000 Vd,Vn,Vm (vector) -INST1(tbx_2regs, "tbx", 0, 0, IF_DV_3C, 0x0E003000) +INST1(tbx_2regs, "tbx", 0, IF_DV_3C, 0x0E003000) // tbx Vd,{Vn,Vn+1},Vm DV_3C 0Q001110000mmmmm 001100nnnnnddddd 0E00 3000 Vd,Vn,Vm (vector) -INST1(tbx_3regs, "tbx", 0, 0, IF_DV_3C, 0x0E005000) +INST1(tbx_3regs, "tbx", 0, IF_DV_3C, 0x0E005000) // tbx Vd,{Vn,Vn+1,Vn+2},Vm DV_3C 0Q001110000mmmmm 010100nnnnnddddd 0E00 5000 Vd,Vn,Vm (vector) -INST1(tbx_4regs, "tbx", 0, 0, IF_DV_3C, 0x0E007000) +INST1(tbx_4regs, "tbx", 0, IF_DV_3C, 0x0E007000) // tbx Vd,{Vn,Vn+1,Vn+2,Vn+3},Vm DV_3C 0Q001110000mmmmm 011100nnnnnddddd 0E00 7000 Vd,Vn,Vm (vector) // clang-format on diff --git a/src/coreclr/src/jit/jitconfigvalues.h b/src/coreclr/src/jit/jitconfigvalues.h index cb86931dfaa7a..d531362543ebe 100644 --- a/src/coreclr/src/jit/jitconfigvalues.h +++ b/src/coreclr/src/jit/jitconfigvalues.h @@ -437,13 +437,13 @@ CONFIG_INTEGER(JitSaveFpLrWithCalleeSavedRegisters, W("JitSaveFpLrWithCalleeSave #endif // defined(TARGET_ARM64) #endif // DEBUG -#if !FEATURE_MULTIREG_RET +#if defined(TARGET_ARMARCH) CONFIG_INTEGER(JitDoOldStructRetyping, W("JitDoOldStructRetyping"), 1) // Allow Jit to retype structs as primitive types // when possible. -#else // FEATURE_MULTIREG_RET +#else CONFIG_INTEGER(JitDoOldStructRetyping, W("JitDoOldStructRetyping"), 1) // Allow Jit to retype structs as primitive types // when possible. -#endif // FEATURE_MULTIREG_RET +#endif #undef CONFIG_INTEGER #undef CONFIG_STRING diff --git a/src/coreclr/src/jit/lclvars.cpp b/src/coreclr/src/jit/lclvars.cpp index ab3280b9c296b..608b4410cd942 100644 --- a/src/coreclr/src/jit/lclvars.cpp +++ b/src/coreclr/src/jit/lclvars.cpp @@ -1971,10 +1971,12 @@ bool Compiler::StructPromotionHelper::ShouldPromoteStructVar(unsigned lclNum) // void Compiler::StructPromotionHelper::SortStructFields() { - assert(!structPromotionInfo.fieldsSorted); - qsort(structPromotionInfo.fields, structPromotionInfo.fieldCnt, sizeof(*structPromotionInfo.fields), - lvaFieldOffsetCmp); - structPromotionInfo.fieldsSorted = true; + if (!structPromotionInfo.fieldsSorted) + { + qsort(structPromotionInfo.fields, structPromotionInfo.fieldCnt, sizeof(*structPromotionInfo.fields), + lvaFieldOffsetCmp); + structPromotionInfo.fieldsSorted = true; + } } //-------------------------------------------------------------------------------------------- @@ -2158,10 +2160,7 @@ void Compiler::StructPromotionHelper::PromoteStructVar(unsigned lclNum) } #endif - if (!structPromotionInfo.fieldsSorted) - { - SortStructFields(); - } + SortStructFields(); for (unsigned index = 0; index < structPromotionInfo.fieldCnt; ++index) { diff --git a/src/coreclr/src/jit/lower.cpp b/src/coreclr/src/jit/lower.cpp index 16a0ee738e45e..2c093a67d048b 100644 --- a/src/coreclr/src/jit/lower.cpp +++ b/src/coreclr/src/jit/lower.cpp @@ -37,7 +37,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Notes: // If 'childNode' it has any existing sources, they will now be sources for the parent. // -void Lowering::MakeSrcContained(GenTree* parentNode, GenTree* childNode) +void Lowering::MakeSrcContained(GenTree* parentNode, GenTree* childNode) const { assert(!parentNode->OperIsLeaf()); assert(childNode->canBeContained()); @@ -255,6 +255,13 @@ GenTree* Lowering::LowerNode(GenTree* node) case GT_STORE_BLK: case GT_STORE_OBJ: + if (node->AsBlk()->Data()->IsCall()) + { + assert(!comp->compDoOldStructRetyping()); + LowerStoreCallStruct(node->AsBlk()); + break; + } + __fallthrough; case GT_STORE_DYN_BLK: LowerBlockStore(node->AsBlk()); break; @@ -297,64 +304,8 @@ GenTree* Lowering::LowerNode(GenTree* node) __fallthrough; case GT_STORE_LCL_FLD: - { - GenTreeLclVarCommon* const store = node->AsLclVarCommon(); - GenTree* src = store->gtGetOp1(); - if ((varTypeUsesFloatReg(store) != varTypeUsesFloatReg(src)) && !store->IsPhiDefn() && - (src->TypeGet() != TYP_STRUCT)) - { - if (m_lsra->isRegCandidate(comp->lvaGetDesc(store->GetLclNum()))) - { - GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, store->TypeGet(), src, nullptr); - store->gtOp1 = bitcast; - src = store->gtGetOp1(); - BlockRange().InsertBefore(store, bitcast); - ContainCheckBitCast(bitcast); - } - else - { - // This is an actual store, we'll just retype it. - store->gtType = src->TypeGet(); - } - } - - if ((node->TypeGet() == TYP_STRUCT) && (src->OperGet() != GT_PHI)) - { - LclVarDsc* varDsc = comp->lvaGetDesc(store); -#if FEATURE_MULTIREG_RET - if (src->OperGet() == GT_CALL) - { - assert(src->AsCall()->HasMultiRegRetVal()); - } - else -#endif // FEATURE_MULTIREG_RET - if (!src->OperIs(GT_LCL_VAR, GT_CALL) || varDsc->GetLayout()->GetRegisterType() == TYP_UNDEF) - { - GenTreeLclVar* addr = comp->gtNewLclVarAddrNode(store->GetLclNum(), TYP_BYREF); - - addr->gtFlags |= GTF_VAR_DEF; - assert(!addr->IsPartialLclFld(comp)); - addr->gtFlags |= GTF_DONT_CSE; - - // Create the assignment node. - store->ChangeOper(GT_STORE_OBJ); - - store->gtFlags = GTF_ASG | GTF_IND_NONFAULTING | GTF_IND_TGT_NOT_HEAP; -#ifndef JIT32_GCENCODER - store->AsObj()->gtBlkOpGcUnsafe = false; -#endif - store->AsObj()->gtBlkOpKind = GenTreeObj::BlkOpKindInvalid; - store->AsObj()->SetLayout(varDsc->GetLayout()); - store->AsObj()->SetAddr(addr); - store->AsObj()->SetData(src); - BlockRange().InsertBefore(store, addr); - LowerBlockStore(store->AsObj()); - break; - } - } - LowerStoreLoc(node->AsLclVarCommon()); + LowerStoreLocCommon(node->AsLclVarCommon()); break; - } #if defined(TARGET_ARM64) case GT_CMPXCHG: @@ -1689,13 +1640,10 @@ void Lowering::LowerCall(GenTree* node) LowerFastTailCall(call); } -#if !FEATURE_MULTIREG_RET if (varTypeIsStruct(call)) { - assert(!comp->compDoOldStructRetyping()); LowerCallStruct(call); } -#endif // !FEATURE_MULTIREG_RET ContainCheckCallOperands(call); JITDUMP("lowering call (after):\n"); @@ -2993,7 +2941,6 @@ void Lowering::LowerRet(GenTreeUnOp* ret) BlockRange().InsertBefore(ret, bitcast); ContainCheckBitCast(bitcast); } -#if !FEATURE_MULTIREG_RET else { #ifdef DEBUG @@ -3002,19 +2949,38 @@ void Lowering::LowerRet(GenTreeUnOp* ret) GenTree* retVal = ret->gtGetOp1(); if (varTypeIsStruct(ret->TypeGet()) != varTypeIsStruct(retVal->TypeGet())) { - // This could happen if we have retyped op1 as a primitive type during struct promotion, - // check `retypedFieldsMap` for details. - assert(genActualType(comp->info.compRetNativeType) == genActualType(retVal->TypeGet())); + if (varTypeIsStruct(ret->TypeGet())) + { + assert(!comp->compDoOldStructRetyping()); + bool actualTypesMatch = false; + if (genActualType(comp->info.compRetNativeType) == genActualType(retVal->TypeGet())) + { + // This could happen if we have retyped op1 as a primitive type during struct promotion, + // check `retypedFieldsMap` for details. + actualTypesMatch = true; + } + bool constStructInit = retVal->IsConstInitVal(); + assert(actualTypesMatch || constStructInit); + } + else + { +#ifdef FEATURE_SIMD + assert(comp->compDoOldStructRetyping()); + assert(ret->TypeIs(TYP_DOUBLE)); + assert(retVal->TypeIs(TYP_SIMD8)); +#else // !FEATURE_SIMD + unreached(); +#endif // !FEATURE_SIMD + } } } -#endif - if (varTypeIsStruct(ret)) +#endif // DEBUG + if (varTypeIsStruct(ret) && !comp->compMethodReturnsMultiRegRetType()) { assert(!comp->compDoOldStructRetyping()); LowerRetStruct(ret); } } -#endif // !FEATURE_MULTIREG_RET // Method doing PInvokes has exactly one return block unless it has tail calls. if (comp->compMethodRequiresPInvokeFrame() && (comp->compCurBB == comp->genReturnBB)) @@ -3024,7 +2990,111 @@ void Lowering::LowerRet(GenTreeUnOp* ret) ContainCheckRet(ret); } -#if !FEATURE_MULTIREG_RET +//---------------------------------------------------------------------------------------------- +// LowerStoreLocCommon: platform idependent part of local var or field store lowering. +// +// Arguments: +// lclStore - The store lcl node to lower. +// +void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) +{ + assert(lclStore->OperIs(GT_STORE_LCL_FLD, GT_STORE_LCL_VAR)); + GenTree* src = lclStore->gtGetOp1(); + LclVarDsc* varDsc = comp->lvaGetDesc(lclStore); + if ((varTypeUsesFloatReg(lclStore) != varTypeUsesFloatReg(src)) && !lclStore->IsPhiDefn() && + (src->TypeGet() != TYP_STRUCT)) + { + if (m_lsra->isRegCandidate(varDsc)) + { + GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, lclStore->TypeGet(), src, nullptr); + lclStore->gtOp1 = bitcast; + src = lclStore->gtGetOp1(); + BlockRange().InsertBefore(lclStore, bitcast); + ContainCheckBitCast(bitcast); + } + else + { + // This is an actual store, we'll just retype it. + lclStore->gtType = src->TypeGet(); + } + } + + if ((lclStore->TypeGet() == TYP_STRUCT) && (src->OperGet() != GT_PHI)) + { + if (src->OperGet() == GT_CALL) + { + GenTreeCall* call = src->AsCall(); + const ClassLayout* layout = varDsc->GetLayout(); + const var_types regType = layout->GetRegisterType(); + +#ifdef DEBUG + const unsigned slotCount = layout->GetSlotCount(); +#if defined(TARGET_XARCH) && !defined(UNIX_AMD64_ABI) + // Windows x64 doesn't have multireg returns, + // x86 uses it only for long return type, not for structs. + assert(!comp->compDoOldStructRetyping()); + assert(slotCount == 1); + assert(regType != TYP_UNDEF); +#else // !TARGET_XARCH || UNIX_AMD64_ABI + if (!varDsc->lvIsHfa()) + { + if (slotCount > 1) + { + assert(call->HasMultiRegRetVal()); + } + else + { + assert(!comp->compDoOldStructRetyping()); + unsigned size = layout->GetSize(); + assert((size <= 8) || (size == 16)); + bool isPowerOf2 = (((size - 1) & size) == 0); + bool isTypeDefined = (regType != TYP_UNDEF); + assert(isPowerOf2 == isTypeDefined); + } + } +#endif // !TARGET_XARCH || UNIX_AMD64_ABI +#endif // DEBUG + +#if !defined(WINDOWS_AMD64_ABI) + if (!call->HasMultiRegRetVal() && (regType == TYP_UNDEF)) + { + // If we have a single return register, + // but we can't retype it as a primitive type, we must spill it. + GenTreeLclVar* spilledCall = SpillStructCallResult(call); + lclStore->gtOp1 = spilledCall; + src = lclStore->gtOp1; + LowerStoreLocCommon(lclStore); + return; + } +#endif // !WINDOWS_AMD64_ABI + } + else if (!src->OperIs(GT_LCL_VAR) || varDsc->GetLayout()->GetRegisterType() == TYP_UNDEF) + { + GenTreeLclVar* addr = comp->gtNewLclVarAddrNode(lclStore->GetLclNum(), TYP_BYREF); + + addr->gtFlags |= GTF_VAR_DEF; + assert(!addr->IsPartialLclFld(comp)); + addr->gtFlags |= GTF_DONT_CSE; + + // Create the assignment node. + lclStore->ChangeOper(GT_STORE_OBJ); + GenTreeBlk* objStore = lclStore->AsObj(); + objStore->gtFlags = GTF_ASG | GTF_IND_NONFAULTING | GTF_IND_TGT_NOT_HEAP; +#ifndef JIT32_GCENCODER + objStore->gtBlkOpGcUnsafe = false; +#endif + objStore->gtBlkOpKind = GenTreeObj::BlkOpKindInvalid; + objStore->SetLayout(varDsc->GetLayout()); + objStore->SetAddr(addr); + objStore->SetData(src); + BlockRange().InsertBefore(objStore, addr); + LowerBlockStore(objStore); + return; + } + } + LowerStoreLoc(lclStore); +} + //---------------------------------------------------------------------------------------------- // LowerRetStructLclVar: Lowers a struct return node. // @@ -3033,6 +3103,7 @@ void Lowering::LowerRet(GenTreeUnOp* ret) // void Lowering::LowerRetStruct(GenTreeUnOp* ret) { + assert(!comp->compMethodReturnsMultiRegRetType()); assert(!comp->compDoOldStructRetyping()); assert(ret->OperIs(GT_RETURN)); assert(varTypeIsStruct(ret)); @@ -3050,6 +3121,13 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret) case GT_CNS_INT: assert(retVal->TypeIs(TYP_INT)); + assert(retVal->AsIntCon()->IconValue() == 0); + if (varTypeUsesFloatReg(nativeReturnType)) + { + retVal->ChangeOperConst(GT_CNS_DBL); + retVal->ChangeType(TYP_FLOAT); + retVal->AsDblCon()->gtDconVal = 0; + } break; case GT_OBJ: @@ -3063,15 +3141,38 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret) LowerRetStructLclVar(ret); break; +#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_SIMD case GT_SIMD: +#endif // FEATURE_SIMD +#ifdef FEATURE_HW_INTRINSICS + case GT_HWINTRINSIC: +#endif // FEATURE_HW_INTRINSICS + { + assert(!retVal->TypeIs(TYP_STRUCT)); + if (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(retVal)) + { + GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, ret->TypeGet(), retVal, nullptr); + ret->gtOp1 = bitcast; + BlockRange().InsertBefore(ret, bitcast); + ContainCheckBitCast(bitcast); + } + } + break; +#endif // FEATURE_SIMD || FEATURE_HW_INTRINSICS + case GT_LCL_FLD: { - GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, ret->TypeGet(), retVal, nullptr); - ret->gtOp1 = bitcast; - BlockRange().InsertBefore(ret, bitcast); - ContainCheckBitCast(bitcast); - break; +#ifdef DEBUG + GenTreeLclFld* lclFld = retVal->AsLclFld(); + unsigned lclNum = lclFld->GetLclNum(); + LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); + assert(varDsc->lvDoNotEnregister); +#endif + retVal->ChangeType(nativeReturnType); } + break; + default: unreached(); } @@ -3081,15 +3182,21 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret) // LowerRetStructLclVar: Lowers a return node with a struct lclVar as a source. // // Arguments: -// node - The return node to lower. +// node - The return node to lower. +// +// Notes: +// - if LclVar is allocated in memory then read it as return type; +// - if LclVar can be enregistered read it as register type and add a bitcast if necessary; // void Lowering::LowerRetStructLclVar(GenTreeUnOp* ret) { + assert(!comp->compMethodReturnsMultiRegRetType()); assert(!comp->compDoOldStructRetyping()); assert(ret->OperIs(GT_RETURN)); - GenTreeLclVar* lclVar = ret->gtGetOp1()->AsLclVar(); - unsigned lclNum = lclVar->GetLclNum(); - LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); + GenTreeLclVarCommon* lclVar = ret->gtGetOp1()->AsLclVar(); + assert(lclVar->OperIs(GT_LCL_VAR)); + unsigned lclNum = lclVar->GetLclNum(); + LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); #ifdef DEBUG if (comp->gtGetStructHandleIfPresent(lclVar) == NO_CLASS_HANDLE) @@ -3100,10 +3207,9 @@ void Lowering::LowerRetStructLclVar(GenTreeUnOp* ret) #endif if (varDsc->lvPromoted && (comp->lvaGetPromotionType(lclNum) == Compiler::PROMOTION_TYPE_INDEPENDENT)) { - bool canEnregister = false; if (varDsc->lvFieldCnt == 1) { - // We have to replace it with its field. + // We can replace the struct with its only field and keep the field on a register. assert(varDsc->lvRefCnt() == 0); unsigned fieldLclNum = varDsc->lvFieldLclStart; LclVarDsc* fieldDsc = comp->lvaGetDesc(fieldLclNum); @@ -3113,10 +3219,11 @@ void Lowering::LowerRetStructLclVar(GenTreeUnOp* ret) JITDUMP("Replacing an independently promoted local var with its only field for the return %u, %u\n", lclNum, fieldLclNum); lclVar->ChangeType(fieldDsc->lvType); - canEnregister = true; + lclNum = fieldLclNum; + varDsc = comp->lvaGetDesc(lclNum); } } - if (!canEnregister) + else { // TODO-1stClassStructs: We can no longer promote or enregister this struct, // since it is referenced as a whole. @@ -3124,16 +3231,25 @@ void Lowering::LowerRetStructLclVar(GenTreeUnOp* ret) } } - var_types regType = varDsc->GetRegisterType(lclVar); - assert((regType != TYP_STRUCT) && (regType != TYP_UNKNOWN)); - // Note: regType could be a small type, in this case return will generate an extension move. - lclVar->ChangeType(regType); - if (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(lclVar)) + if (varDsc->lvDoNotEnregister) { - GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, ret->TypeGet(), lclVar, nullptr); - ret->gtOp1 = bitcast; - BlockRange().InsertBefore(ret, bitcast); - ContainCheckBitCast(bitcast); + lclVar->ChangeOper(GT_LCL_FLD); + lclVar->AsLclFld()->SetLclOffs(0); + lclVar->ChangeType(ret->TypeGet()); + } + else + { + var_types lclVarType = varDsc->GetRegisterType(lclVar); + assert(lclVarType != TYP_UNDEF); + lclVar->ChangeType(lclVarType); + + if (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(lclVarType)) + { + GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, ret->TypeGet(), lclVar, nullptr); + ret->gtOp1 = bitcast; + BlockRange().InsertBefore(ret, bitcast); + ContainCheckBitCast(bitcast); + } } } @@ -3143,16 +3259,32 @@ void Lowering::LowerRetStructLclVar(GenTreeUnOp* ret) // Arguments: // call - The call node to lower. // -// Note: it transforms the call's user. +// Notes: +// - this handles only single-register returns; +// - it transforms the call's user for `GT_STOREIND`. // void Lowering::LowerCallStruct(GenTreeCall* call) { + assert(varTypeIsStruct(call)); + if (call->HasMultiRegRetVal()) + { + return; + } + +#ifdef TARGET_ARMARCH + // !compDoOldStructRetyping is not supported on arm yet, + // because of HFA. + assert(comp->compDoOldStructRetyping()); + return; +#else // !TARGET_ARMARCH + assert(!comp->compDoOldStructRetyping()); CORINFO_CLASS_HANDLE retClsHnd = call->gtRetClsHnd; Compiler::structPassingKind howToReturnStruct; var_types returnType = comp->getReturnTypeForStruct(retClsHnd, &howToReturnStruct); assert(!varTypeIsStruct(returnType) && returnType != TYP_UNKNOWN); - call->gtType = genActualType(returnType); // the callee normalizes small return types. + var_types origType = call->TypeGet(); + call->gtType = genActualType(returnType); LIR::Use callUse; if (BlockRange().TryGetUse(call, &callUse)) @@ -3162,35 +3294,108 @@ void Lowering::LowerCallStruct(GenTreeCall* call) { case GT_RETURN: case GT_STORE_LCL_VAR: - // Leave as is, the user will handle it. - break; - case GT_STORE_BLK: case GT_STORE_OBJ: - { - GenTreeBlk* storeBlk = user->AsBlk(); -#ifdef DEBUG - unsigned storeSize = storeBlk->GetLayout()->GetSize(); - assert(storeSize == genTypeSize(returnType)); -#endif // DEBUG - // For `STORE_BLK<2>(dst, call struct<2>)` we will have call retyped as `int`, - // but `STORE` has to use the unwidened type. - user->ChangeType(returnType); - user->SetOper(GT_STOREIND); - } - break; + // Leave as is, the user will handle it. + assert(user->TypeIs(origType)); + break; case GT_STOREIND: - assert(user->TypeIs(TYP_SIMD8, TYP_REF)); - user->ChangeType(returnType); +#ifdef FEATURE_SIMD + if (user->TypeIs(TYP_SIMD8)) + { + user->ChangeType(returnType); + break; + } +#endif // FEATURE_SIMD + // importer has a separate mechanism to retype calls to helpers, + // keep it for now. + assert(user->TypeIs(TYP_REF)); + assert(call->IsHelperCall()); + assert(returnType == user->TypeGet()); break; default: unreached(); } } +#endif // !TARGET_ARMARCH } -#endif // !FEATURE_MULTIREG_RET + +//---------------------------------------------------------------------------------------------- +// LowerStoreCallStruct: Lowers a store block where source is a struct typed call. +// +// Arguments: +// store - The store node to lower. +// +// Notes: +// - it spills the call's result if it can be retyped as a primitive type. +// +void Lowering::LowerStoreCallStruct(GenTreeBlk* store) +{ + assert(!comp->compDoOldStructRetyping()); + assert(varTypeIsStruct(store)); + assert(store->Data()->IsCall()); + GenTreeCall* call = store->Data()->AsCall(); + + const ClassLayout* layout = store->GetLayout(); + assert(layout->GetSlotCount() == 1); + const var_types regType = layout->GetRegisterType(); + + unsigned storeSize = store->GetLayout()->GetSize(); + if (regType != TYP_UNDEF) + { + store->ChangeType(regType); + store->SetOper(GT_STOREIND); + LowerStoreIndir(store->AsIndir()); + } + else + { +#if defined(WINDOWS_AMD64_ABI) + // All ABI except Windows x64 supports passing 3 byte structs in registers. + // Other 64 bites ABI-s support passing 5, 6, 7 byte structs. + unreached(); +#else // !WINDOWS_AMD64_ABI + if (store->OperIs(GT_STORE_OBJ)) + { + store->SetOper(GT_STORE_BLK); + } + store->gtBlkOpKind = GenTreeObj::BlkOpKindUnroll; + + GenTreeLclVar* spilledCall = SpillStructCallResult(call); + store->SetData(spilledCall); + LowerBlockStore(store); +#endif // WINDOWS_AMD64_ABI + } +} + +#if !defined(WINDOWS_AMD64_ABI) +//---------------------------------------------------------------------------------------------- +// SpillStructCallResult: Spill call result to memory. +// +// Arguments: +// call - call with 3, 5, 6 or 7 return size that has to be spilled to memory. +// +// Return Value: +// load of the spilled variable. +// +GenTreeLclVar* Lowering::SpillStructCallResult(GenTreeCall* call) const +{ + // TODO-1stClassStructs: we can support this in codegen for `GT_STORE_BLK` without new temps. + const unsigned spillNum = comp->lvaGrabTemp(true DEBUGARG("Return value temp for an odd struct return size")); + CORINFO_CLASS_HANDLE retClsHnd = call->gtRetClsHnd; + comp->lvaSetStruct(spillNum, retClsHnd, false); + GenTreeLclFld* spill = new (comp, GT_STORE_LCL_FLD) GenTreeLclFld(GT_STORE_LCL_FLD, call->gtType, spillNum, 0); + spill->gtOp1 = call; + spill->gtFlags |= GTF_VAR_DEF; + + BlockRange().InsertAfter(call, spill); + ContainCheckStoreLoc(spill); + GenTreeLclVar* loadCallResult = comp->gtNewLclvNode(spillNum, TYP_STRUCT)->AsLclVar(); + BlockRange().InsertAfter(spill, loadCallResult); + return loadCallResult; +} +#endif // !WINDOWS_AMD64_ABI GenTree* Lowering::LowerDirectCall(GenTreeCall* call) { @@ -3282,11 +3487,19 @@ GenTree* Lowering::LowerDirectCall(GenTreeCall* call) case IAT_PVALUE: { - // Non-virtual direct calls to addresses accessed by - // a single indirection. - GenTree* cellAddr = AddrGen(addr); - GenTree* indir = Ind(cellAddr); - result = indir; + bool isR2RRelativeIndir = false; +#if defined(FEATURE_READYTORUN_COMPILER) && defined(TARGET_ARMARCH) + isR2RRelativeIndir = call->IsR2RRelativeIndir(); +#endif // FEATURE_READYTORUN_COMPILER && TARGET_ARMARCH + + if (!isR2RRelativeIndir) + { + // Non-virtual direct calls to addresses accessed by + // a single indirection. + GenTree* cellAddr = AddrGen(addr); + GenTree* indir = Ind(cellAddr); + result = indir; + } break; } diff --git a/src/coreclr/src/jit/lower.h b/src/coreclr/src/jit/lower.h index 9c79ede16869a..0582cfe61e5d6 100644 --- a/src/coreclr/src/jit/lower.h +++ b/src/coreclr/src/jit/lower.h @@ -92,7 +92,7 @@ class Lowering final : public Phase void ContainCheckStoreIndir(GenTreeIndir* indirNode); void ContainCheckMul(GenTreeOp* node); void ContainCheckShiftRotate(GenTreeOp* node); - void ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc); + void ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) const; void ContainCheckCast(GenTreeCast* node); void ContainCheckCompare(GenTreeOp* node); void ContainCheckBinary(GenTreeOp* node); @@ -132,11 +132,14 @@ class Lowering final : public Phase GenTreeCC* LowerNodeCC(GenTree* node, GenCondition condition); void LowerJmpMethod(GenTree* jmp); void LowerRet(GenTreeUnOp* ret); -#if !FEATURE_MULTIREG_RET + void LowerStoreLocCommon(GenTreeLclVarCommon* lclVar); void LowerRetStruct(GenTreeUnOp* ret); void LowerRetStructLclVar(GenTreeUnOp* ret); void LowerCallStruct(GenTreeCall* call); -#endif + void LowerStoreCallStruct(GenTreeBlk* store); +#if !defined(WINDOWS_AMD64_ABI) + GenTreeLclVar* SpillStructCallResult(GenTreeCall* call) const; +#endif // WINDOWS_AMD64_ABI GenTree* LowerDelegateInvoke(GenTreeCall* call); GenTree* LowerIndirectNonvirtCall(GenTreeCall* call); GenTree* LowerDirectCall(GenTreeCall* call); @@ -315,9 +318,177 @@ class Lowering final : public Phase #ifdef FEATURE_HW_INTRINSICS void LowerHWIntrinsic(GenTreeHWIntrinsic* node); void LowerHWIntrinsicCC(GenTreeHWIntrinsic* node, NamedIntrinsic newIntrinsicId, GenCondition condition); + void LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp); + void LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node); void LowerFusedMultiplyAdd(GenTreeHWIntrinsic* node); + +#ifdef TARGET_ARM64 + bool IsValidConstForMovImm(GenTreeHWIntrinsic* node); +#endif // TARGET_ARM64 + + union VectorConstant { + int8_t i8[32]; + uint8_t u8[32]; + int16_t i16[16]; + uint16_t u16[16]; + int32_t i32[8]; + uint32_t u32[8]; + int64_t i64[4]; + uint64_t u64[4]; + float f32[8]; + double f64[4]; + }; + + //---------------------------------------------------------------------------------------------- + // ProcessArgForHWIntrinsicCreate: Processes an argument for the Lowering::LowerHWIntrinsicCreate method + // + // Arguments: + // arg - The argument to process + // argIdx - The index of the argument being processed + // vecCns - The vector constant being constructed + // baseType - The base type of the vector constant + // + // Returns: + // true if arg was a constant; otherwise, false + static bool HandleArgForHWIntrinsicCreate(GenTree* arg, int argIdx, VectorConstant& vecCns, var_types baseType) + { + switch (baseType) + { + case TYP_BYTE: + case TYP_UBYTE: + { + if (arg->IsCnsIntOrI()) + { + vecCns.i8[argIdx] = static_cast(arg->AsIntCon()->gtIconVal); + return true; + } + else + { + // We expect the VectorConstant to have been already zeroed + assert(vecCns.i8[argIdx] == 0); + } + break; + } + + case TYP_SHORT: + case TYP_USHORT: + { + if (arg->IsCnsIntOrI()) + { + vecCns.i16[argIdx] = static_cast(arg->AsIntCon()->gtIconVal); + return true; + } + else + { + // We expect the VectorConstant to have been already zeroed + assert(vecCns.i16[argIdx] == 0); + } + break; + } + + case TYP_INT: + case TYP_UINT: + { + if (arg->IsCnsIntOrI()) + { + vecCns.i32[argIdx] = static_cast(arg->AsIntCon()->gtIconVal); + return true; + } + else + { + // We expect the VectorConstant to have been already zeroed + assert(vecCns.i32[argIdx] == 0); + } + break; + } + + case TYP_LONG: + case TYP_ULONG: + { + if (arg->OperIs(GT_CNS_LNG)) + { + vecCns.i64[argIdx] = static_cast(arg->AsLngCon()->gtLconVal); + return true; + } + else + { + // We expect the VectorConstant to have been already zeroed + assert(vecCns.i64[argIdx] == 0); + } + break; + } + + case TYP_FLOAT: + { + if (arg->IsCnsFltOrDbl()) + { + vecCns.f32[argIdx] = static_cast(arg->AsDblCon()->gtDconVal); + return true; + } + else + { + // We expect the VectorConstant to have been already zeroed + // We check against the i32, rather than f32, to account for -0.0 + assert(vecCns.i32[argIdx] == 0); + } + break; + } + + case TYP_DOUBLE: + { + if (arg->IsCnsFltOrDbl()) + { + vecCns.f64[argIdx] = static_cast(arg->AsDblCon()->gtDconVal); + return true; + } + else + { + // We expect the VectorConstant to have been already zeroed + // We check against the i64, rather than f64, to account for -0.0 + assert(vecCns.i64[argIdx] == 0); + } + break; + } + + default: + { + unreached(); + } + } + + return false; + } #endif // FEATURE_HW_INTRINSICS + //---------------------------------------------------------------------------------------------- + // TryRemoveCastIfPresent: Removes op it is a cast operation and the size of its input is at + // least the size of expectedType + // + // Arguments: + // expectedType - The expected type of the cast operation input if it is to be removed + // op - The tree to remove if it is a cast op whose input is at least the size of expectedType + // + // Returns: + // op if it was not a cast node or if its input is not at least the size of expected type; + // Otherwise, it returns the underlying operation that was being casted + GenTree* TryRemoveCastIfPresent(var_types expectedType, GenTree* op) + { + if (!op->OperIs(GT_CAST)) + { + return op; + } + + GenTree* castOp = op->AsCast()->CastOp(); + + if (genTypeSize(castOp->gtType) >= genTypeSize(expectedType)) + { + BlockRange().Remove(op); + return castOp; + } + + return op; + } + // Utility functions public: static bool IndirsAreEquivalent(GenTree* pTreeA, GenTree* pTreeB); @@ -325,7 +496,7 @@ class Lowering final : public Phase // return true if 'childNode' is an immediate that can be contained // by the 'parentNode' (i.e. folded into an instruction) // for example small enough and non-relocatable - bool IsContainableImmed(GenTree* parentNode, GenTree* childNode); + bool IsContainableImmed(GenTree* parentNode, GenTree* childNode) const; // Return true if 'node' is a containable memory op. bool IsContainableMemoryOp(GenTree* node) @@ -344,7 +515,7 @@ class Lowering final : public Phase bool AreSourcesPossiblyModifiedLocals(GenTree* addr, GenTree* base, GenTree* index); // Makes 'childNode' contained in the 'parentNode' - void MakeSrcContained(GenTree* parentNode, GenTree* childNode); + void MakeSrcContained(GenTree* parentNode, GenTree* childNode) const; // Checks and makes 'childNode' contained in the 'parentNode' bool CheckImmedAndMakeContained(GenTree* parentNode, GenTree* childNode); diff --git a/src/coreclr/src/jit/lowerarmarch.cpp b/src/coreclr/src/jit/lowerarmarch.cpp index 6f3cbda1f55a9..c3ac6513e9546 100644 --- a/src/coreclr/src/jit/lowerarmarch.cpp +++ b/src/coreclr/src/jit/lowerarmarch.cpp @@ -52,7 +52,7 @@ bool Lowering::IsCallTargetInRange(void* addr) // TODO-CQ: we can contain a floating point 0.0 constant in a compare instruction // (vcmp on arm, fcmp on arm64). // -bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) +bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) const { if (!varTypeIsFloating(parentNode->TypeGet())) { @@ -535,8 +535,484 @@ void Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) node->gtType = TYP_SIMD16; } + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + + switch (intrinsicId) + { + case NI_Vector64_Create: + case NI_Vector128_Create: + { + // We don't directly support the Vector64.Create or Vector128.Create methods in codegen + // and instead lower them to other intrinsic nodes in LowerHWIntrinsicCreate so we expect + // that the node is modified to either not be a HWIntrinsic node or that it is no longer + // the same intrinsic as when it came in. + + LowerHWIntrinsicCreate(node); + assert(!node->OperIsHWIntrinsic() || (node->gtHWIntrinsicId != intrinsicId)); + LowerNode(node); + return; + } + + case NI_Vector64_op_Equality: + case NI_Vector128_op_Equality: + { + LowerHWIntrinsicCmpOp(node, GT_EQ); + return; + } + + case NI_Vector64_op_Inequality: + case NI_Vector128_op_Inequality: + { + LowerHWIntrinsicCmpOp(node, GT_NE); + return; + } + + default: + break; + } + ContainCheckHWIntrinsic(node); } + +//---------------------------------------------------------------------------------------------- +// Lowering::IsValidConstForMovImm: Determines if the given node can be replaced by a mov/fmov immediate instruction +// +// Arguments: +// node - The hardware intrinsic node. +// +// Returns: +// true if the node can be replaced by a mov/fmov immediate instruction; otherwise, false +// +// IMPORTANT: +// This check may end up modifying node->gtOp1 if it is a cast node that can be removed +bool Lowering::IsValidConstForMovImm(GenTreeHWIntrinsic* node) +{ + assert((node->gtHWIntrinsicId == NI_Vector64_Create) || (node->gtHWIntrinsicId == NI_Vector128_Create) || + (node->gtHWIntrinsicId == NI_Vector64_CreateScalarUnsafe) || + (node->gtHWIntrinsicId == NI_Vector128_CreateScalarUnsafe) || + (node->gtHWIntrinsicId == NI_AdvSimd_DuplicateToVector64) || + (node->gtHWIntrinsicId == NI_AdvSimd_DuplicateToVector128) || + (node->gtHWIntrinsicId == NI_AdvSimd_Arm64_DuplicateToVector64) || + (node->gtHWIntrinsicId == NI_AdvSimd_Arm64_DuplicateToVector128)); + assert(HWIntrinsicInfo::lookupNumArgs(node) == 1); + + GenTree* op1 = node->gtOp1; + GenTree* castOp = nullptr; + + if (varTypeIsIntegral(node->gtSIMDBaseType) && op1->OperIs(GT_CAST)) + { + // We will sometimes get a cast around a constant value (such as for + // certain long constants) which would block the below containment. + // So we will temporarily check what the cast is from instead so we + // can catch those cases as well. + + castOp = op1->AsCast()->CastOp(); + op1 = castOp; + } + + if (op1->IsCnsIntOrI()) + { + const ssize_t dataValue = op1->AsIntCon()->gtIconVal; + + if (comp->GetEmitter()->emitIns_valid_imm_for_movi(dataValue, emitActualTypeSize(node->gtSIMDBaseType))) + { + if (castOp != nullptr) + { + // We found a containable immediate under + // a cast, so remove the cast from the LIR. + + BlockRange().Remove(node->gtOp1); + node->gtOp1 = op1; + } + return true; + } + } + else if (op1->IsCnsFltOrDbl()) + { + assert(varTypeIsFloating(node->gtSIMDBaseType)); + assert(castOp == nullptr); + + const double dataValue = op1->AsDblCon()->gtDconVal; + return comp->GetEmitter()->emitIns_valid_imm_for_fmov(dataValue); + } + + return false; +} + +//---------------------------------------------------------------------------------------------- +// Lowering::LowerHWIntrinsicCmpOp: Lowers a Vector128 or Vector256 comparison intrinsic +// +// Arguments: +// node - The hardware intrinsic node. +// cmpOp - The comparison operation, currently must be GT_EQ or GT_NE +// +void Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp) +{ + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + var_types baseType = node->gtSIMDBaseType; + unsigned simdSize = node->gtSIMDSize; + var_types simdType = Compiler::getSIMDTypeForSize(simdSize); + + assert((intrinsicId == NI_Vector64_op_Equality) || (intrinsicId == NI_Vector64_op_Inequality) || + (intrinsicId == NI_Vector128_op_Equality) || (intrinsicId == NI_Vector128_op_Inequality)); + + assert(varTypeIsSIMD(simdType)); + assert(varTypeIsArithmetic(baseType)); + assert(simdSize != 0); + assert(node->gtType == TYP_BOOL); + assert((cmpOp == GT_EQ) || (cmpOp == GT_NE)); + + // We have the following (with the appropriate simd size and where the intrinsic could be op_Inequality): + // /--* op2 simd + // /--* op1 simd + // node = * HWINTRINSIC simd T op_Equality + + GenTree* op1 = node->gtGetOp1(); + GenTree* op2 = node->gtGetOp2(); + + NamedIntrinsic cmpIntrinsic; + + switch (baseType) + { + case TYP_BYTE: + case TYP_UBYTE: + case TYP_SHORT: + case TYP_USHORT: + case TYP_INT: + case TYP_UINT: + case TYP_FLOAT: + { + cmpIntrinsic = NI_AdvSimd_CompareEqual; + break; + } + + case TYP_LONG: + case TYP_ULONG: + case TYP_DOUBLE: + { + cmpIntrinsic = NI_AdvSimd_Arm64_CompareEqual; + break; + } + + default: + { + unreached(); + } + } + + GenTree* cmp = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, cmpIntrinsic, baseType, simdSize); + BlockRange().InsertBefore(node, cmp); + LowerNode(cmp); + + if ((baseType == TYP_FLOAT) && (simdSize == 12)) + { + // For TYP_SIMD12 we don't want the upper bits to participate in the comparison. So, we will insert all ones + // into those bits of the result, "as if" the upper bits are equal. Then if all lower bits are equal, we get the + // expected all-ones result, and will get the expected 0's only where there are non-matching bits. + + GenTree* idxCns = comp->gtNewIconNode(3, TYP_INT); + BlockRange().InsertAfter(cmp, idxCns); + + GenTree* insCns = comp->gtNewIconNode(-1, TYP_INT); + BlockRange().InsertAfter(idxCns, insCns); + + GenTree* tmp = + comp->gtNewSimdAsHWIntrinsicNode(simdType, cmp, idxCns, insCns, NI_AdvSimd_Insert, TYP_INT, simdSize); + BlockRange().InsertAfter(insCns, tmp); + LowerNode(tmp); + + cmp = tmp; + } + + GenTree* msk = comp->gtNewSimdHWIntrinsicNode(simdType, cmp, NI_AdvSimd_Arm64_MinAcross, TYP_UBYTE, simdSize); + BlockRange().InsertAfter(cmp, msk); + LowerNode(msk); + + GenTree* zroCns = comp->gtNewIconNode(0, TYP_INT); + BlockRange().InsertAfter(msk, zroCns); + + GenTree* val = comp->gtNewSimdAsHWIntrinsicNode(TYP_UBYTE, msk, zroCns, NI_AdvSimd_Extract, TYP_UBYTE, simdSize); + BlockRange().InsertAfter(zroCns, val); + LowerNode(val); + + zroCns = comp->gtNewIconNode(0, TYP_INT); + BlockRange().InsertAfter(val, zroCns); + + node->ChangeOper(cmpOp); + + node->gtType = TYP_INT; + node->gtOp1 = val; + node->gtOp2 = zroCns; + + // The CompareEqual will set (condition is true) or clear (condition is false) all bits of the respective element + // The MinAcross then ensures we get either all bits set (all conditions are true) or clear (any condition is false) + // So, we need to invert the condition from the operation since we compare against zero + + GenCondition cmpCnd = (cmpOp == GT_EQ) ? GenCondition::NE : GenCondition::EQ; + GenTree* cc = LowerNodeCC(node, cmpCnd); + + node->gtType = TYP_VOID; + node->ClearUnusedValue(); + + LowerNode(node); +} + +//---------------------------------------------------------------------------------------------- +// Lowering::LowerHWIntrinsicCreate: Lowers a Vector64 or Vector128 Create call +// +// Arguments: +// node - The hardware intrinsic node. +// +void Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) +{ + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + var_types simdType = node->gtType; + var_types baseType = node->gtSIMDBaseType; + unsigned simdSize = node->gtSIMDSize; + VectorConstant vecCns = {}; + + if ((simdSize == 8) && (simdType == TYP_DOUBLE)) + { + simdType = TYP_SIMD8; + } + + assert(varTypeIsSIMD(simdType)); + assert(varTypeIsArithmetic(baseType)); + assert(simdSize != 0); + + GenTreeArgList* argList = nullptr; + GenTree* op1 = node->gtGetOp1(); + GenTree* op2 = node->gtGetOp2(); + + // Spare GenTrees to be used for the lowering logic below + // Defined upfront to avoid naming conflicts, etc... + GenTree* idx = nullptr; + GenTree* tmp1 = nullptr; + GenTree* tmp2 = nullptr; + GenTree* tmp3 = nullptr; + + assert(op1 != nullptr); + + unsigned argCnt = 0; + unsigned cnsArgCnt = 0; + + if (op1->OperIsList()) + { + assert(op2 == nullptr); + + for (argList = op1->AsArgList(); argList != nullptr; argList = argList->Rest()) + { + if (HandleArgForHWIntrinsicCreate(argList->Current(), argCnt, vecCns, baseType)) + { + cnsArgCnt += 1; + } + argCnt += 1; + } + } + else + { + if (HandleArgForHWIntrinsicCreate(op1, argCnt, vecCns, baseType)) + { + cnsArgCnt += 1; + } + argCnt += 1; + + if (op2 != nullptr) + { + if (HandleArgForHWIntrinsicCreate(op2, argCnt, vecCns, baseType)) + { + cnsArgCnt += 1; + } + argCnt += 1; + } + else if (cnsArgCnt == 1) + { + // These intrinsics are meant to set the same value to every element + // so we'll just specially handle it here and copy it into the remaining + // indices. + + for (unsigned i = 1; i < simdSize / genTypeSize(baseType); i++) + { + HandleArgForHWIntrinsicCreate(op1, i, vecCns, baseType); + } + } + } + assert((argCnt == 1) || (argCnt == (simdSize / genTypeSize(baseType)))); + + if ((argCnt == cnsArgCnt) && (argCnt == 1)) + { + GenTree* castOp = nullptr; + + if (varTypeIsIntegral(baseType) && op1->OperIs(GT_CAST)) + { + // We will sometimes get a cast around a constant value (such as for + // certain long constants) which would block the below containment. + // So we will temporarily check what the cast is from instead so we + // can catch those cases as well. + + castOp = op1->AsCast()->CastOp(); + op1 = castOp; + } + + if (IsValidConstForMovImm(node)) + { + // Set the cnsArgCnt to zero so we get lowered to a DuplicateToVector + // intrinsic, which will itself mark the node as contained. + cnsArgCnt = 0; + + // Reacquire op1 as the above check may have removed a cast node and + // changed op1. + op1 = node->gtOp1; + } + } + + if (argCnt == cnsArgCnt) + { + if (op1->OperIsList()) + { + for (argList = op1->AsArgList(); argList != nullptr; argList = argList->Rest()) + { + BlockRange().Remove(argList->Current()); + } + } + else + { + BlockRange().Remove(op1); + + if (op2 != nullptr) + { + BlockRange().Remove(op2); + } + } + + assert((simdSize == 8) || (simdSize == 16)); + + UNATIVE_OFFSET cnsSize = simdSize; + UNATIVE_OFFSET cnsAlign = cnsSize; + + CORINFO_FIELD_HANDLE hnd = comp->GetEmitter()->emitAnyConst(&vecCns, cnsSize, cnsAlign); + GenTree* clsVarAddr = new (comp, GT_CLS_VAR_ADDR) GenTreeClsVar(GT_CLS_VAR_ADDR, TYP_I_IMPL, hnd, nullptr); + BlockRange().InsertBefore(node, clsVarAddr); + + node->ChangeOper(GT_IND); + node->gtOp1 = clsVarAddr; + + // TODO-ARM64-CQ: We should be able to modify at least the paths that use Insert to trivially support partial + // vector constants. With this, we can create a constant if say 50% of the inputs are also constant and just + // insert the non-constant values which should still allow some gains. + + return; + } + else if (argCnt == 1) + { + // We have the following (where simd is simd8 or simd16): + // /--* op1 T + // node = * HWINTRINSIC simd T Create + + // We will be constructing the following parts: + // /--* op1 T + // node = * HWINTRINSIC simd T DuplicateToVector + + // This is roughly the following managed code: + // return AdvSimd.Arm64.DuplicateToVector(op1); + + if (varTypeIsLong(baseType) || (baseType == TYP_DOUBLE)) + { + node->gtHWIntrinsicId = + (simdType == TYP_SIMD8) ? NI_AdvSimd_Arm64_DuplicateToVector64 : NI_AdvSimd_Arm64_DuplicateToVector128; + } + else + { + node->gtHWIntrinsicId = + (simdType == TYP_SIMD8) ? NI_AdvSimd_DuplicateToVector64 : NI_AdvSimd_DuplicateToVector128; + } + return; + } + + // We have the following (where simd is simd8 or simd16): + // /--* op1 T + // +--* ... T + // +--* opN T + // node = * HWINTRINSIC simd T Create + + if (op1->OperIsList()) + { + argList = op1->AsArgList(); + op1 = argList->Current(); + argList = argList->Rest(); + } + + // We will be constructing the following parts: + // /--* op1 T + // tmp1 = * HWINTRINSIC simd8 T CreateScalarUnsafe + // ... + + // This is roughly the following managed code: + // var tmp1 = Vector64.CreateScalarUnsafe(op1); + // ... + + NamedIntrinsic createScalarUnsafe = + (simdType == TYP_SIMD8) ? NI_Vector64_CreateScalarUnsafe : NI_Vector128_CreateScalarUnsafe; + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, createScalarUnsafe, baseType, simdSize); + BlockRange().InsertAfter(op1, tmp1); + LowerNode(tmp1); + + unsigned N = 0; + GenTree* opN = nullptr; + + for (N = 1; N < argCnt - 1; N++) + { + // We will be constructing the following parts: + // ... + // idx = CNS_INT int N + // /--* tmp1 simd + // +--* idx int + // +--* opN T + // tmp1 = * HWINTRINSIC simd T Insert + // ... + + // This is roughly the following managed code: + // ... + // tmp1 = AdvSimd.Insert(tmp1, N, opN); + // ... + + opN = argList->Current(); + + idx = comp->gtNewIconNode(N, TYP_INT); + BlockRange().InsertBefore(opN, idx); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, idx, opN, NI_AdvSimd_Insert, baseType, simdSize); + BlockRange().InsertAfter(opN, tmp1); + LowerNode(tmp1); + + argList = argList->Rest(); + } + + assert(N == (argCnt - 1)); + + // We will be constructing the following parts: + // idx = CNS_INT int N + // /--* tmp1 simd + // +--* idx int + // +--* opN T + // node = * HWINTRINSIC simd T Insert + + // This is roughly the following managed code: + // ... + // tmp1 = AdvSimd.Insert(tmp1, N, opN); + // ... + + opN = (argCnt == 2) ? op2 : argList->Current(); + + idx = comp->gtNewIconNode(N, TYP_INT); + BlockRange().InsertBefore(opN, idx); + + node->gtOp1 = comp->gtNewArgList(tmp1, idx, opN); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_AdvSimd_Insert; +} #endif // FEATURE_HW_INTRINSICS //------------------------------------------------------------------------ @@ -610,10 +1086,12 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) } #endif // FEATURE_SIMD - GenTree* addr = indirNode->Addr(); - bool makeContained = true; + GenTree* addr = indirNode->Addr(); + if ((addr->OperGet() == GT_LEA) && IsSafeToContainMem(indirNode, addr)) { + bool makeContained = true; + #ifdef TARGET_ARM // ARM floating-point load/store doesn't support a form similar to integer // ldr Rdst, [Rbase + Roffset] with offset in a register. The only supported @@ -637,12 +1115,23 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) } } } -#endif +#endif // TARGET_ARM + if (makeContained) { MakeSrcContained(indirNode, addr); } } +#ifdef TARGET_ARM64 + else if (addr->OperGet() == GT_CLS_VAR_ADDR) + { + // These nodes go into an addr mode: + // - GT_CLS_VAR_ADDR turns into a constant. + + // make this contained, it turns into a constant that goes into an addr mode + MakeSrcContained(indirNode, addr); + } +#endif // TARGET_ARM64 } //------------------------------------------------------------------------ @@ -713,7 +1202,7 @@ void Lowering::ContainCheckShiftRotate(GenTreeOp* node) // Arguments: // node - pointer to the node // -void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) +void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) const { assert(storeLoc->OperIsLocalStore()); GenTree* op1 = storeLoc->gtGetOp1(); @@ -730,13 +1219,20 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) return; } } + + const LclVarDsc* varDsc = comp->lvaGetDesc(storeLoc); + #ifdef FEATURE_SIMD if (varTypeIsSIMD(storeLoc)) { - if (op1->IsIntegralConst(0)) + // If this is a store to memory, we can initialize a zero vector in memory from REG_ZR. + if ((op1->IsIntegralConst(0) || op1->IsSIMDZero()) && varDsc->lvDoNotEnregister) { - // For an InitBlk we want op1 to be contained MakeSrcContained(storeLoc, op1); + if (op1->IsSIMDZero()) + { + MakeSrcContained(op1, op1->gtGetOp1()); + } } return; } @@ -745,8 +1241,7 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) // If the source is a containable immediate, make it contained, unless it is // an int-size or larger store of zero to memory, because we can generate smaller code // by zeroing a register and then storing it. - const LclVarDsc* varDsc = comp->lvaGetDesc(storeLoc); - var_types type = varDsc->GetRegisterType(storeLoc); + var_types type = varDsc->GetRegisterType(storeLoc); if (IsContainableImmed(storeLoc, op1) && (!op1->IsIntegralConst(0) || varTypeIsSmall(type))) { MakeSrcContained(storeLoc, op1); @@ -833,11 +1328,6 @@ void Lowering::ContainCheckSIMD(GenTreeSIMD* simdNode) CheckImmedAndMakeContained(simdNode, simdNode->gtGetOp2()); break; - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: - // TODO-ARM64-CQ Support containing 0 - break; - case SIMDIntrinsicGetItem: { // This implements get_Item method. The sources are: @@ -890,7 +1380,44 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) switch (intrin.id) { + case NI_AdvSimd_DuplicateSelectedScalarToVector64: + case NI_AdvSimd_DuplicateSelectedScalarToVector128: case NI_AdvSimd_Extract: + case NI_AdvSimd_ShiftLeftLogical: + case NI_AdvSimd_ShiftLeftLogicalSaturate: + case NI_AdvSimd_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsigned: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_ShiftLeftLogicalScalar: + case NI_AdvSimd_ShiftLeftLogicalWideningLower: + case NI_AdvSimd_ShiftLeftLogicalWideningUpper: + case NI_AdvSimd_ShiftRightArithmetic: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticRounded: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedScalar: + case NI_AdvSimd_ShiftRightArithmeticScalar: + case NI_AdvSimd_ShiftRightLogical: + case NI_AdvSimd_ShiftRightLogicalNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalRounded: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalRoundedScalar: + case NI_AdvSimd_ShiftRightLogicalScalar: + case NI_AdvSimd_Arm64_DuplicateSelectedScalarToVector128: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalRoundedNarrowingSaturateScalar: + case NI_Vector64_GetElement: + case NI_Vector128_GetElement: if (intrin.op2->IsCnsIntOrI()) { MakeSrcContained(node, intrin.op2); @@ -899,6 +1426,22 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AdvSimd_ExtractVector64: case NI_AdvSimd_ExtractVector128: + case NI_AdvSimd_ShiftRightArithmeticAdd: + case NI_AdvSimd_ShiftRightArithmeticAddScalar: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedAdd: + case NI_AdvSimd_ShiftRightArithmeticRoundedAddScalar: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalAdd: + case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalNarrowingUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedAdd: + case NI_AdvSimd_ShiftRightLogicalRoundedAddScalar: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingUpper: if (intrin.op3->IsCnsIntOrI()) { MakeSrcContained(node, intrin.op3); @@ -924,31 +1467,23 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) } break; - case NI_Vector64_Create: - case NI_Vector128_Create: case NI_Vector64_CreateScalarUnsafe: case NI_Vector128_CreateScalarUnsafe: - if (intrin.op1->IsCnsIntOrI()) - { - const ssize_t dataValue = intrin.op1->AsIntCon()->gtIconVal; - - if (comp->GetEmitter()->emitIns_valid_imm_for_movi(dataValue, emitActualTypeSize(intrin.baseType))) - { - MakeSrcContained(node, intrin.op1); - } - } - else if (intrin.op1->IsCnsFltOrDbl()) + case NI_AdvSimd_DuplicateToVector64: + case NI_AdvSimd_DuplicateToVector128: + case NI_AdvSimd_Arm64_DuplicateToVector64: + case NI_AdvSimd_Arm64_DuplicateToVector128: + { + if (IsValidConstForMovImm(node)) { - assert(varTypeIsFloating(intrin.baseType)); - - const double dataValue = intrin.op1->AsDblCon()->gtDconVal; + // Use node->gtOp1 as the above check may + // have removed a cast node and changed op1 - if (comp->GetEmitter()->emitIns_valid_imm_for_fmov(dataValue)) - { - MakeSrcContained(node, intrin.op1); - } + MakeSrcContained(node, node->gtOp1); } break; + } + default: unreached(); } diff --git a/src/coreclr/src/jit/lowerxarch.cpp b/src/coreclr/src/jit/lowerxarch.cpp index ad0426bbb620d..52a4de5a1c2e4 100644 --- a/src/coreclr/src/jit/lowerxarch.cpp +++ b/src/coreclr/src/jit/lowerxarch.cpp @@ -712,8 +712,12 @@ void Lowering::LowerSIMD(GenTreeSIMD* simdNode) BlockRange().Remove(list->Current()); } - CORINFO_FIELD_HANDLE hnd = - comp->GetEmitter()->emitAnyConst(constArgValues, sizeof(constArgValues), emitDataAlignment::Required); + assert(sizeof(constArgValues) == 16); + + UNATIVE_OFFSET cnsSize = sizeof(constArgValues); + UNATIVE_OFFSET cnsAlign = (comp->compCodeOpt() != Compiler::SMALL_CODE) ? cnsSize : 1; + + CORINFO_FIELD_HANDLE hnd = comp->GetEmitter()->emitAnyConst(constArgValues, cnsSize, cnsAlign); GenTree* clsVarAddr = new (comp, GT_CLS_VAR_ADDR) GenTreeClsVar(GT_CLS_VAR_ADDR, TYP_I_IMPL, hnd, nullptr); BlockRange().InsertBefore(simdNode, clsVarAddr); simdNode->ChangeOper(GT_IND); @@ -743,14 +747,6 @@ void Lowering::LowerSIMD(GenTreeSIMD* simdNode) // the addr of SIMD vector with the given index. simdNode->gtOp1->gtFlags |= GTF_IND_REQ_ADDR_IN_REG; } - else if (simdNode->IsSIMDEqualityOrInequality()) - { - LowerNodeCC(simdNode, - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality ? GenCondition::EQ : GenCondition::NE); - - simdNode->gtType = TYP_VOID; - simdNode->ClearUnusedValue(); - } #endif ContainCheckSIMD(simdNode); } @@ -927,8 +923,70 @@ void Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) node->gtType = TYP_SIMD16; } - switch (node->gtHWIntrinsicId) + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + + switch (intrinsicId) { + case NI_Vector128_Create: + case NI_Vector256_Create: + { + // We don't directly support the Vector128.Create or Vector256.Create methods in codegen + // and instead lower them to other intrinsic nodes in LowerHWIntrinsicCreate so we expect + // that the node is modified to either not be a HWIntrinsic node or that it is no longer + // the same intrinsic as when it came in. In the case of Vector256.Create, we may lower + // it into 2x Vector128.Create intrinsics which themselves are also lowered into other + // intrinsics that are not Vector*.Create + + LowerHWIntrinsicCreate(node); + assert(!node->OperIsHWIntrinsic() || (node->gtHWIntrinsicId != intrinsicId)); + LowerNode(node); + return; + } + + case NI_Vector128_op_Equality: + case NI_Vector256_op_Equality: + { + LowerHWIntrinsicCmpOp(node, GT_EQ); + return; + } + + case NI_Vector128_op_Inequality: + case NI_Vector256_op_Inequality: + { + LowerHWIntrinsicCmpOp(node, GT_NE); + return; + } + + case NI_SSE2_Insert: + case NI_SSE41_Insert: + case NI_SSE41_X64_Insert: + { + assert(HWIntrinsicInfo::lookupNumArgs(node) == 3); + + GenTreeArgList* argList = node->gtOp1->AsArgList(); + + // Insert takes either a 32-bit register or a memory operand. + // In either case, only gtSIMDBaseType bits are read and so + // widening or narrowing the operand may be unnecessary and it + // can just be used directly. + + argList->Rest()->gtOp1 = TryRemoveCastIfPresent(node->gtSIMDBaseType, argList->Rest()->gtOp1); + break; + } + + case NI_SSE42_Crc32: + { + assert(HWIntrinsicInfo::lookupNumArgs(node) == 2); + + // Crc32 takes either a bit register or a memory operand. + // In either case, only gtType bits are read and so widening + // or narrowing the operand may be unnecessary and it can + // just be used directly. + + node->gtOp2 = TryRemoveCastIfPresent(node->gtType, node->gtOp2); + break; + } + case NI_SSE2_CompareGreaterThan: { if (node->gtSIMDBaseType != TYP_DOUBLE) @@ -1081,6 +1139,1318 @@ void Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) ContainCheckHWIntrinsic(node); } + +//---------------------------------------------------------------------------------------------- +// Lowering::LowerHWIntrinsicCmpOp: Lowers a Vector128 or Vector256 comparison intrinsic +// +// Arguments: +// node - The hardware intrinsic node. +// cmpOp - The comparison operation, currently must be GT_EQ or GT_NE +// +void Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp) +{ + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + var_types baseType = node->gtSIMDBaseType; + unsigned simdSize = node->gtSIMDSize; + var_types simdType = Compiler::getSIMDTypeForSize(simdSize); + + assert((intrinsicId == NI_Vector128_op_Equality) || (intrinsicId == NI_Vector128_op_Inequality) || + (intrinsicId == NI_Vector256_op_Equality) || (intrinsicId == NI_Vector256_op_Inequality)); + + assert(varTypeIsSIMD(simdType)); + assert(varTypeIsArithmetic(baseType)); + assert(simdSize != 0); + assert(node->gtType == TYP_BOOL); + assert((cmpOp == GT_EQ) || (cmpOp == GT_NE)); + + // We have the following (with the appropriate simd size and where the intrinsic could be op_Inequality): + // /--* op2 simd + // /--* op1 simd + // node = * HWINTRINSIC simd T op_Equality + + GenTree* op1 = node->gtGetOp1(); + GenTree* op2 = node->gtGetOp2(); + + GenCondition cmpCnd = (cmpOp == GT_EQ) ? GenCondition::EQ : GenCondition::NE; + + if (op2->IsIntegralConstVector(0) && comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + // On SSE4.1 or higher we can optimize comparisons against zero to + // just use PTEST. We can't support it for floating-point, however, + // as it has both +0.0 and -0.0 where +0.0 == -0.0 + + node->gtOp1 = op1; + BlockRange().Remove(op2); + + LIR::Use op1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(op1Use); + op1 = node->gtOp1; + + op2 = comp->gtClone(op1); + BlockRange().InsertAfter(op1, op2); + node->gtOp2 = op2; + + if (simdSize == 32) + { + node->gtHWIntrinsicId = NI_AVX_TestZ; + LowerHWIntrinsicCC(node, NI_AVX_PTEST, cmpCnd); + } + else + { + node->gtHWIntrinsicId = NI_SSE41_TestZ; + LowerHWIntrinsicCC(node, NI_SSE41_PTEST, cmpCnd); + } + + return; + } + + NamedIntrinsic cmpIntrinsic; + var_types cmpType; + NamedIntrinsic mskIntrinsic; + var_types mskType; + int mskConstant; + + switch (baseType) + { + case TYP_BYTE: + case TYP_UBYTE: + case TYP_SHORT: + case TYP_USHORT: + case TYP_INT: + case TYP_UINT: + { + cmpType = baseType; + mskType = TYP_UBYTE; + + if (simdSize == 32) + { + cmpIntrinsic = NI_AVX2_CompareEqual; + mskIntrinsic = NI_AVX2_MoveMask; + mskConstant = -1; + } + else + { + assert(simdSize == 16); + + cmpIntrinsic = NI_SSE2_CompareEqual; + mskIntrinsic = NI_SSE2_MoveMask; + mskConstant = 0xFFFF; + } + break; + } + + case TYP_LONG: + case TYP_ULONG: + { + mskType = TYP_UBYTE; + + if (simdSize == 32) + { + cmpIntrinsic = NI_AVX2_CompareEqual; + cmpType = baseType; + mskIntrinsic = NI_AVX2_MoveMask; + mskConstant = -1; + } + else + { + assert(simdSize == 16); + + if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + cmpIntrinsic = NI_SSE41_CompareEqual; + cmpType = baseType; + } + else + { + cmpIntrinsic = NI_SSE2_CompareEqual; + cmpType = TYP_UINT; + } + + mskIntrinsic = NI_SSE2_MoveMask; + mskConstant = 0xFFFF; + } + break; + } + + case TYP_FLOAT: + { + cmpType = baseType; + mskType = baseType; + + if (simdSize == 32) + { + cmpIntrinsic = NI_AVX_CompareEqual; + mskIntrinsic = NI_AVX_MoveMask; + mskConstant = 0xFF; + } + else + { + cmpIntrinsic = NI_SSE_CompareEqual; + mskIntrinsic = NI_SSE_MoveMask; + + if (simdSize == 16) + { + mskConstant = 0xF; + } + else if (simdSize == 12) + { + mskConstant = 0x7; + } + else + { + assert(simdSize == 8); + mskConstant = 0x3; + } + } + break; + } + + case TYP_DOUBLE: + { + cmpType = baseType; + mskType = baseType; + + if (simdSize == 32) + { + cmpIntrinsic = NI_AVX_CompareEqual; + mskIntrinsic = NI_AVX_MoveMask; + mskConstant = 0xF; + } + else + { + assert(simdSize == 16); + + cmpIntrinsic = NI_SSE2_CompareEqual; + mskIntrinsic = NI_SSE2_MoveMask; + mskConstant = 0x3; + } + break; + } + + default: + { + unreached(); + } + } + + GenTree* cmp = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, cmpIntrinsic, cmpType, simdSize); + BlockRange().InsertBefore(node, cmp); + LowerNode(cmp); + + GenTree* msk = comp->gtNewSimdHWIntrinsicNode(TYP_INT, cmp, mskIntrinsic, mskType, simdSize); + BlockRange().InsertAfter(cmp, msk); + LowerNode(msk); + + GenTree* mskCns = comp->gtNewIconNode(mskConstant, TYP_INT); + BlockRange().InsertAfter(msk, mskCns); + + if ((baseType == TYP_FLOAT) && (simdSize < 16)) + { + // For TYP_SIMD8 and TYP_SIMD12 we need to clear the upper bits and can't assume their value + + GenTree* tmp = comp->gtNewOperNode(GT_AND, TYP_INT, msk, mskCns); + BlockRange().InsertAfter(mskCns, tmp); + LowerNode(msk); + + msk = tmp; + + mskCns = comp->gtNewIconNode(mskConstant, TYP_INT); + BlockRange().InsertAfter(msk, mskCns); + } + + node->ChangeOper(cmpOp); + + node->gtType = TYP_INT; + node->gtOp1 = msk; + node->gtOp2 = mskCns; + + GenTree* cc = LowerNodeCC(node, cmpCnd); + + node->gtType = TYP_VOID; + node->ClearUnusedValue(); + + LowerNode(node); +} + +//---------------------------------------------------------------------------------------------- +// Lowering::LowerHWIntrinsicCreate: Lowers a Vector128 or Vector256 Create call +// +// Arguments: +// node - The hardware intrinsic node. +// +void Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) +{ + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + var_types simdType = node->gtType; + var_types baseType = node->gtSIMDBaseType; + unsigned simdSize = node->gtSIMDSize; + VectorConstant vecCns = {}; + + assert(varTypeIsSIMD(simdType)); + assert(varTypeIsArithmetic(baseType)); + assert(simdSize != 0); + + GenTreeArgList* argList = nullptr; + GenTree* op1 = node->gtGetOp1(); + GenTree* op2 = node->gtGetOp2(); + + // Spare GenTrees to be used for the lowering logic below + // Defined upfront to avoid naming conflicts, etc... + GenTree* idx = nullptr; + GenTree* tmp1 = nullptr; + GenTree* tmp2 = nullptr; + GenTree* tmp3 = nullptr; + + assert(op1 != nullptr); + + unsigned argCnt = 0; + unsigned cnsArgCnt = 0; + + if (op1->OperIsList()) + { + assert(op2 == nullptr); + + for (argList = op1->AsArgList(); argList != nullptr; argList = argList->Rest()) + { + if (HandleArgForHWIntrinsicCreate(argList->Current(), argCnt, vecCns, baseType)) + { + cnsArgCnt += 1; + } + argCnt += 1; + } + } + else + { + if (HandleArgForHWIntrinsicCreate(op1, argCnt, vecCns, baseType)) + { + cnsArgCnt += 1; + } + argCnt += 1; + + if (op2 != nullptr) + { + if (HandleArgForHWIntrinsicCreate(op2, argCnt, vecCns, baseType)) + { + cnsArgCnt += 1; + } + argCnt += 1; + } + else if (cnsArgCnt == 1) + { + // These intrinsics are meant to set the same value to every element + // so we'll just specially handle it here and copy it into the remaining + // indices. + + for (unsigned i = 1; i < simdSize / genTypeSize(baseType); i++) + { + HandleArgForHWIntrinsicCreate(op1, i, vecCns, baseType); + } + } + } + assert((argCnt == 1) || (argCnt == (simdSize / genTypeSize(baseType)))); + + if (argCnt == cnsArgCnt) + { + if (op1->OperIsList()) + { + for (argList = op1->AsArgList(); argList != nullptr; argList = argList->Rest()) + { + BlockRange().Remove(argList->Current()); + } + } + else + { + BlockRange().Remove(op1); + + if (op2 != nullptr) + { + BlockRange().Remove(op2); + } + } + + assert((simdSize == 16) || (simdSize == 32)); + + UNATIVE_OFFSET cnsSize = simdSize; + UNATIVE_OFFSET cnsAlign = (comp->compCodeOpt() != Compiler::SMALL_CODE) ? cnsSize : 1; + + CORINFO_FIELD_HANDLE hnd = comp->GetEmitter()->emitAnyConst(&vecCns, cnsSize, cnsAlign); + GenTree* clsVarAddr = new (comp, GT_CLS_VAR_ADDR) GenTreeClsVar(GT_CLS_VAR_ADDR, TYP_I_IMPL, hnd, nullptr); + BlockRange().InsertBefore(node, clsVarAddr); + + node->ChangeOper(GT_IND); + node->gtOp1 = clsVarAddr; + + // TODO-XARCH-CQ: We should be able to modify at least the paths that use Insert to trivially support partial + // vector constants. With this, we can create a constant if say 50% of the inputs are also constant and just + // insert the non-constant values which should still allow some gains. + + return; + } + else if (argCnt == 1) + { + // We have the following (where simd is simd16 or simd32): + // /--* op1 T + // node = * HWINTRINSIC simd T Create + + if (intrinsicId == NI_Vector256_Create) + { + if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + // We will be constructing the following parts: + // /--* op1 T + // tmp1 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* tmp1 simd16 + // node = * HWINTRINSIC simd32 T BroadcastScalarToVector256 + + // This is roughly the following managed code: + // var tmp1 = Vector128.CreateScalarUnsafe(op1); + // return Avx2.BroadcastScalarToVector256(tmp1); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(op1, tmp1); + LowerNode(tmp1); + + node->gtOp1 = tmp1; + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_AVX2_BroadcastScalarToVector256; + return; + } + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + + // We will be constructing the following parts: + // /--* op1 T + // tmp1 = * HWINTRINSIC simd16 T Create + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // /--* tmp2 simd16 + // tmp3 = * HWINTRINSIC simd16 T ToVector256Unsafe + // idx = CNS_INT int 0 + // /--* tmp3 simd32 + // +--* tmp1 simd16 + // +--* idx int + // node = * HWINTRINSIC simd32 T InsertVector128 + + // This is roughly the following managed code: + // var tmp1 = Vector128.Create(op1); + // var tmp2 = tmp1; + // var tmp3 = tmp2.ToVector256Unsafe(); + // return Avx.InsertVector128(tmp3, tmp1, 0x01); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_Vector128_Create, baseType, 16); + BlockRange().InsertAfter(op1, tmp1); + LowerNode(tmp1); + + node->gtOp1 = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->gtOp1; + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + tmp3 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD32, tmp2, NI_Vector128_ToVector256Unsafe, baseType, 16); + BlockRange().InsertAfter(tmp2, tmp3); + LowerNode(tmp3); + + idx = comp->gtNewIconNode(0x01, TYP_INT); + BlockRange().InsertAfter(tmp3, idx); + + node->gtOp1 = comp->gtNewArgList(tmp3, tmp1, idx); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_AVX_InsertVector128; + return; + } + + // We will be constructing the following parts: + // /--* op1 T + // tmp1 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // ... + + // This is roughly the following managed code: + // var tmp1 = Vector128.CreateScalarUnsafe(op1); + // ... + + tmp1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(op1, tmp1); + LowerNode(tmp1); + + if ((baseType != TYP_DOUBLE) && comp->compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // node = * HWINTRINSIC simd16 T BroadcastScalarToVector128 + + // This is roughly the following managed code: + // ... + // return Avx2.BroadcastScalarToVector128(tmp1); + + node->gtOp1 = tmp1; + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_AVX2_BroadcastScalarToVector128; + return; + } + + switch (baseType) + { + case TYP_BYTE: + case TYP_UBYTE: + { + if (comp->compOpportunisticallyDependsOn(InstructionSet_SSSE3)) + { + // We will be constructing the following parts: + // ... + // tmp2 = HWINTRINSIC simd16 ubyte get_Zero + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 ubyte Shuffle + + // This is roughly the following managed code: + // ... + // var tmp2 = Vector128.Zero; + // return Ssse3.Shuffle(tmp1, tmp2); + + tmp2 = comp->gtNewSimdHWIntrinsicNode(simdType, NI_Vector128_get_Zero, TYP_UBYTE, simdSize); + BlockRange().InsertAfter(tmp1, tmp2); + LowerNode(tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSSE3_Shuffle; + break; + } + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // tmp1 = * HWINTRINSIC simd16 ubyte UnpackLow + // ... + + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // tmp1 = Sse2.UnpackLow(tmp1, tmp2); + // ... + + node->gtOp1 = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->gtOp1; + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_SSE2_UnpackLow, TYP_UBYTE, simdSize); + BlockRange().InsertAfter(tmp2, tmp1); + LowerNode(tmp1); + + __fallthrough; + } + + case TYP_SHORT: + case TYP_USHORT: + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // tmp1 = * HWINTRINSIC simd16 ushort UnpackLow + // ... + + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // tmp1 = Sse2.UnpackLow(tmp1, tmp2); + // ... + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + node->gtOp1 = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->gtOp1; + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_SSE2_UnpackLow, TYP_USHORT, simdSize); + BlockRange().InsertAfter(tmp2, tmp1); + LowerNode(tmp1); + + __fallthrough; + } + + case TYP_INT: + case TYP_UINT: + { + // We will be constructing the following parts: + // ... + // idx = CNS_INT int 0 + // /--* tmp1 simd16 + // +--* idx int + // node = * HWINTRINSIC simd16 uint Shuffle + + // This is roughly the following managed code: + // ... + // return Sse2.Shuffle(tmp1, 0x00); + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + idx = comp->gtNewIconNode(0x00, TYP_INT); + BlockRange().InsertAfter(tmp1, idx); + + node->gtOp1 = tmp1; + node->gtOp2 = idx; + + node->gtHWIntrinsicId = NI_SSE2_Shuffle; + node->gtSIMDBaseType = TYP_UINT; + + break; + } + +#if defined(TARGET_AMD64) + case TYP_LONG: + case TYP_ULONG: + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 ulong UnpackLow + + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // return Sse2.UnpackLow(tmp1, tmp2); + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + node->gtOp1 = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->gtOp1; + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSE2_UnpackLow; + break; + } +#endif // TARGET_AMD64 + + case TYP_FLOAT: + { + if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX)) + { + // We will be constructing the following parts: + // ... + // idx = CNS_INT int 0 + // /--* tmp1 simd16 + // +--* idx int + // node = * HWINTRINSIC simd16 float Permute + + // This is roughly the following managed code: + // ... + // return Avx.Permute(tmp1, 0x00); + + idx = comp->gtNewIconNode(0x00, TYP_INT); + BlockRange().InsertAfter(tmp1, idx); + + node->gtOp1 = tmp1; + node->gtOp2 = idx; + + node->gtHWIntrinsicId = NI_AVX_Permute; + break; + } + + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // idx = CNS_INT int 0 + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // +--* idx int + // node = * HWINTRINSIC simd16 float Shuffle + + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // return Sse.Shuffle(tmp1, tmp2, 0x00); + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE)); + + node->gtOp1 = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->gtOp1; + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + idx = comp->gtNewIconNode(0x00, TYP_INT); + BlockRange().InsertAfter(tmp2, idx); + + node->gtOp1 = comp->gtNewArgList(tmp1, tmp2, idx); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_SSE_Shuffle; + break; + } + + case TYP_DOUBLE: + { + if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE3)) + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // node = * HWINTRINSIC simd16 double MoveAndDuplicate + + // This is roughly the following managed code: + // ... + // return Sse3.MoveAndDuplicate(tmp1); + + node->gtOp1 = tmp1; + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_SSE3_MoveAndDuplicate; + break; + } + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // * STORE_LCL_VAR simd16 + // tmp1 = LCL_VAR simd16 + // tmp2 = LCL_VAR simd16 + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 float MoveLowToHigh + + // This is roughly the following managed code: + // ... + // var tmp2 = tmp1; + // return Sse.MoveLowToHigh(tmp1, tmp2); + + node->gtOp1 = tmp1; + LIR::Use tmp1Use(BlockRange(), &node->gtOp1, node); + ReplaceWithLclVar(tmp1Use); + tmp1 = node->gtOp1; + + tmp2 = comp->gtClone(tmp1); + BlockRange().InsertAfter(tmp1, tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSE_MoveLowToHigh; + node->gtSIMDBaseType = TYP_FLOAT; + + break; + } + + default: + { + unreached(); + } + } + + return; + } + + // We have the following (where simd is simd16 or simd32): + // /--* op1 T + // +--* ... T + // +--* opN T + // node = * HWINTRINSIC simd T Create + + if (intrinsicId == NI_Vector256_Create) + { + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + + // We will be constructing the following parts: + // /--* op1 T + // +--* ... T + // lo = * HWINTRINSIC simd16 T Create + // /--* ... T + // +--* opN T + // hi = * HWINTRINSIC simd16 T Create + // idx = CNS_INT int 1 + // /--* lo simd32 + // +--* hi simd16 + // +--* idx int + // node = * HWINTRINSIC simd32 T InsertVector128 + + // This is roughly the following managed code: + // ... + // var lo = Vector128.Create(op1, ...); + // var hi = Vector128.Create(..., opN); + // return Avx.InsertVector128(lo, hi, 0x01); + + // Each Vector128.Create call gets half the operands. That is: + // lo = Vector128.Create(op1, op2); + // hi = Vector128.Create(op3, op4); + // -or- + // lo = Vector128.Create(op1, ..., op3); + // hi = Vector128.Create(op4, ..., op7); + // -or- + // lo = Vector128.Create(op1, ..., op7); + // hi = Vector128.Create(op8, ..., op15); + // -or- + // lo = Vector128.Create(op1, ..., op15); + // hi = Vector128.Create(op16, ..., op31); + + unsigned halfArgCnt = argCnt / 2; + assert((halfArgCnt * 2) == argCnt); + + argList = op1->AsArgList(); + + for (unsigned i = 0; i < halfArgCnt; i++) + { + op2 = argList; + argList = argList->Rest(); + } + + op2->AsArgList()->gtOp2 = nullptr; + op2 = argList; + + // The above for loop splits the operand count into exactly half. + // Once it exits, op1 will point to op1 and op2 will point to the + // last operand that will be passed to the first Vector128.Create + // We will set its op2 to null, terminating the chain and then + // assign op2 to be argList, which is the first operand that will + // get passed to the second Vector128.Create + + GenTree* lo = nullptr; + GenTree* hi = nullptr; + + if (halfArgCnt == 2) + { + // The Vector256.Create calls that take 4 operands are special + // because the half argument count is 2, which means we can't + // actually use the GT_LIST anymore and need to pass them as + // explicit operands instead. + + argList = op1->AsArgList(); + + tmp1 = argList->Current(); + tmp2 = argList->Rest()->Current(); + + lo = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, tmp1, tmp2, NI_Vector128_Create, baseType, 16); + BlockRange().InsertAfter(tmp2, lo); + LowerNode(lo); + + argList = op2->AsArgList(); + + tmp1 = argList->Current(); + tmp2 = argList->Rest()->Current(); + + hi = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, tmp1, tmp2, NI_Vector128_Create, baseType, 16); + BlockRange().InsertAfter(tmp2, hi); + LowerNode(hi); + } + else + { + // The rest of the Vector256.Create calls take at least 8 operands + // and so the half count is at least 4 and we have to continue + // passing around GT_LIST nodes in op1 with a null op2 + assert(halfArgCnt >= 4); + + tmp1 = op2->AsArgList()->Current(); + + lo = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_Vector128_Create, baseType, 16); + BlockRange().InsertBefore(tmp1, lo); + LowerNode(lo); + + hi = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, NI_Vector128_Create, baseType, 16); + BlockRange().InsertBefore(node, hi); + LowerNode(hi); + } + + idx = comp->gtNewIconNode(0x01, TYP_INT); + BlockRange().InsertAfter(hi, idx); + + node->gtOp1 = comp->gtNewArgList(lo, hi, idx); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_AVX_InsertVector128; + return; + } + + if (op1->OperIsList()) + { + argList = op1->AsArgList(); + op1 = argList->Current(); + argList = argList->Rest(); + } + + // We will be constructing the following parts: + // /--* op1 T + // tmp1 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // ... + + // This is roughly the following managed code: + // var tmp1 = Vector128.CreateScalarUnsafe(op1); + // ... + + tmp1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(op1, tmp1); + LowerNode(tmp1); + + switch (baseType) + { + case TYP_BYTE: + case TYP_UBYTE: + case TYP_SHORT: + case TYP_USHORT: + case TYP_INT: + case TYP_UINT: + { + unsigned N = 0; + GenTree* opN = nullptr; + NamedIntrinsic insIntrinsic = NI_Illegal; + + if ((baseType == TYP_SHORT) || (baseType == TYP_USHORT)) + { + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + insIntrinsic = NI_SSE2_Insert; + } + else if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + insIntrinsic = NI_SSE41_Insert; + } + + if (insIntrinsic != NI_Illegal) + { + for (N = 1; N < argCnt - 1; N++) + { + // We will be constructing the following parts: + // ... + // idx = CNS_INT int N + // /--* tmp1 simd16 + // +--* opN T + // +--* idx int + // tmp1 = * HWINTRINSIC simd16 T Insert + // ... + + // This is roughly the following managed code: + // ... + // tmp1 = Sse?.Insert(tmp1, opN, N); + // ... + + opN = argList->Current(); + + idx = comp->gtNewIconNode(N, TYP_INT); + BlockRange().InsertAfter(opN, idx); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, opN, idx, insIntrinsic, baseType, simdSize); + BlockRange().InsertAfter(idx, tmp1); + LowerNode(tmp1); + + argList = argList->Rest(); + } + + assert(N == (argCnt - 1)); + + // We will be constructing the following parts: + // idx = CNS_INT int N + // /--* tmp1 simd16 + // +--* opN T + // +--* idx int + // node = * HWINTRINSIC simd16 T Insert + + // This is roughly the following managed code: + // ... + // tmp1 = Sse?.Insert(tmp1, opN, N); + // ... + + opN = argList->Current(); + + idx = comp->gtNewIconNode(N, TYP_INT); + BlockRange().InsertAfter(opN, idx); + + node->gtOp1 = comp->gtNewArgList(tmp1, opN, idx); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = insIntrinsic; + break; + } + + assert((baseType != TYP_SHORT) && (baseType != TYP_USHORT)); + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + GenTree* op[16]; + op[0] = tmp1; + + for (N = 1; N < argCnt; N++) + { + opN = argList->Current(); + + op[N] = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, opN, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(opN, op[N]); + LowerNode(op[N]); + + argList = argList->Rest(); + } + assert(argList == nullptr); + + if ((baseType == TYP_BYTE) || (baseType == TYP_UBYTE)) + { + for (N = 0; N < argCnt; N += 4) + { + // We will be constructing the following parts: + // ... + // /--* opN T + // opN = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opO T + // opO = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opN simd16 + // +--* opO simd16 + // tmp1 = * HWINTRINSIC simd16 T UnpackLow + // /--* opP T + // opP = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opQ T + // opQ = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opP simd16 + // +--* opQ simd16 + // tmp2 = * HWINTRINSIC simd16 T UnpackLow + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // tmp3 = * HWINTRINSIC simd16 T UnpackLow + // ... + + // This is roughly the following managed code: + // ... + // tmp1 = Sse2.UnpackLow(opN, opO); + // tmp2 = Sse2.UnpackLow(opP, opQ); + // tmp3 = Sse2.UnpackLow(tmp1, tmp2); + // ... + + unsigned O = N + 1; + unsigned P = N + 2; + unsigned Q = N + 3; + + tmp1 = + comp->gtNewSimdHWIntrinsicNode(simdType, op[N], op[O], NI_SSE2_UnpackLow, TYP_UBYTE, simdSize); + BlockRange().InsertAfter(op[O], tmp1); + LowerNode(tmp1); + + tmp2 = + comp->gtNewSimdHWIntrinsicNode(simdType, op[P], op[Q], NI_SSE2_UnpackLow, TYP_UBYTE, simdSize); + BlockRange().InsertAfter(op[Q], tmp2); + LowerNode(tmp2); + + tmp3 = + comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_SSE2_UnpackLow, TYP_USHORT, simdSize); + BlockRange().InsertAfter(tmp2, tmp3); + LowerNode(tmp3); + + // This caches the result in index 0 through 3, depending on which + // loop iteration this is and allows the rest of the logic to be + // shared with the TYP_INT and TYP_UINT path. + + op[N / 4] = tmp3; + } + } + + // We will be constructing the following parts: + // ... + // /--* opN T + // opN = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opO T + // opO = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opN simd16 + // +--* opO simd16 + // tmp1 = * HWINTRINSIC simd16 T UnpackLow + // /--* opP T + // opP = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opQ T + // opQ = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opP simd16 + // +--* opQ simd16 + // tmp2 = * HWINTRINSIC simd16 T UnpackLow + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 T UnpackLow + + // This is roughly the following managed code: + // ... + // tmp1 = Sse2.UnpackLow(opN, opO); + // tmp2 = Sse2.UnpackLow(opP, opQ); + // return Sse2.UnpackLow(tmp1, tmp2); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, op[0], op[1], NI_SSE2_UnpackLow, TYP_UINT, simdSize); + BlockRange().InsertAfter(op[1], tmp1); + LowerNode(tmp1); + + tmp2 = comp->gtNewSimdHWIntrinsicNode(simdType, op[2], op[3], NI_SSE2_UnpackLow, TYP_UINT, simdSize); + BlockRange().InsertAfter(op[3], tmp2); + LowerNode(tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSE2_UnpackLow; + node->gtSIMDBaseType = TYP_ULONG; + break; + } + +#if defined(TARGET_AMD64) + case TYP_LONG: + case TYP_ULONG: + { + if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41_X64)) + { + // We will be constructing the following parts: + // ... + // idx = CNS_INT int 1 + // /--* tmp1 simd16 + // +--* op2 T + // +--* idx int + // node = * HWINTRINSIC simd16 T Insert + + // This is roughly the following managed code: + // ... + // return Sse41.X64.Insert(tmp1, op2, 0x01); + + idx = comp->gtNewIconNode(0x01, TYP_INT); + BlockRange().InsertAfter(op2, idx); + + node->gtOp1 = comp->gtNewArgList(tmp1, op2, idx); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_SSE41_X64_Insert; + break; + } + + // We will be constructing the following parts: + // ... + // /--* op2 T + // tmp2 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 T UnpackLow + + // This is roughly the following managed code: + // ... + // var tmp2 = Vector128.CreateScalarUnsafe(op2); + // return Sse2.UnpackLow(tmp1, tmp2); + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + tmp2 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(op2, tmp2); + LowerNode(tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSE2_UnpackLow; + break; + } +#endif // TARGET_AMD64 + + case TYP_FLOAT: + { + unsigned N = 0; + GenTree* opN = nullptr; + + if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + { + for (N = 1; N < argCnt - 1; N++) + { + // We will be constructing the following parts: + // ... + // + // /--* opN T + // tmp2 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // idx = CNS_INT int N + // /--* tmp1 simd16 + // +--* opN T + // +--* idx int + // tmp1 = * HWINTRINSIC simd16 T Insert + // ... + + // This is roughly the following managed code: + // ... + // tmp2 = Vector128.CreateScalarUnsafe(opN); + // tmp1 = Sse41.Insert(tmp1, tmp2, N << 4); + // ... + + opN = argList->Current(); + + tmp2 = + comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, opN, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(opN, tmp2); + LowerNode(tmp2); + + idx = comp->gtNewIconNode(N << 4, TYP_INT); + BlockRange().InsertAfter(tmp2, idx); + + tmp1 = + comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, idx, NI_SSE41_Insert, baseType, simdSize); + BlockRange().InsertAfter(idx, tmp1); + LowerNode(tmp1); + + argList = argList->Rest(); + } + + // We will be constructing the following parts: + // ... + // + // /--* opN T + // tmp2 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // idx = CNS_INT int N + // /--* tmp1 simd16 + // +--* opN T + // +--* idx int + // node = * HWINTRINSIC simd16 T Insert + + // This is roughly the following managed code: + // ... + // tmp2 = Vector128.CreateScalarUnsafe(opN); + // return Sse41.Insert(tmp1, tmp2, N << 4); + + opN = argList->Current(); + + tmp2 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, opN, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(opN, tmp2); + LowerNode(tmp2); + + idx = comp->gtNewIconNode((argCnt - 1) << 4, TYP_INT); + BlockRange().InsertAfter(tmp2, idx); + + node->gtOp1 = comp->gtNewArgList(tmp1, tmp2, idx); + node->gtOp2 = nullptr; + + node->gtHWIntrinsicId = NI_SSE41_Insert; + break; + } + + // We will be constructing the following parts: + // ... + // /--* opN T + // opN = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opO T + // opO = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opN simd16 + // +--* opO simd16 + // tmp1 = * HWINTRINSIC simd16 T UnpackLow + // /--* opP T + // opP = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opQ T + // opQ = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* opP simd16 + // +--* opQ simd16 + // tmp2 = * HWINTRINSIC simd16 T UnpackLow + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 T MoveLowToHigh + + // This is roughly the following managed code: + // ... + // tmp1 = Sse.UnpackLow(opN, opO); + // tmp2 = Sse.UnpackLow(opP, opQ); + // return Sse.MoveLowToHigh(tmp1, tmp2); + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE)); + + GenTree* op[4]; + op[0] = tmp1; + + for (N = 1; N < argCnt; N++) + { + opN = argList->Current(); + + op[N] = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, opN, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(opN, op[N]); + LowerNode(op[N]); + + argList = argList->Rest(); + } + assert(argList == nullptr); + + tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, op[0], op[1], NI_SSE_UnpackLow, baseType, simdSize); + BlockRange().InsertAfter(op[1], tmp1); + LowerNode(tmp1); + + tmp2 = comp->gtNewSimdHWIntrinsicNode(simdType, op[2], op[3], NI_SSE_UnpackLow, baseType, simdSize); + BlockRange().InsertAfter(op[3], tmp2); + LowerNode(tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSE_MoveLowToHigh; + break; + } + + case TYP_DOUBLE: + { + // We will be constructing the following parts: + // ... + // /--* op2 T + // tmp2 = * HWINTRINSIC simd16 T CreateScalarUnsafe + // /--* tmp1 simd16 + // +--* tmp2 simd16 + // node = * HWINTRINSIC simd16 T MoveLowToHigh + + // This is roughly the following managed code: + // ... + // var tmp2 = Vector128.CreateScalarUnsafe(op2); + // return Sse.MoveLowToHigh(tmp1, tmp2); + + assert(comp->compIsaSupportedDebugOnly(InstructionSet_SSE2)); + + tmp2 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, NI_Vector128_CreateScalarUnsafe, baseType, 16); + BlockRange().InsertAfter(op2, tmp2); + LowerNode(tmp2); + + node->gtOp1 = tmp1; + node->gtOp2 = tmp2; + + node->gtHWIntrinsicId = NI_SSE_MoveLowToHigh; + node->gtSIMDBaseType = TYP_FLOAT; + + break; + } + + default: + { + unreached(); + } + } +} #endif // FEATURE_HW_INTRINSICS //---------------------------------------------------------------------------------------------- @@ -1437,7 +2807,7 @@ bool Lowering::IsCallTargetInRange(void* addr) } // return true if the immediate can be folded into an instruction, for example small enough and non-relocatable -bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) +bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) const { if (!childNode->IsIntCnsFitsInI32()) { @@ -1973,7 +3343,7 @@ void Lowering::ContainCheckShiftRotate(GenTreeOp* node) // Arguments: // node - pointer to the node // -void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) +void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) const { assert(storeLoc->OperIsLocalStore()); GenTree* op1 = storeLoc->gtGetOp1(); @@ -1990,14 +3360,22 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) return; } } + + const LclVarDsc* varDsc = comp->lvaGetDesc(storeLoc); + #ifdef FEATURE_SIMD if (varTypeIsSIMD(storeLoc)) { - if (op1->IsCnsIntOrI()) + assert(!op1->IsCnsIntOrI()); + if (storeLoc->TypeIs(TYP_SIMD12) && op1->IsSIMDZero() && varDsc->lvDoNotEnregister) { - // For an InitBlk we want op1 to be contained; otherwise we want it to - // be evaluated into an xmm register. + // For a SIMD12 store we can zero from integer registers more easily. MakeSrcContained(storeLoc, op1); + GenTree* constNode = op1->gtGetOp1(); + assert(constNode->OperIsConst()); + constNode->ClearContained(); + constNode->gtType = TYP_INT; + constNode->SetOper(GT_CNS_INT); } return; } @@ -2006,8 +3384,7 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc) // If the source is a containable immediate, make it contained, unless it is // an int-size or larger store of zero to memory, because we can generate smaller code // by zeroing a register and then storing it. - const LclVarDsc* varDsc = comp->lvaGetDesc(storeLoc); - var_types type = varDsc->GetRegisterType(storeLoc); + var_types type = varDsc->GetRegisterType(storeLoc); if (IsContainableImmed(storeLoc, op1) && (!op1->IsIntegralConst(0) || varTypeIsSmall(type))) { MakeSrcContained(storeLoc, op1); @@ -2546,19 +3923,6 @@ void Lowering::ContainCheckSIMD(GenTreeSIMD* simdNode) CheckImmedAndMakeContained(simdNode, simdNode->gtGetOp2()); break; - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: - // On SSE4/AVX, we can generate optimal code for (in)equality - // against zero using ptest. We can safely do this optimization - // for integral vectors but not for floating-point for the reason - // that we have +0.0 and -0.0 and +0.0 == -0.0 - op2 = simdNode->gtGetOp2(); - if ((comp->getSIMDSupportLevel() >= SIMD_SSE4_Supported) && op2->IsIntegralConstVector(0)) - { - MakeSrcContained(simdNode, op2); - } - break; - case SIMDIntrinsicGetItem: { // This implements get_Item method. The sources are: diff --git a/src/coreclr/src/jit/lsra.cpp b/src/coreclr/src/jit/lsra.cpp index 8c9783cedad80..5101e57389295 100644 --- a/src/coreclr/src/jit/lsra.cpp +++ b/src/coreclr/src/jit/lsra.cpp @@ -1791,6 +1791,8 @@ void LinearScan::identifyCandidates() VarSetOps::AddElemD(compiler, fpMaybeCandidateVars, varDsc->lvVarIndex); } } + JITDUMP(" "); + DBEXEC(VERBOSE, newInt->dump()); } else { @@ -6282,6 +6284,26 @@ void LinearScan::updatePreviousInterval(RegRecord* reg, Interval* interval, Regi #endif } +//----------------------------------------------------------------------------- +// writeLocalReg: Write the register assignment for a GT_LCL_VAR node. +// +// Arguments: +// lclNode - The GT_LCL_VAR node +// varNum - The variable number for the register +// reg - The assigned register +// +// Return Value: +// None +// +void LinearScan::writeLocalReg(GenTreeLclVar* lclNode, unsigned varNum, regNumber reg) +{ + // We don't yet support multireg locals. + assert((lclNode->GetLclNum() == varNum) && !lclNode->IsMultiReg()); + assert(lclNode->GetLclNum() == varNum); + lclNode->SetRegNum(reg); +} + +//----------------------------------------------------------------------------- // LinearScan::resolveLocalRef // Description: // Update the graph for a local reference. @@ -6318,7 +6340,7 @@ void LinearScan::updatePreviousInterval(RegRecord* reg, Interval* interval, Regi // NICE: Consider tracking whether an Interval is always in the same location (register/stack) // in which case it will require no resolution. // -void LinearScan::resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPosition* currentRefPosition) +void LinearScan::resolveLocalRef(BasicBlock* block, GenTreeLclVar* treeNode, RefPosition* currentRefPosition) { assert((block == nullptr) == (treeNode == nullptr)); assert(enregisterLocalVars); @@ -6339,11 +6361,11 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPositi { if (currentRefPosition->lastUse) { - treeNode->gtFlags |= GTF_VAR_DEATH; + treeNode->SetLastUse(currentRefPosition->getMultiRegIdx()); } else { - treeNode->gtFlags &= ~GTF_VAR_DEATH; + treeNode->ClearLastUse(currentRefPosition->getMultiRegIdx()); } if ((currentRefPosition->registerAssignment != RBM_NONE) && (interval->physReg == REG_NA) && @@ -6354,7 +6376,7 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPositi // during resolution. In this case we're better off making it contained. assert(inVarToRegMaps[curBBNum][varDsc->lvVarIndex] == REG_STK); currentRefPosition->registerAssignment = RBM_NONE; - treeNode->SetRegNum(REG_NA); + writeLocalReg(treeNode->AsLclVar(), interval->varNum, REG_NA); } } @@ -6445,9 +6467,11 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPositi // // Note that varDsc->GetRegNum() is already to REG_STK above. interval->physReg = REG_NA; - treeNode->SetRegNum(REG_NA); + writeLocalReg(treeNode->AsLclVar(), interval->varNum, REG_NA); treeNode->gtFlags &= ~GTF_SPILLED; treeNode->SetContained(); + // We don't support RegOptional for multi-reg localvars. + assert(!treeNode->IsMultiReg()); } else { @@ -6470,7 +6494,7 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPositi interval->physReg = REG_NA; if (treeNode != nullptr) { - treeNode->SetRegNum(REG_NA); + writeLocalReg(treeNode->AsLclVar(), interval->varNum, REG_NA); } } else // Not reload and Not pure-def that's spillAfter @@ -6489,7 +6513,7 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPositi // But for copyReg, the homeReg remains unchanged. assert(treeNode != nullptr); - treeNode->SetRegNum(interval->physReg); + writeLocalReg(treeNode->AsLclVar(), interval->varNum, interval->physReg); if (currentRefPosition->copyReg) { @@ -7345,9 +7369,9 @@ void LinearScan::resolveRegisters() { writeRegisters(currentRefPosition, treeNode); - if (treeNode->IsLocal() && currentRefPosition->getInterval()->isLocalVar) + if (treeNode->OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR) && currentRefPosition->getInterval()->isLocalVar) { - resolveLocalRef(block, treeNode, currentRefPosition); + resolveLocalRef(block, treeNode->AsLclVar(), currentRefPosition); } // Mark spill locations on temps @@ -7370,7 +7394,7 @@ void LinearScan::resolveRegisters() treeNode->ResetReuseRegVal(); } - // In case of multi-reg call node, also set spill flag on the + // In case of multi-reg node, also set spill flag on the // register specified by multi-reg index of current RefPosition. // Note that the spill flag on treeNode indicates that one or // more its allocated registers are in that state. @@ -9305,7 +9329,7 @@ void Interval::dump() } if (isStructField) { - printf(" (struct)"); + printf(" (field)"); } if (isPromotedStruct) { @@ -9495,7 +9519,7 @@ void LinearScan::lsraGetOperandString(GenTree* tree, void LinearScan::lsraDispNode(GenTree* tree, LsraTupleDumpMode mode, bool hasDest) { Compiler* compiler = JitTls::GetCompiler(); - const unsigned operandStringLength = 16; + const unsigned operandStringLength = 6 * MAX_MULTIREG_COUNT + 1; char operandString[operandStringLength]; const char* emptyDestOperand = " "; char spillChar = ' '; @@ -9635,7 +9659,7 @@ void LinearScan::TupleStyleDump(LsraTupleDumpMode mode) { BasicBlock* block; LsraLocation currentLoc = 1; // 0 is the entry - const unsigned operandStringLength = 16; + const unsigned operandStringLength = 6 * MAX_MULTIREG_COUNT + 1; char operandString[operandStringLength]; // currentRefPosition is not used for LSRA_DUMP_PRE @@ -10799,6 +10823,7 @@ void LinearScan::verifyFinalAllocation() regRecord->assignedInterval = interval; if (VERBOSE) { + dumpEmptyRefPosition(); printf("Move %-4s ", getRegName(regRecord->regNum)); } } diff --git a/src/coreclr/src/jit/lsra.h b/src/coreclr/src/jit/lsra.h index bc077aad9f77b..7c4056241daca 100644 --- a/src/coreclr/src/jit/lsra.h +++ b/src/coreclr/src/jit/lsra.h @@ -965,8 +965,8 @@ class LinearScan : public LinearScanInterface #ifdef DEBUG void checkLastUses(BasicBlock* block); - static int ComputeOperandDstCount(GenTree* operand); - static int ComputeAvailableSrcCount(GenTree* node); + int ComputeOperandDstCount(GenTree* operand); + int ComputeAvailableSrcCount(GenTree* node); #endif // DEBUG void setFrameType(); @@ -1090,7 +1090,8 @@ class LinearScan : public LinearScanInterface RefPosition* buildInternalFloatRegisterDefForNode(GenTree* tree, regMaskTP internalCands = RBM_NONE); void buildInternalRegisterUses(); - void resolveLocalRef(BasicBlock* block, GenTree* treeNode, RefPosition* currentRefPosition); + void writeLocalReg(GenTreeLclVar* lclNode, unsigned varNum, regNumber reg); + void resolveLocalRef(BasicBlock* block, GenTreeLclVar* treeNode, RefPosition* currentRefPosition); void insertMove(BasicBlock* block, GenTree* insertionPoint, unsigned lclNum, regNumber inReg, regNumber outReg); @@ -1575,6 +1576,7 @@ class LinearScan : public LinearScanInterface int BuildBlockStore(GenTreeBlk* blkNode); int BuildModDiv(GenTree* tree); int BuildIntrinsic(GenTree* tree); + void BuildStoreLocDef(GenTreeLclVarCommon* storeLoc, LclVarDsc* varDsc, RefPosition* singleUseRef, int index); int BuildStoreLoc(GenTreeLclVarCommon* tree); int BuildIndir(GenTreeIndir* indirTree); int BuildGCWriteBarrier(GenTree* tree); diff --git a/src/coreclr/src/jit/lsraarm.cpp b/src/coreclr/src/jit/lsraarm.cpp index b28e295443b69..165ad929fbc05 100644 --- a/src/coreclr/src/jit/lsraarm.cpp +++ b/src/coreclr/src/jit/lsraarm.cpp @@ -219,7 +219,6 @@ int LinearScan::BuildNode(GenTree* tree) switch (tree->OperGet()) { case GT_LCL_VAR: - case GT_LCL_FLD: { // We handle tracked variables differently from non-tracked ones. If it is tracked, // we will simply add a use of the tracked variable at its parent/consumer. @@ -230,13 +229,23 @@ int LinearScan::BuildNode(GenTree* tree) // is processed, unless this is marked "isLocalDefUse" because it is a stack-based argument // to a call or an orphaned dead node. // - GenTreeLclVarCommon* const lclVar = tree->AsLclVarCommon(); - LclVarDsc* const varDsc = compiler->lvaGetDesc(lclVar); - if (isCandidateVar(varDsc)) + bool isCandidate = compiler->lvaGetDesc(tree->AsLclVar())->lvLRACandidate; + if (tree->IsRegOptional() && !isCandidate) + { + tree->ClearRegOptional(); + tree->SetContained(); + return 0; + } + if (isCandidate) { return 0; } + } + __fallthrough; + case GT_LCL_FLD: + { + GenTreeLclVarCommon* const lclVar = tree->AsLclVarCommon(); if (lclVar->OperIs(GT_LCL_FLD) && lclVar->AsLclFld()->IsOffsetMisaligned()) { buildInternalIntRegisterDefForNode(lclVar); // to generate address. diff --git a/src/coreclr/src/jit/lsraarm64.cpp b/src/coreclr/src/jit/lsraarm64.cpp index 6b7e6116e3f45..c7146d6872af0 100644 --- a/src/coreclr/src/jit/lsraarm64.cpp +++ b/src/coreclr/src/jit/lsraarm64.cpp @@ -76,7 +76,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_LCL_VAR: - case GT_LCL_FLD: { // We handle tracked variables differently from non-tracked ones. If it is tracked, // we will simply add a use of the tracked variable at its parent/consumer. @@ -87,11 +86,22 @@ int LinearScan::BuildNode(GenTree* tree) // is processed, unless this is marked "isLocalDefUse" because it is a stack-based argument // to a call or an orphaned dead node. // - LclVarDsc* const varDsc = &compiler->lvaTable[tree->AsLclVarCommon()->GetLclNum()]; - if (isCandidateVar(varDsc)) + bool isCandidate = compiler->lvaGetDesc(tree->AsLclVar())->lvLRACandidate; + if (tree->IsRegOptional() && !isCandidate) { + tree->ClearRegOptional(); + tree->SetContained(); return 0; } + if (isCandidate) + { + return 0; + } + } + __fallthrough; + + case GT_LCL_FLD: + { srcCount = 0; #ifdef FEATURE_SIMD // Need an additional register to read upper 4 bytes of Vector3. @@ -802,16 +812,12 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) { case SIMDIntrinsicInit: case SIMDIntrinsicCast: - case SIMDIntrinsicSqrt: - case SIMDIntrinsicAbs: case SIMDIntrinsicConvertToSingle: case SIMDIntrinsicConvertToInt32: case SIMDIntrinsicConvertToDouble: case SIMDIntrinsicConvertToInt64: case SIMDIntrinsicWidenLo: case SIMDIntrinsicWidenHi: - case SIMDIntrinsicCeil: - case SIMDIntrinsicFloor: // No special handling required. break; @@ -858,16 +864,8 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) case SIMDIntrinsicMul: case SIMDIntrinsicDiv: case SIMDIntrinsicBitwiseAnd: - case SIMDIntrinsicBitwiseAndNot: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: - case SIMDIntrinsicMin: - case SIMDIntrinsicMax: case SIMDIntrinsicEqual: - case SIMDIntrinsicLessThan: - case SIMDIntrinsicGreaterThan: - case SIMDIntrinsicLessThanOrEqual: - case SIMDIntrinsicGreaterThanOrEqual: // No special handling required. break; @@ -916,23 +914,10 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) // We have an array and an index, which may be contained. break; - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: - buildInternalFloatRegisterDefForNode(simdTree); - break; - case SIMDIntrinsicDotProduct: buildInternalFloatRegisterDefForNode(simdTree); break; - case SIMDIntrinsicSelect: - // TODO-ARM64-CQ Allow lowering to see SIMDIntrinsicSelect so we can generate BSL VC, VA, VB - // bsl target register must be VC. Reserve a temp in case we need to shuffle things. - // This will require a different approach, as GenTreeSIMD has only two operands. - assert(!"SIMDIntrinsicSelect not yet supported"); - buildInternalFloatRegisterDefForNode(simdTree); - break; - case SIMDIntrinsicInitArrayX: case SIMDIntrinsicInitFixed: case SIMDIntrinsicCopyToArray: @@ -946,7 +931,6 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) case SIMDIntrinsicGetY: case SIMDIntrinsicGetZ: case SIMDIntrinsicGetW: - case SIMDIntrinsicInstEquals: case SIMDIntrinsicHWAccel: case SIMDIntrinsicWiden: case SIMDIntrinsicInvalid: @@ -1001,13 +985,22 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) int srcCount = 0; int dstCount = intrinsicTree->IsValue() ? 1 : 0; - // We may need to allocate an additional general-purpose register when an intrinsic has a non-const immediate - // operand and the intrinsic does not have an alternative non-const fallback form. - // However, for a case when the operand can take only two possible values - zero and one - // the codegen will use cbnz to do conditional branch. - bool mayNeedBranchTargetReg = (intrin.category == HW_Category_IMM) && !HWIntrinsicInfo::NoJmpTableImm(intrin.id) && - (HWIntrinsicInfo::lookupImmUpperBound(intrin.id, intrinsicTree->gtSIMDSize, - intrinsicTree->gtSIMDBaseType) != 2); + bool mayNeedBranchTargetReg = false; + + if ((intrin.category == HW_Category_IMM) && !HWIntrinsicInfo::NoJmpTableImm(intrin.id)) + { + // We may need to allocate an additional general-purpose register when an intrinsic has a non-const immediate + // operand and the intrinsic does not have an alternative non-const fallback form. + // However, for a case when the operand can take only two possible values - zero and one + // the codegen will use cbnz to do conditional branch. + + int immLowerBound = 0; + int immUpperBound = 0; + + HWIntrinsicInfo::lookupImmBounds(intrin.id, intrinsicTree->gtSIMDSize, intrinsicTree->gtSIMDBaseType, + &immLowerBound, &immUpperBound); + mayNeedBranchTargetReg = (immLowerBound != 0) || (immUpperBound != 1); + } if (mayNeedBranchTargetReg) { @@ -1015,13 +1008,64 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) switch (intrin.id) { + case NI_AdvSimd_DuplicateSelectedScalarToVector64: + case NI_AdvSimd_DuplicateSelectedScalarToVector128: case NI_AdvSimd_Extract: case NI_AdvSimd_Insert: + case NI_AdvSimd_ShiftLeftLogical: + case NI_AdvSimd_ShiftLeftLogicalSaturate: + case NI_AdvSimd_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsigned: + case NI_AdvSimd_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_ShiftLeftLogicalScalar: + case NI_AdvSimd_ShiftLeftLogicalWideningLower: + case NI_AdvSimd_ShiftLeftLogicalWideningUpper: + case NI_AdvSimd_ShiftRightArithmetic: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticRounded: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower: + case NI_AdvSimd_ShiftRightArithmeticRoundedScalar: + case NI_AdvSimd_ShiftRightArithmeticScalar: + case NI_AdvSimd_ShiftRightLogical: + case NI_AdvSimd_ShiftRightLogicalNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalRounded: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingLower: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateLower: + case NI_AdvSimd_ShiftRightLogicalRoundedScalar: + case NI_AdvSimd_ShiftRightLogicalScalar: + case NI_AdvSimd_Arm64_DuplicateSelectedScalarToVector128: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateScalar: + case NI_AdvSimd_Arm64_ShiftLeftLogicalSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalNarrowingSaturateScalar: + case NI_AdvSimd_Arm64_ShiftRightLogicalRoundedNarrowingSaturateScalar: needBranchTargetReg = !intrin.op2->isContainedIntOrIImmed(); break; case NI_AdvSimd_ExtractVector64: case NI_AdvSimd_ExtractVector128: + case NI_AdvSimd_ShiftRightArithmeticAdd: + case NI_AdvSimd_ShiftRightArithmeticAddScalar: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedAdd: + case NI_AdvSimd_ShiftRightArithmeticRoundedAddScalar: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper: + case NI_AdvSimd_ShiftRightArithmeticRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalAdd: + case NI_AdvSimd_ShiftRightLogicalAddScalar: + case NI_AdvSimd_ShiftRightLogicalNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalNarrowingUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedAdd: + case NI_AdvSimd_ShiftRightLogicalRoundedAddScalar: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingSaturateUpper: + case NI_AdvSimd_ShiftRightLogicalRoundedNarrowingUpper: needBranchTargetReg = !intrin.op3->isContainedIntOrIImmed(); break; diff --git a/src/coreclr/src/jit/lsraarmarch.cpp b/src/coreclr/src/jit/lsraarmarch.cpp index fab94aaf11252..64d18bf6d80bd 100644 --- a/src/coreclr/src/jit/lsraarmarch.cpp +++ b/src/coreclr/src/jit/lsraarmarch.cpp @@ -74,23 +74,32 @@ int LinearScan::BuildIndir(GenTreeIndir* indirTree) if (addr->isContained()) { - assert(addr->OperGet() == GT_LEA); - GenTreeAddrMode* lea = addr->AsAddrMode(); - index = lea->Index(); - cns = lea->Offset(); - - // On ARM we may need a single internal register - // (when both conditions are true then we still only need a single internal register) - if ((index != nullptr) && (cns != 0)) + if (addr->OperGet() == GT_LEA) { - // ARM does not support both Index and offset so we need an internal register - buildInternalIntRegisterDefForNode(indirTree); + GenTreeAddrMode* lea = addr->AsAddrMode(); + index = lea->Index(); + cns = lea->Offset(); + + // On ARM we may need a single internal register + // (when both conditions are true then we still only need a single internal register) + if ((index != nullptr) && (cns != 0)) + { + // ARM does not support both Index and offset so we need an internal register + buildInternalIntRegisterDefForNode(indirTree); + } + else if (!emitter::emitIns_valid_imm_for_ldst_offset(cns, emitTypeSize(indirTree))) + { + // This offset can't be contained in the ldr/str instruction, so we need an internal register + buildInternalIntRegisterDefForNode(indirTree); + } } - else if (!emitter::emitIns_valid_imm_for_ldst_offset(cns, emitTypeSize(indirTree))) +#ifdef TARGET_ARM64 + else if (addr->OperGet() == GT_CLS_VAR_ADDR) { - // This offset can't be contained in the ldr/str instruction, so we need an internal register + // Reserve int to load constant from memory (IF_LARGELDC) buildInternalIntRegisterDefForNode(indirTree); } +#endif // TARGET_ARM64 } #ifdef FEATURE_SIMD @@ -126,9 +135,9 @@ int LinearScan::BuildIndir(GenTreeIndir* indirTree) // int LinearScan::BuildCall(GenTreeCall* call) { - bool hasMultiRegRetVal = false; - ReturnTypeDesc* retTypeDesc = nullptr; - regMaskTP dstCandidates = RBM_NONE; + bool hasMultiRegRetVal = false; + const ReturnTypeDesc* retTypeDesc = nullptr; + regMaskTP dstCandidates = RBM_NONE; int srcCount = 0; int dstCount = 0; @@ -173,6 +182,12 @@ int LinearScan::BuildCall(GenTreeCall* call) ctrlExprCandidates = RBM_FASTTAILCALL_TARGET; } } +#if defined(FEATURE_READYTORUN_COMPILER) && defined(TARGET_ARMARCH) + else if (call->IsR2RRelativeIndir()) + { + buildInternalIntRegisterDefForNode(call); + } +#endif // FEATURE_READYTORUN_COMPILER && TARGET_ARMARCH #ifdef TARGET_ARM else { diff --git a/src/coreclr/src/jit/lsrabuild.cpp b/src/coreclr/src/jit/lsrabuild.cpp index 7a41dd28e713a..c1a5e0b586b40 100644 --- a/src/coreclr/src/jit/lsrabuild.cpp +++ b/src/coreclr/src/jit/lsrabuild.cpp @@ -1507,8 +1507,7 @@ int LinearScan::ComputeOperandDstCount(GenTree* operand) // Stores and void-typed operands may be encountered when processing call nodes, which contain // pointers to argument setup stores. assert(operand->OperIsStore() || operand->OperIsBlkOp() || operand->OperIsPutArgStk() || - operand->OperIsCompare() || operand->OperIs(GT_CMP) || operand->IsSIMDEqualityOrInequality() || - operand->TypeGet() == TYP_VOID); + operand->OperIsCompare() || operand->OperIs(GT_CMP) || operand->TypeGet() == TYP_VOID); return 0; } } @@ -2699,7 +2698,7 @@ void LinearScan::BuildDefs(GenTree* tree, int dstCount, regMaskTP dstCandidates) { fixedReg = true; } - ReturnTypeDesc* retTypeDesc = nullptr; + const ReturnTypeDesc* retTypeDesc = nullptr; if (tree->IsMultiRegCall()) { retTypeDesc = tree->AsCall()->GetReturnTypeDesc(); @@ -3074,9 +3073,9 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc) assert(storeLoc->OperGet() == GT_STORE_LCL_VAR); // srcCount = number of registers in which the value is returned by call - GenTreeCall* call = op1->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - srcCount = retTypeDesc->GetReturnRegCount(); + const GenTreeCall* call = op1->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + srcCount = retTypeDesc->GetReturnRegCount(); for (int i = 0; i < srcCount; ++i) { @@ -3113,7 +3112,20 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc) #endif // !TARGET_64BIT else if (op1->isContained()) { - srcCount = 0; +#ifdef TARGET_XARCH + if (varTypeIsSIMD(storeLoc)) + { + // This is the zero-init case, and we need a register to hold the zero. + // (On Arm64 we can just store REG_ZR.) + assert(op1->IsSIMDZero()); + singleUseRef = BuildUse(op1->gtGetOp1()); + srcCount = 1; + } + else +#endif + { + srcCount = 0; + } } else { @@ -3271,9 +3283,9 @@ int LinearScan::BuildReturn(GenTree* tree) { noway_assert(op1->IsMultiRegCall()); - ReturnTypeDesc* retTypeDesc = op1->AsCall()->GetReturnTypeDesc(); - int srcCount = retTypeDesc->GetReturnRegCount(); - useCandidates = retTypeDesc->GetABIReturnRegs(); + const ReturnTypeDesc* retTypeDesc = op1->AsCall()->GetReturnTypeDesc(); + const int srcCount = retTypeDesc->GetReturnRegCount(); + useCandidates = retTypeDesc->GetABIReturnRegs(); for (int i = 0; i < srcCount; i++) { BuildUse(op1, useCandidates, i); diff --git a/src/coreclr/src/jit/lsraxarch.cpp b/src/coreclr/src/jit/lsraxarch.cpp index f784b55453871..1239ca23c7bbe 100644 --- a/src/coreclr/src/jit/lsraxarch.cpp +++ b/src/coreclr/src/jit/lsraxarch.cpp @@ -83,26 +83,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_LCL_VAR: - // Because we do containment analysis before we redo dataflow and identify register - // candidates, the containment analysis only uses !lvDoNotEnregister to estimate register - // candidates. - // If there is a lclVar that is estimated to be register candidate but - // is not, if they were marked regOptional they should now be marked contained instead. - // TODO-XArch-CQ: When this is being called while RefPositions are being created, - // use lvLRACandidate here instead. - if (tree->IsRegOptional()) - { - if (!compiler->lvaTable[tree->AsLclVarCommon()->GetLclNum()].lvTracked || - compiler->lvaTable[tree->AsLclVarCommon()->GetLclNum()].lvDoNotEnregister) - { - tree->ClearRegOptional(); - tree->SetContained(); - return 0; - } - } - __fallthrough; - - case GT_LCL_FLD: { // We handle tracked variables differently from non-tracked ones. If it is tracked, // we will simply add a use of the tracked variable at its parent/consumer. @@ -113,11 +93,27 @@ int LinearScan::BuildNode(GenTree* tree) // is processed, unless this is marked "isLocalDefUse" because it is a stack-based argument // to a call or an orphaned dead node. // - LclVarDsc* const varDsc = &compiler->lvaTable[tree->AsLclVarCommon()->GetLclNum()]; - if (isCandidateVar(varDsc)) + // Because we do containment analysis before we redo dataflow and identify register + // candidates, the containment analysis only uses !lvDoNotEnregister to estimate register + // candidates. + // If there is a lclVar that is estimated to be register candidate but + // is not, if they were marked regOptional they should now be marked contained instead. + bool isCandidate = compiler->lvaGetDesc(tree->AsLclVar())->lvLRACandidate; + if (tree->IsRegOptional() && !isCandidate) + { + tree->ClearRegOptional(); + tree->SetContained(); + return 0; + } + if (isCandidate) { return 0; } + } + __fallthrough; + + case GT_LCL_FLD: + { srcCount = 0; #ifdef FEATURE_SIMD // Need an additional register to read upper 4 bytes of Vector3. @@ -1033,11 +1029,11 @@ int LinearScan::BuildShiftRotate(GenTree* tree) // int LinearScan::BuildCall(GenTreeCall* call) { - bool hasMultiRegRetVal = false; - ReturnTypeDesc* retTypeDesc = nullptr; - int srcCount = 0; - int dstCount = 0; - regMaskTP dstCandidates = RBM_NONE; + bool hasMultiRegRetVal = false; + const ReturnTypeDesc* retTypeDesc = nullptr; + int srcCount = 0; + int dstCount = 0; + regMaskTP dstCandidates = RBM_NONE; assert(!call->isContained()); if (call->TypeGet() != TYP_VOID) @@ -1866,21 +1862,17 @@ int LinearScan::BuildIntrinsic(GenTree* tree) // int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) { - // Only SIMDIntrinsicInit can be contained. Other than that, - // only SIMDIntrinsicOpEquality and SIMDIntrinsicOpInEquality can have 0 dstCount. - int dstCount = simdTree->IsValue() ? 1 : 0; + // All intrinsics have a dstCount of 1 + assert(simdTree->IsValue()); + bool buildUses = true; regMaskTP dstCandidates = RBM_NONE; if (simdTree->isContained()) { + // Only SIMDIntrinsicInit can be contained assert(simdTree->gtSIMDIntrinsicID == SIMDIntrinsicInit); } - else if (dstCount != 1) - { - assert((simdTree->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality) || - (simdTree->gtSIMDIntrinsicID == SIMDIntrinsicOpInEquality)); - } SetContainsAVXFlags(simdTree->gtSIMDSize); GenTree* op1 = simdTree->gtGetOp1(); GenTree* op2 = simdTree->gtGetOp2(); @@ -1960,35 +1952,11 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) noway_assert(varTypeIsFloating(simdTree->gtSIMDBaseType)); break; - case SIMDIntrinsicAbs: - // float/double vectors: This gets implemented as bitwise-And operation - // with a mask and hence should never see here. - // - // Must be a Vector or Vector Vector - assert(simdTree->gtSIMDBaseType == TYP_INT || simdTree->gtSIMDBaseType == TYP_SHORT || - simdTree->gtSIMDBaseType == TYP_BYTE); - assert(compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported); - break; - - case SIMDIntrinsicSqrt: - // SSE2 has no instruction support for sqrt on integer vectors. - noway_assert(varTypeIsFloating(simdTree->gtSIMDBaseType)); - break; - - case SIMDIntrinsicCeil: - case SIMDIntrinsicFloor: - assert(compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported); - break; - case SIMDIntrinsicAdd: case SIMDIntrinsicSub: case SIMDIntrinsicMul: case SIMDIntrinsicBitwiseAnd: - case SIMDIntrinsicBitwiseAndNot: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: - case SIMDIntrinsicMin: - case SIMDIntrinsicMax: // SSE2 32-bit integer multiplication requires two temp regs if (simdTree->gtSIMDIntrinsicID == SIMDIntrinsicMul && simdTree->gtSIMDBaseType == TYP_INT && compiler->getSIMDSupportLevel() == SIMD_SSE2_Supported) @@ -2001,40 +1969,6 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) case SIMDIntrinsicEqual: break; - // SSE2 doesn't support < and <= directly on int vectors. - // Instead we need to use > and >= with swapped operands. - case SIMDIntrinsicLessThan: - case SIMDIntrinsicLessThanOrEqual: - noway_assert(!varTypeIsIntegral(simdTree->gtSIMDBaseType)); - break; - - // SIMDIntrinsicEqual is supported only on non-floating point base type vectors. - // SSE2 cmpps/pd doesn't support > and >= directly on float/double vectors. - // Instead we need to use < and <= with swapped operands. - case SIMDIntrinsicGreaterThan: - noway_assert(!varTypeIsFloating(simdTree->gtSIMDBaseType)); - break; - - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: - if (simdTree->gtGetOp2()->isContained()) - { - // If the second operand is contained then ContainCheckSIMD has determined - // that PTEST can be used. We only need a single source register and no - // internal registers. - } - else - { - // Can't use PTEST so we need 2 source registers, 1 internal SIMD register - // (to hold the result of PCMPEQD or other similar SIMD compare instruction) - // and one internal INT register (to hold the result of PMOVMSKB). - buildInternalIntRegisterDefForNode(simdTree); - buildInternalFloatRegisterDefForNode(simdTree); - } - // These SIMD nodes only set the condition flags. - dstCount = 0; - break; - case SIMDIntrinsicDotProduct: // Float/Double vectors: // For SSE, or AVX with 32-byte vectors, we also need an internal register @@ -2262,14 +2196,7 @@ int LinearScan::BuildSIMD(GenTreeSIMD* simdTree) srcCount = BuildRMWUses(simdTree); } buildInternalRegisterUses(); - if (dstCount == 1) - { - BuildDef(simdTree, dstCandidates); - } - else - { - assert(dstCount == 0); - } + BuildDef(simdTree, dstCandidates); return srcCount; } #endif // FEATURE_SIMD @@ -2666,17 +2593,32 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) { srcCount += BuildAddrUses(op2->gtGetOp1()); } - else if (isRMW && !op2->isContained()) + else if (isRMW) { - if (HWIntrinsicInfo::IsCommutative(intrinsicId)) + if (!op2->isContained() && HWIntrinsicInfo::IsCommutative(intrinsicId)) { + // When op2 is not contained and we are commutative, we can set op2 + // to also be a tgtPrefUse. Codegen will then swap the operands. + tgtPrefUse2 = BuildUse(op2); srcCount += 1; } - else + else if (!op2->isContained() || varTypeIsArithmetic(intrinsicTree->TypeGet())) { + // When op2 is not contained or if we are producing a scalar value + // we need to mark it as delay free because the operand and target + // exist in the same register set. + srcCount += BuildDelayFreeUses(op2); } + else + { + // When op2 is contained and we are not producing a scalar value we + // have no concerns of overwriting op2 because they exist in different + // register sets. + + srcCount += BuildOperandUses(op2); + } } else { diff --git a/src/coreclr/src/jit/morph.cpp b/src/coreclr/src/jit/morph.cpp index fdff5b7298d6d..4fcaa51aa6173 100644 --- a/src/coreclr/src/jit/morph.cpp +++ b/src/coreclr/src/jit/morph.cpp @@ -63,38 +63,41 @@ GenTree* Compiler::fgMorphIntoHelperCall(GenTree* tree, int helper, GenTreeCall: // The helper call ought to be semantically equivalent to the original node, so preserve its VN. tree->ChangeOper(GT_CALL, GenTree::PRESERVE_VN); - tree->AsCall()->gtCallType = CT_HELPER; - tree->AsCall()->gtCallMethHnd = eeFindHelper(helper); - tree->AsCall()->gtCallThisArg = nullptr; - tree->AsCall()->gtCallArgs = args; - tree->AsCall()->gtCallLateArgs = nullptr; - tree->AsCall()->fgArgInfo = nullptr; - tree->AsCall()->gtRetClsHnd = nullptr; - tree->AsCall()->gtCallMoreFlags = 0; - tree->AsCall()->gtInlineCandidateInfo = nullptr; - tree->AsCall()->gtControlExpr = nullptr; + GenTreeCall* call = tree->AsCall(); + + call->gtCallType = CT_HELPER; + call->gtCallMethHnd = eeFindHelper(helper); + call->gtCallThisArg = nullptr; + call->gtCallArgs = args; + call->gtCallLateArgs = nullptr; + call->fgArgInfo = nullptr; + call->gtRetClsHnd = nullptr; + call->gtCallMoreFlags = 0; + call->gtInlineCandidateInfo = nullptr; + call->gtControlExpr = nullptr; #if DEBUG // Helper calls are never candidates. - tree->AsCall()->gtInlineObservation = InlineObservation::CALLSITE_IS_CALL_TO_HELPER; + call->gtInlineObservation = InlineObservation::CALLSITE_IS_CALL_TO_HELPER; #endif // DEBUG #ifdef FEATURE_READYTORUN_COMPILER - tree->AsCall()->gtEntryPoint.addr = nullptr; - tree->AsCall()->gtEntryPoint.accessType = IAT_VALUE; + call->gtEntryPoint.addr = nullptr; + call->gtEntryPoint.accessType = IAT_VALUE; #endif +#if FEATURE_MULTIREG_RET + call->ResetReturnType(); + call->ClearOtherRegs(); + call->ClearOtherRegFlags(); #ifndef TARGET_64BIT if (varTypeIsLong(tree)) { - GenTreeCall* callNode = tree->AsCall(); - ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); - retTypeDesc->Reset(); - retTypeDesc->InitializeLongReturnType(this); - callNode->ClearOtherRegs(); + call->InitializeLongReturnType(); } #endif // !TARGET_64BIT +#endif // FEATURE_MULTIREG_RET if (tree->OperMayThrow(this)) { @@ -115,7 +118,7 @@ GenTree* Compiler::fgMorphIntoHelperCall(GenTree* tree, int helper, GenTreeCall: if (morphArgs) { - tree = fgMorphArgs(tree->AsCall()); + tree = fgMorphArgs(call); } return tree; @@ -1947,8 +1950,6 @@ GenTree* Compiler::fgMakeTmpArgNode(fgArgTabEntry* curArgTabEntry) assert(varTypeIsStruct(type)); if (lvaIsMultiregStruct(varDsc, curArgTabEntry->IsVararg())) { - // ToDo-ARM64: Consider using: arg->ChangeOper(GT_LCL_FLD); - // as that is how UNIX_AMD64_ABI works. // We will create a GT_OBJ for the argument below. // This will be passed by value in two registers. assert(addrNode != nullptr); @@ -3665,31 +3666,21 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) #else // UNIX_AMD64_ABI // On Unix, structs are always passed by value. // We only need a copy if we have one of the following: - // - We have a lclVar that has been promoted and is passed in registers. // - The sizes don't match for a non-lclVar argument. // - We have a known struct type (e.g. SIMD) that requires multiple registers. - // TODO-Amd64-Unix-CQ: The first case could and should be handled without copies. // TODO-Amd64-Unix-Throughput: We don't need to keep the structDesc in the argEntry if it's not // actually passed in registers. if (argEntry->isPassedInRegisters()) { assert(argEntry->structDesc.passedInRegisters); - if (lclVar != nullptr) - { - if (lvaGetPromotionType(lclVar->AsLclVarCommon()->GetLclNum()) == - PROMOTION_TYPE_INDEPENDENT) - { - copyBlkClass = objClass; - } - } - else if (argObj->OperIs(GT_OBJ)) + if (argObj->OperIs(GT_OBJ)) { if (passingSize != structSize) { copyBlkClass = objClass; } } - else + else if (lclVar == nullptr) { // This should only be the case of a value directly producing a known struct type. assert(argObj->TypeGet() != TYP_STRUCT); @@ -9720,7 +9711,9 @@ GenTree* Compiler::fgMorphInitBlock(GenTree* tree) } #endif // LOCAL_ASSERTION_PROP - if (destLclVar->lvPromoted) + // If we have already determined that a promoted TYP_STRUCT lclVar will not be enregistered, + // we are better off doing a block init. + if (destLclVar->lvPromoted && (!destLclVar->lvDoNotEnregister || !destLclNode->TypeIs(TYP_STRUCT))) { GenTree* newTree = fgMorphPromoteLocalInitBlock(destLclNode->AsLclVar(), initVal, blockSize); @@ -10604,15 +10597,30 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) // Are both dest and src promoted structs? if (destDoFldAsg && srcDoFldAsg) { - // Both structs should be of the same type, or each have a single field of the same type. + // Both structs should be of the same type, or have the same number of fields of the same type. // If not we will use a copy block. - if (lvaTable[destLclNum].lvVerTypeInfo.GetClassHandle() != - lvaTable[srcLclNum].lvVerTypeInfo.GetClassHandle()) + bool misMatchedTypes = false; + if (destLclVar->lvVerTypeInfo.GetClassHandle() != srcLclVar->lvVerTypeInfo.GetClassHandle()) { - unsigned destFieldNum = lvaTable[destLclNum].lvFieldLclStart; - unsigned srcFieldNum = lvaTable[srcLclNum].lvFieldLclStart; - if ((lvaTable[destLclNum].lvFieldCnt != 1) || (lvaTable[srcLclNum].lvFieldCnt != 1) || - (lvaTable[destFieldNum].lvType != lvaTable[srcFieldNum].lvType)) + if (destLclVar->lvFieldCnt != srcLclVar->lvFieldCnt) + { + misMatchedTypes = true; + } + else + { + for (int i = 0; i < destLclVar->lvFieldCnt; i++) + { + LclVarDsc* destFieldVarDsc = lvaGetDesc(destLclVar->lvFieldLclStart + i); + LclVarDsc* srcFieldVarDsc = lvaGetDesc(srcLclVar->lvFieldLclStart + i); + if ((destFieldVarDsc->lvType != srcFieldVarDsc->lvType) || + (destFieldVarDsc->lvFldOffset != srcFieldVarDsc->lvFldOffset)) + { + misMatchedTypes = true; + break; + } + } + } + if (misMatchedTypes) { requiresCopyBlock = true; // Mismatched types, leave as a CopyBlock JITDUMP(" with mismatched types"); @@ -11642,6 +11650,17 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) op2->AsDblCon()->gtDconVal = 1.0 / divisor; } } + + // array.Length is always positive so GT_DIV can be changed to GT_UDIV + // if op2 is a positive cns + if (!optValnumCSE_phase && op1->OperIs(GT_ARR_LENGTH) && op2->IsIntegralConst() && + op2->AsIntCon()->IconValue() >= 2) // for 0 and 1 it doesn't matter if it's UDIV or DIV + { + assert(tree->OperIs(GT_DIV)); + tree->ChangeOper(GT_UDIV); + return fgMorphSmpOp(tree, mac); + } + #ifndef TARGET_64BIT if (typ == TYP_LONG) { @@ -11706,6 +11725,16 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) goto USE_HELPER_FOR_ARITH; } + // array.Length is always positive so GT_DIV can be changed to GT_UDIV + // if op2 is a positive cns + if (!optValnumCSE_phase && op1->OperIs(GT_ARR_LENGTH) && op2->IsIntegralConst() && + op2->AsIntCon()->IconValue() >= 2) // for 0 and 1 it doesn't matter if it's UMOD or MOD + { + assert(tree->OperIs(GT_MOD)); + tree->ChangeOper(GT_UMOD); + return fgMorphSmpOp(tree, mac); + } + // Do not use optimizations (unlike UMOD's idiv optimizing during codegen) for signed mod. // A similar optimization for signed mod will not work for a negative perfectly divisible // HI-word. To make it correct, we would need to divide without the sign and then flip the @@ -17431,7 +17460,8 @@ void Compiler::fgMorphLocalField(GenTree* tree, GenTree* parent) var_types treeType = tree->TypeGet(); var_types fieldType = fldVarDsc->TypeGet(); - if (fldOffset != BAD_VAR_NUM && (genTypeSize(fieldType) == genTypeSize(treeType))) + if (fldOffset != BAD_VAR_NUM && + ((genTypeSize(fieldType) == genTypeSize(treeType)) || (varDsc->lvFieldCnt == 1))) { // There is an existing sub-field we can use. tree->AsLclFld()->SetLclNum(fieldLclIndex); diff --git a/src/coreclr/src/jit/namedintrinsiclist.h b/src/coreclr/src/jit/namedintrinsiclist.h index d105eabdbb3dd..c9a87d782a62c 100644 --- a/src/coreclr/src/jit/namedintrinsiclist.h +++ b/src/coreclr/src/jit/namedintrinsiclist.h @@ -22,11 +22,14 @@ enum NamedIntrinsic : unsigned short NI_System_Type_get_IsValueType, NI_System_Type_IsAssignableFrom, -#ifdef FEATURE_HW_INTRINSICS + // These are used by HWIntrinsics but are defined more generally + // to allow dead code optimization and handle the recursion case + NI_IsSupported_True, NI_IsSupported_False, NI_Throw_PlatformNotSupportedException, +#ifdef FEATURE_HW_INTRINSICS NI_HW_INTRINSIC_START, #if defined(TARGET_XARCH) #define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ @@ -41,10 +44,12 @@ enum NamedIntrinsic : unsigned short NI_SIMD_AS_HWINTRINSIC_START, #if defined(TARGET_XARCH) -#define SIMD_AS_HWINTRINSIC(classId, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) NI_##classId##_##name, +#define SIMD_AS_HWINTRINSIC(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + NI_##classId##_##id, #include "simdashwintrinsiclistxarch.h" #elif defined(TARGET_ARM64) -#define SIMD_AS_HWINTRINSIC(classId, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) NI_##classId##_##name, +#define SIMD_AS_HWINTRINSIC(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + NI_##classId##_##id, #include "simdashwintrinsiclistarm64.h" #endif // !defined(TARGET_XARCH) && !defined(TARGET_ARM64) NI_SIMD_AS_HWINTRINSIC_END, diff --git a/src/coreclr/src/jit/objectalloc.cpp b/src/coreclr/src/jit/objectalloc.cpp index 4c34b4d36806b..7be52493cd21e 100644 --- a/src/coreclr/src/jit/objectalloc.cpp +++ b/src/coreclr/src/jit/objectalloc.cpp @@ -521,7 +521,7 @@ unsigned int ObjectAllocator::MorphAllocObjNodeIntoStackAlloc(GenTreeAllocObj* a bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0; bool bbIsReturn = block->bbJumpKind == BBJ_RETURN; LclVarDsc* const lclDsc = comp->lvaGetDesc(lclNum); - if (comp->fgVarNeedsExplicitZeroInit(lclDsc, bbInALoop, bbIsReturn)) + if (comp->fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn)) { //------------------------------------------------------------------------ // STMTx (IL 0x... ???) diff --git a/src/coreclr/src/jit/optimizer.cpp b/src/coreclr/src/jit/optimizer.cpp index 096898ba00997..2fe04e7a8b060 100644 --- a/src/coreclr/src/jit/optimizer.cpp +++ b/src/coreclr/src/jit/optimizer.cpp @@ -9189,3 +9189,147 @@ void Compiler::optOptimizeBools() fgDebugCheckBBlist(); #endif } + +typedef JitHashTable, unsigned> LclVarRefCounts; + +//------------------------------------------------------------------------------------------ +// optRemoveRedundantZeroInits: Remove redundant zero intializations. +// +// Notes: +// This phase iterates over basic blocks starting with the first basic block until there is no unique +// basic block successor or until it detects a loop. It keeps track of local nodes it encounters. +// When it gets to an assignment to a local variable or a local field, it checks whether the assignment +// is the first reference to the local (or to the parent of the local field), and, if so, +// it may do one of two optimizations: +// 1. If the following conditions are true: +// the local is untracked, +// the rhs of the assignment is 0, +// the local is guaranteed to be fully initialized in the prolog, +// then the explicit zero initialization is removed. +// 2. If the following conditions are true: +// the assignment is to a local (and not a field), +// the local is not lvLiveInOutOfHndlr or no exceptions can be thrown between the prolog and the assignment, +// either the local has no gc pointers or there are no gc-safe points between the prolog and the assignment, +// then the local with lvHasExplicitInit which tells the codegen not to insert zero initialization for this +// local in the prolog. + +void Compiler::optRemoveRedundantZeroInits() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In optRemoveRedundantZeroInits()\n"); + } +#endif // DEBUG + + CompAllocator allocator(getAllocator(CMK_ZeroInit)); + LclVarRefCounts refCounts(allocator); + bool hasGCSafePoint = false; + bool canThrow = false; + + assert(fgStmtListThreaded); + + for (BasicBlock* block = fgFirstBB; (block != nullptr) && ((block->bbFlags & BBF_MARKED) == 0); + block = block->GetUniqueSucc()) + { + block->bbFlags |= BBF_MARKED; + for (Statement* stmt = block->FirstNonPhiDef(); stmt != nullptr;) + { + Statement* next = stmt->GetNextStmt(); + for (GenTree* tree = stmt->GetTreeList(); tree != nullptr; tree = tree->gtNext) + { + if (((tree->gtFlags & GTF_CALL) != 0) && (!tree->IsCall() || !tree->AsCall()->IsSuppressGCTransition())) + { + hasGCSafePoint = true; + } + + if ((tree->gtFlags & GTF_EXCEPT) != 0) + { + canThrow = true; + } + + switch (tree->gtOper) + { + case GT_LCL_VAR: + case GT_LCL_FLD: + case GT_LCL_VAR_ADDR: + case GT_LCL_FLD_ADDR: + { + unsigned lclNum = tree->AsLclVarCommon()->GetLclNum(); + unsigned* pRefCount = refCounts.LookupPointer(lclNum); + if (pRefCount != nullptr) + { + *pRefCount = (*pRefCount) + 1; + } + else + { + refCounts.Set(lclNum, 1); + } + + break; + } + case GT_ASG: + { + GenTreeOp* treeOp = tree->AsOp(); + if (treeOp->gtOp1->OperIs(GT_LCL_VAR, GT_LCL_FLD)) + { + unsigned lclNum = treeOp->gtOp1->AsLclVarCommon()->GetLclNum(); + LclVarDsc* const lclDsc = lvaGetDesc(lclNum); + unsigned* pRefCount = refCounts.LookupPointer(lclNum); + assert(pRefCount != nullptr); + if (*pRefCount == 1) + { + // The local hasn't been referenced before this assignment. + bool removedExplicitZeroInit = false; + if (!lclDsc->lvTracked && treeOp->gtOp2->IsIntegralConst(0)) + { + bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0; + bool bbIsReturn = block->bbJumpKind == BBJ_RETURN; + + if (!fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn)) + { + // We are guaranteed to have a zero initialization in the prolog and + // the local hasn't been redefined between the prolog and this explicit + // zero initialization so the assignment can be safely removed. + if (tree == stmt->GetRootNode()) + { + fgRemoveStmt(block, stmt); + removedExplicitZeroInit = true; + *pRefCount = 0; + lclDsc->lvSuppressedZeroInit = 1; + } + } + } + + if (!removedExplicitZeroInit && treeOp->gtOp1->OperIs(GT_LCL_VAR) && + (!canThrow || !lclDsc->lvLiveInOutOfHndlr)) + { + // If compMethodRequiresPInvokeFrame() returns true, lower may later + // insert a call to CORINFO_HELP_INIT_PINVOKE_FRAME which is a gc-safe point. + if (!lclDsc->HasGCPtr() || + (!GetInterruptible() && !hasGCSafePoint && !compMethodRequiresPInvokeFrame())) + { + // The local hasn't been used and won't be reported to the gc between + // the prolog and this explicit intialization. Therefore, it doesn't + // require zero initialization in the prolog. + lclDsc->lvHasExplicitInit = 1; + } + } + } + } + break; + } + default: + break; + } + } + stmt = next; + } + } + + for (BasicBlock* block = fgFirstBB; (block != nullptr) && ((block->bbFlags & BBF_MARKED) != 0); + block = block->GetUniqueSucc()) + { + block->bbFlags &= ~BBF_MARKED; + } +} diff --git a/src/coreclr/src/jit/rationalize.cpp b/src/coreclr/src/jit/rationalize.cpp index 07bdd29f83411..b8f8595b43e06 100644 --- a/src/coreclr/src/jit/rationalize.cpp +++ b/src/coreclr/src/jit/rationalize.cpp @@ -295,7 +295,7 @@ static void RewriteAssignmentIntoStoreLclCore(GenTreeOp* assignment, store->AsLclFld()->SetFieldSeq(var->AsLclFld()->GetFieldSeq()); } - copyFlags(store, var, GTF_LIVENESS_MASK); + copyFlags(store, var, (GTF_LIVENESS_MASK | GTF_VAR_MULTIREG)); store->gtFlags &= ~GTF_REVERSE_OPS; store->gtType = var->TypeGet(); @@ -785,10 +785,18 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge // type(s). if ((hwIntrinsicNode->gtType == TYP_I_IMPL) && (hwIntrinsicNode->gtSIMDSize == TARGET_POINTER_SIZE)) { - // This happens when it is consumed by a GT_RET_EXPR. - // It can only be a Vector2f or Vector2i. - assert(genTypeSize(hwIntrinsicNode->gtSIMDBaseType) == 4); - hwIntrinsicNode->gtType = TYP_SIMD8; +#ifdef TARGET_ARM64 + // Special case for GetElement/ToScalar because they take Vector64 and return T + // and T can be long or ulong. + if (!(hwIntrinsicNode->gtHWIntrinsicId == NI_Vector64_GetElement || + hwIntrinsicNode->gtHWIntrinsicId == NI_Vector64_ToScalar)) +#endif + { + // This happens when it is consumed by a GT_RET_EXPR. + // It can only be a Vector2f or Vector2i. + assert(genTypeSize(hwIntrinsicNode->gtSIMDBaseType) == 4); + hwIntrinsicNode->gtType = TYP_SIMD8; + } } break; } diff --git a/src/coreclr/src/jit/regset.cpp b/src/coreclr/src/jit/regset.cpp index a550df415c030..0ebde49eadfb2 100644 --- a/src/coreclr/src/jit/regset.cpp +++ b/src/coreclr/src/jit/regset.cpp @@ -285,18 +285,17 @@ RegSet::SpillDsc* RegSet::rsGetSpillInfo(GenTree* tree, regNumber reg, SpillDsc* // Return Value: // None. // -// Assumption: -// RyuJIT backend specific: in case of multi-reg call nodes, GTF_SPILL -// flag associated with the reg that is being spilled is cleared. The -// caller of this method is expected to clear GTF_SPILL flag on call -// node after all of its registers marked for spilling are spilled. +// Notes: +// For multi-reg nodes, only the spill flag associated with this reg is cleared. +// The spill flag on the node should be cleared by the caller of this method. // void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) { assert(tree != nullptr); - GenTreeCall* call = nullptr; - var_types treeType; + GenTreeCall* call = nullptr; + GenTreeLclVar* lcl = nullptr; + var_types treeType; #if defined(TARGET_ARM) GenTreePutArgSplit* splitArg = nullptr; GenTreeMultiRegOp* multiReg = nullptr; @@ -304,9 +303,9 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) if (tree->IsMultiRegCall()) { - call = tree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - treeType = retTypeDesc->GetReturnRegType(regIdx); + call = tree->AsCall(); + const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + treeType = retTypeDesc->GetReturnRegType(regIdx); } #ifdef TARGET_ARM else if (tree->OperIsPutArgSplit()) @@ -320,6 +319,12 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) treeType = multiReg->GetRegType(regIdx); } #endif // TARGET_ARM + else if (tree->IsMultiRegLclVar()) + { + GenTreeLclVar* lcl = tree->AsLclVar(); + LclVarDsc* varDsc = m_rsCompiler->lvaGetDesc(lcl->GetLclNum()); + treeType = varDsc->TypeGet(); + } else { treeType = tree->TypeGet(); @@ -345,9 +350,8 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) // vars should be handled elsewhere, and to prevent // spilling twice clear GTF_SPILL flag on tree node. // - // In case of multi-reg call nodes only the spill flag - // associated with the reg is cleared. Spill flag on - // call node should be cleared by the caller of this method. + // In case of multi-reg nodes, only the spill flag associated with this reg is cleared. + // The spill flag on the node should be cleared by the caller of this method. assert((tree->gtFlags & GTF_SPILL) != 0); unsigned regFlags = 0; @@ -371,6 +375,12 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) regFlags &= ~GTF_SPILL; } #endif // TARGET_ARM + else if (lcl != nullptr) + { + regFlags = lcl->GetRegSpillFlagByIdx(regIdx); + assert((regFlags & GTF_SPILL) != 0); + regFlags &= ~GTF_SPILL; + } else { assert(!varTypeIsMultiReg(tree)); @@ -446,6 +456,11 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) multiReg->SetRegSpillFlagByIdx(regFlags, regIdx); } #endif // TARGET_ARM + else if (lcl != nullptr) + { + regFlags |= GTF_SPILLED; + lcl->SetRegSpillFlagByIdx(regFlags, regIdx); + } } #if defined(TARGET_X86) @@ -565,6 +580,13 @@ TempDsc* RegSet::rsUnspillInPlace(GenTree* tree, regNumber oldReg, unsigned regI multiReg->SetRegSpillFlagByIdx(flags, regIdx); } #endif // TARGET_ARM + else if (tree->IsMultiRegLclVar()) + { + GenTreeLclVar* lcl = tree->AsLclVar(); + unsigned flags = lcl->GetRegSpillFlagByIdx(regIdx); + flags &= ~GTF_SPILLED; + lcl->SetRegSpillFlagByIdx(flags, regIdx); + } else { tree->gtFlags &= ~GTF_SPILLED; diff --git a/src/coreclr/src/jit/simd.cpp b/src/coreclr/src/jit/simd.cpp index bfd8c04f76789..3bd38ef537199 100644 --- a/src/coreclr/src/jit/simd.cpp +++ b/src/coreclr/src/jit/simd.cpp @@ -1075,19 +1075,9 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in case SIMDIntrinsicSub: case SIMDIntrinsicMul: case SIMDIntrinsicDiv: - case SIMDIntrinsicSqrt: - case SIMDIntrinsicMin: - case SIMDIntrinsicMax: - case SIMDIntrinsicAbs: case SIMDIntrinsicEqual: - case SIMDIntrinsicLessThan: - case SIMDIntrinsicLessThanOrEqual: - case SIMDIntrinsicGreaterThan: - case SIMDIntrinsicGreaterThanOrEqual: case SIMDIntrinsicBitwiseAnd: - case SIMDIntrinsicBitwiseAndNot: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: case SIMDIntrinsicDotProduct: case SIMDIntrinsicCast: case SIMDIntrinsicConvertToSingle: @@ -1268,218 +1258,6 @@ SIMDIntrinsicID Compiler::impSIMDLongRelOpEqual(CORINFO_CLASS_HANDLE typeHnd, SIMDIntrinsicShuffleSSE2, TYP_INT, size); return SIMDIntrinsicBitwiseAnd; } - -// impSIMDLongRelOpGreaterThan: transforms operands and returns the SIMD intrinsic to be applied on -// transformed operands to obtain > comparison result. -// -// Arguments: -// typeHnd - type handle of SIMD vector -// size - SIMD vector size -// pOp1 - in-out parameter; first operand -// pOp2 - in-out parameter; second operand -// -// Return Value: -// Modifies in-out params pOp1, pOp2 and returns intrinsic ID to be applied to modified operands -// -SIMDIntrinsicID Compiler::impSIMDLongRelOpGreaterThan(CORINFO_CLASS_HANDLE typeHnd, - unsigned size, - GenTree** pOp1, - GenTree** pOp2) -{ - var_types simdType = (*pOp1)->TypeGet(); - assert(varTypeIsSIMD(simdType) && ((*pOp2)->TypeGet() == simdType)); - - // GreaterThan(v1, v2) where v1 and v2 are vector long. - // Let us consider the case of single long element comparison. - // say L1 = (x1, y1) and L2 = (x2, y2) where x1, y1, x2, and y2 are 32-bit integers that comprise the longs L1 and - // L2. - // - // GreaterThan(L1, L2) can be expressed in terms of > relationship between 32-bit integers that comprise L1 and L2 - // as - // = (x1, y1) > (x2, y2) - // = (x1 > x2) || [(x1 == x2) && (y1 > y2)] - eq (1) - // - // t = (v1 > v2) 32-bit signed comparison - // u = (v1 == v2) 32-bit sized element equality - // v = (v1 > v2) 32-bit unsigned comparison - // - // z = shuffle(t, (3, 3, 1, 1)) - This corresponds to (x1 > x2) in eq(1) above - // t1 = Shuffle(v, (2, 2, 0, 0)) - This corresponds to (y1 > y2) in eq(1) above - // u1 = Shuffle(u, (3, 3, 1, 1)) - This corresponds to (x1 == x2) in eq(1) above - // w = And(t1, u1) - This corresponds to [(x1 == x2) && (y1 > y2)] in eq(1) above - // Result = BitwiseOr(z, w) - - // Since op1 and op2 gets used multiple times, make sure side effects are computed. - GenTree* dupOp1 = nullptr; - GenTree* dupOp2 = nullptr; - GenTree* dupDupOp1 = nullptr; - GenTree* dupDupOp2 = nullptr; - - if (((*pOp1)->gtFlags & GTF_SIDE_EFFECT) != 0) - { - dupOp1 = fgInsertCommaFormTemp(pOp1, typeHnd); - dupDupOp1 = gtNewLclvNode(dupOp1->AsLclVarCommon()->GetLclNum(), simdType); - } - else - { - dupOp1 = gtCloneExpr(*pOp1); - dupDupOp1 = gtCloneExpr(*pOp1); - } - - if (((*pOp2)->gtFlags & GTF_SIDE_EFFECT) != 0) - { - dupOp2 = fgInsertCommaFormTemp(pOp2, typeHnd); - dupDupOp2 = gtNewLclvNode(dupOp2->AsLclVarCommon()->GetLclNum(), simdType); - } - else - { - dupOp2 = gtCloneExpr(*pOp2); - dupDupOp2 = gtCloneExpr(*pOp2); - } - - assert(dupDupOp1 != nullptr && dupDupOp2 != nullptr); - assert(dupOp1 != nullptr && dupOp2 != nullptr); - assert(*pOp1 != nullptr && *pOp2 != nullptr); - - // v1GreaterThanv2Signed - signed 32-bit comparison - GenTree* v1GreaterThanv2Signed = gtNewSIMDNode(simdType, *pOp1, *pOp2, SIMDIntrinsicGreaterThan, TYP_INT, size); - - // v1Equalsv2 - 32-bit equality - GenTree* v1Equalsv2 = gtNewSIMDNode(simdType, dupOp1, dupOp2, SIMDIntrinsicEqual, TYP_INT, size); - - // v1GreaterThanv2Unsigned - unsigned 32-bit comparison - var_types tempBaseType = TYP_UINT; - SIMDIntrinsicID sid = impSIMDRelOp(SIMDIntrinsicGreaterThan, typeHnd, size, &tempBaseType, &dupDupOp1, &dupDupOp2); - GenTree* v1GreaterThanv2Unsigned = gtNewSIMDNode(simdType, dupDupOp1, dupDupOp2, sid, tempBaseType, size); - - GenTree* z = gtNewSIMDNode(simdType, v1GreaterThanv2Signed, gtNewIconNode(SHUFFLE_WWYY, TYP_INT), - SIMDIntrinsicShuffleSSE2, TYP_FLOAT, size); - GenTree* t1 = gtNewSIMDNode(simdType, v1GreaterThanv2Unsigned, gtNewIconNode(SHUFFLE_ZZXX, TYP_INT), - SIMDIntrinsicShuffleSSE2, TYP_FLOAT, size); - GenTree* u1 = gtNewSIMDNode(simdType, v1Equalsv2, gtNewIconNode(SHUFFLE_WWYY, TYP_INT), SIMDIntrinsicShuffleSSE2, - TYP_FLOAT, size); - GenTree* w = gtNewSIMDNode(simdType, u1, t1, SIMDIntrinsicBitwiseAnd, TYP_INT, size); - - *pOp1 = z; - *pOp2 = w; - return SIMDIntrinsicBitwiseOr; -} - -// impSIMDLongRelOpGreaterThanOrEqual: transforms operands and returns the SIMD intrinsic to be applied on -// transformed operands to obtain >= comparison result. -// -// Arguments: -// typeHnd - type handle of SIMD vector -// size - SIMD vector size -// pOp1 - in-out parameter; first operand -// pOp2 - in-out parameter; second operand -// -// Return Value: -// Modifies in-out params pOp1, pOp2 and returns intrinsic ID to be applied to modified operands -// -SIMDIntrinsicID Compiler::impSIMDLongRelOpGreaterThanOrEqual(CORINFO_CLASS_HANDLE typeHnd, - unsigned size, - GenTree** pOp1, - GenTree** pOp2) -{ - var_types simdType = (*pOp1)->TypeGet(); - assert(varTypeIsSIMD(simdType) && ((*pOp2)->TypeGet() == simdType)); - - // expand this to (a == b) | (a > b) - GenTree* dupOp1 = nullptr; - GenTree* dupOp2 = nullptr; - - if (((*pOp1)->gtFlags & GTF_SIDE_EFFECT) != 0) - { - dupOp1 = fgInsertCommaFormTemp(pOp1, typeHnd); - } - else - { - dupOp1 = gtCloneExpr(*pOp1); - } - - if (((*pOp2)->gtFlags & GTF_SIDE_EFFECT) != 0) - { - dupOp2 = fgInsertCommaFormTemp(pOp2, typeHnd); - } - else - { - dupOp2 = gtCloneExpr(*pOp2); - } - - assert(dupOp1 != nullptr && dupOp2 != nullptr); - assert(*pOp1 != nullptr && *pOp2 != nullptr); - - // (a==b) - SIMDIntrinsicID id = impSIMDLongRelOpEqual(typeHnd, size, pOp1, pOp2); - *pOp1 = gtNewSIMDNode(simdType, *pOp1, *pOp2, id, TYP_LONG, size); - - // (a > b) - id = impSIMDLongRelOpGreaterThan(typeHnd, size, &dupOp1, &dupOp2); - *pOp2 = gtNewSIMDNode(simdType, dupOp1, dupOp2, id, TYP_LONG, size); - - return SIMDIntrinsicBitwiseOr; -} - -// impSIMDInt32OrSmallIntRelOpGreaterThanOrEqual: transforms operands and returns the SIMD intrinsic to be applied on -// transformed operands to obtain >= comparison result in case of integer base type vectors -// -// Arguments: -// typeHnd - type handle of SIMD vector -// size - SIMD vector size -// baseType - base type of SIMD vector -// pOp1 - in-out parameter; first operand -// pOp2 - in-out parameter; second operand -// -// Return Value: -// Modifies in-out params pOp1, pOp2 and returns intrinsic ID to be applied to modified operands -// -SIMDIntrinsicID Compiler::impSIMDIntegralRelOpGreaterThanOrEqual( - CORINFO_CLASS_HANDLE typeHnd, unsigned size, var_types baseType, GenTree** pOp1, GenTree** pOp2) -{ - var_types simdType = (*pOp1)->TypeGet(); - assert(varTypeIsSIMD(simdType) && ((*pOp2)->TypeGet() == simdType)); - - // This routine should be used only for integer base type vectors - assert(varTypeIsIntegral(baseType)); - if ((getSIMDSupportLevel() == SIMD_SSE2_Supported) && ((baseType == TYP_LONG) || baseType == TYP_UBYTE)) - { - return impSIMDLongRelOpGreaterThanOrEqual(typeHnd, size, pOp1, pOp2); - } - - // expand this to (a == b) | (a > b) - GenTree* dupOp1 = nullptr; - GenTree* dupOp2 = nullptr; - - if (((*pOp1)->gtFlags & GTF_SIDE_EFFECT) != 0) - { - dupOp1 = fgInsertCommaFormTemp(pOp1, typeHnd); - } - else - { - dupOp1 = gtCloneExpr(*pOp1); - } - - if (((*pOp2)->gtFlags & GTF_SIDE_EFFECT) != 0) - { - dupOp2 = fgInsertCommaFormTemp(pOp2, typeHnd); - } - else - { - dupOp2 = gtCloneExpr(*pOp2); - } - - assert(dupOp1 != nullptr && dupOp2 != nullptr); - assert(*pOp1 != nullptr && *pOp2 != nullptr); - - // (a==b) - *pOp1 = gtNewSIMDNode(simdType, *pOp1, *pOp2, SIMDIntrinsicEqual, baseType, size); - - // (a > b) - *pOp2 = gtNewSIMDNode(simdType, dupOp1, dupOp2, SIMDIntrinsicGreaterThan, baseType, size); - - return SIMDIntrinsicBitwiseOr; -} #endif // TARGET_XARCH // Transforms operands and returns the SIMD intrinsic to be applied on @@ -1514,32 +1292,9 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, if (varTypeIsFloating(baseType)) { - // SSE2/AVX doesn't support > and >= on vector float/double. - // Therefore, we need to use < and <= with swapped operands - if (relOpIntrinsicId == SIMDIntrinsicGreaterThan || relOpIntrinsicId == SIMDIntrinsicGreaterThanOrEqual) - { - GenTree* tmp = *pOp1; - *pOp1 = *pOp2; - *pOp2 = tmp; - - intrinsicID = - (relOpIntrinsicId == SIMDIntrinsicGreaterThan) ? SIMDIntrinsicLessThan : SIMDIntrinsicLessThanOrEqual; - } } else if (varTypeIsIntegral(baseType)) { - // SSE/AVX doesn't support < and <= on integer base type vectors. - // Therefore, we need to use > and >= with swapped operands. - if (intrinsicID == SIMDIntrinsicLessThan || intrinsicID == SIMDIntrinsicLessThanOrEqual) - { - GenTree* tmp = *pOp1; - *pOp1 = *pOp2; - *pOp2 = tmp; - - intrinsicID = (relOpIntrinsicId == SIMDIntrinsicLessThan) ? SIMDIntrinsicGreaterThan - : SIMDIntrinsicGreaterThanOrEqual; - } - if ((getSIMDSupportLevel() == SIMD_SSE2_Supported) && baseType == TYP_LONG) { // There is no direct SSE2 support for comparing TYP_LONG vectors. @@ -1548,28 +1303,13 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, { intrinsicID = impSIMDLongRelOpEqual(typeHnd, size, pOp1, pOp2); } - else if (intrinsicID == SIMDIntrinsicGreaterThan) - { - intrinsicID = impSIMDLongRelOpGreaterThan(typeHnd, size, pOp1, pOp2); - } - else if (intrinsicID == SIMDIntrinsicGreaterThanOrEqual) - { - intrinsicID = impSIMDLongRelOpGreaterThanOrEqual(typeHnd, size, pOp1, pOp2); - } else { unreached(); } } // SSE2 and AVX direct support for signed comparison of int32, int16 and int8 types - else if (!varTypeIsUnsigned(baseType)) - { - if (intrinsicID == SIMDIntrinsicGreaterThanOrEqual) - { - intrinsicID = impSIMDIntegralRelOpGreaterThanOrEqual(typeHnd, size, baseType, pOp1, pOp2); - } - } - else // unsigned + else if (varTypeIsUnsigned(baseType)) { // Vector, Vector, Vector and Vector: // SSE2 supports > for signed comparison. Therefore, to use it for @@ -1644,21 +1384,7 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, return impSIMDRelOp(intrinsicID, typeHnd, size, inOutBaseType, pOp1, pOp2); } } -#elif defined(TARGET_ARM64) - // TODO-ARM64-CQ handle comparisons against zero - - // TARGET_ARM64 doesn't support < and <= on register register comparisons - // Therefore, we need to use > and >= with swapped operands. - if (intrinsicID == SIMDIntrinsicLessThan || intrinsicID == SIMDIntrinsicLessThanOrEqual) - { - GenTree* tmp = *pOp1; - *pOp1 = *pOp2; - *pOp2 = tmp; - - intrinsicID = - (intrinsicID == SIMDIntrinsicLessThan) ? SIMDIntrinsicGreaterThan : SIMDIntrinsicGreaterThanOrEqual; - } -#else // !TARGET_XARCH +#elif !defined(TARGET_ARM64) assert(!"impSIMDRelOp() unimplemented on target arch"); unreached(); #endif // !TARGET_XARCH @@ -1666,411 +1392,6 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, return intrinsicID; } -//------------------------------------------------------------------------- -// impSIMDAbs: creates GT_SIMD node to compute Abs value of a given vector. -// -// Arguments: -// typeHnd - type handle of SIMD vector -// baseType - base type of vector -// size - vector size in bytes -// op1 - operand of Abs intrinsic -// -GenTree* Compiler::impSIMDAbs(CORINFO_CLASS_HANDLE typeHnd, var_types baseType, unsigned size, GenTree* op1) -{ - assert(varTypeIsSIMD(op1)); - - var_types simdType = op1->TypeGet(); - GenTree* retVal = nullptr; - -#ifdef TARGET_XARCH - // When there is no direct support, Abs(v) could be computed - // on integer vectors as follows: - // BitVector = v < vector.Zero - // result = ConditionalSelect(BitVector, vector.Zero - v, v) - - bool useConditionalSelect = false; - if (getSIMDSupportLevel() == SIMD_SSE2_Supported) - { - // SSE2 doesn't support abs on signed integer type vectors. - if (baseType == TYP_LONG || baseType == TYP_INT || baseType == TYP_SHORT || baseType == TYP_BYTE) - { - useConditionalSelect = true; - } - } - else - { - assert(getSIMDSupportLevel() >= SIMD_SSE4_Supported); - if (baseType == TYP_LONG) - { - // SSE4/AVX2 don't support abs on long type vector. - useConditionalSelect = true; - } - } - - if (useConditionalSelect) - { - // This works only on integer vectors not on float/double vectors. - assert(varTypeIsIntegral(baseType)); - - GenTree* op1Assign; - unsigned op1LclNum; - - if (op1->OperGet() == GT_LCL_VAR) - { - op1LclNum = op1->AsLclVarCommon()->GetLclNum(); - op1Assign = nullptr; - } - else - { - op1LclNum = lvaGrabTemp(true DEBUGARG("SIMD Abs op1")); - lvaSetStruct(op1LclNum, typeHnd, false); - op1Assign = gtNewTempAssign(op1LclNum, op1); - op1 = gtNewLclvNode(op1LclNum, op1->TypeGet()); - } - - // Assign Vector.Zero to a temp since it is needed more than once - GenTree* vecZero = gtNewSIMDVectorZero(simdType, baseType, size); - unsigned vecZeroLclNum = lvaGrabTemp(true DEBUGARG("SIMD Abs VecZero")); - lvaSetStruct(vecZeroLclNum, typeHnd, false); - GenTree* vecZeroAssign = gtNewTempAssign(vecZeroLclNum, vecZero); - - // Construct BitVector = v < vector.Zero - GenTree* bitVecOp1 = op1; - GenTree* bitVecOp2 = gtNewLclvNode(vecZeroLclNum, vecZero->TypeGet()); - var_types relOpBaseType = baseType; - SIMDIntrinsicID relOpIntrinsic = - impSIMDRelOp(SIMDIntrinsicLessThan, typeHnd, size, &relOpBaseType, &bitVecOp1, &bitVecOp2); - GenTree* bitVec = gtNewSIMDNode(simdType, bitVecOp1, bitVecOp2, relOpIntrinsic, relOpBaseType, size); - unsigned bitVecLclNum = lvaGrabTemp(true DEBUGARG("SIMD Abs bitVec")); - lvaSetStruct(bitVecLclNum, typeHnd, false); - GenTree* bitVecAssign = gtNewTempAssign(bitVecLclNum, bitVec); - bitVec = gtNewLclvNode(bitVecLclNum, bitVec->TypeGet()); - - // Construct condSelectOp1 = vector.Zero - v - GenTree* subOp1 = gtNewLclvNode(vecZeroLclNum, vecZero->TypeGet()); - GenTree* subOp2 = gtNewLclvNode(op1LclNum, op1->TypeGet()); - GenTree* negVec = gtNewSIMDNode(simdType, subOp1, subOp2, SIMDIntrinsicSub, baseType, size); - - // Construct ConditionalSelect(bitVec, vector.Zero - v, v) - GenTree* vec = gtNewLclvNode(op1LclNum, op1->TypeGet()); - retVal = impSIMDSelect(typeHnd, baseType, size, bitVec, negVec, vec); - - // Prepend bitVec assignment to retVal. - // retVal = (tmp2 = v < tmp1), CondSelect(tmp2, tmp1 - v, v) - retVal = gtNewOperNode(GT_COMMA, simdType, bitVecAssign, retVal); - - // Prepend vecZero assignment to retVal. - // retVal = (tmp1 = vector.Zero), (tmp2 = v < tmp1), CondSelect(tmp2, tmp1 - v, v) - retVal = gtNewOperNode(GT_COMMA, simdType, vecZeroAssign, retVal); - - // If op1 was assigned to a temp, prepend that to retVal. - if (op1Assign != nullptr) - { - // retVal = (v=op1), (tmp1 = vector.Zero), (tmp2 = v < tmp1), CondSelect(tmp2, tmp1 - v, v) - retVal = gtNewOperNode(GT_COMMA, simdType, op1Assign, retVal); - } - } - else if (varTypeIsFloating(baseType)) - { - // Abs(vf) = vf & new SIMDVector(0x7fffffff); - // Abs(vd) = vf & new SIMDVector(0x7fffffffffffffff); - GenTree* bitMask = nullptr; - if (baseType == TYP_FLOAT) - { - float f; - static_assert_no_msg(sizeof(float) == sizeof(int)); - *((int*)&f) = 0x7fffffff; - bitMask = gtNewDconNode(f); - } - else if (baseType == TYP_DOUBLE) - { - double d; - static_assert_no_msg(sizeof(double) == sizeof(__int64)); - *((__int64*)&d) = 0x7fffffffffffffffLL; - bitMask = gtNewDconNode(d); - } - - assert(bitMask != nullptr); - bitMask->gtType = baseType; - GenTree* bitMaskVector = gtNewSIMDNode(simdType, bitMask, SIMDIntrinsicInit, baseType, size); - retVal = gtNewSIMDNode(simdType, op1, bitMaskVector, SIMDIntrinsicBitwiseAnd, baseType, size); - } - else if (baseType == TYP_USHORT || baseType == TYP_UBYTE || baseType == TYP_UINT || baseType == TYP_ULONG) - { - // Abs is a no-op on unsigned integer type vectors - retVal = op1; - } - else - { - assert(getSIMDSupportLevel() >= SIMD_SSE4_Supported); - assert(baseType != TYP_LONG); - - retVal = gtNewSIMDNode(simdType, op1, SIMDIntrinsicAbs, baseType, size); - } -#elif defined(TARGET_ARM64) - if (varTypeIsUnsigned(baseType)) - { - // Abs is a no-op on unsigned integer type vectors - retVal = op1; - } - else - { - retVal = gtNewSIMDNode(simdType, op1, SIMDIntrinsicAbs, baseType, size); - } -#else // !defined(TARGET_XARCH)_ && !defined(TARGET_ARM64) - assert(!"Abs intrinsic on non-xarch target not implemented"); -#endif // !TARGET_XARCH - - return retVal; -} - -// Creates a GT_SIMD tree for Select operation -// -// Arguments: -// typeHnd - type handle of SIMD vector -// baseType - base type of SIMD vector -// size - SIMD vector size -// op1 - first operand = Condition vector vc -// op2 - second operand = va -// op3 - third operand = vb -// -// Return Value: -// Returns GT_SIMD tree that computes Select(vc, va, vb) -// -GenTree* Compiler::impSIMDSelect( - CORINFO_CLASS_HANDLE typeHnd, var_types baseType, unsigned size, GenTree* op1, GenTree* op2, GenTree* op3) -{ - assert(varTypeIsSIMD(op1)); - var_types simdType = op1->TypeGet(); - assert(op2->TypeGet() == simdType); - assert(op3->TypeGet() == simdType); - - // TODO-ARM64-CQ Support generating select instruction for SIMD - - // Select(BitVector vc, va, vb) = (va & vc) | (vb & !vc) - // Select(op1, op2, op3) = (op2 & op1) | (op3 & !op1) - // = SIMDIntrinsicBitwiseOr(SIMDIntrinsicBitwiseAnd(op2, op1), - // SIMDIntrinsicBitwiseAndNot(op3, op1)) - // - // If Op1 has side effect, create an assignment to a temp - GenTree* tmp = op1; - GenTree* asg = nullptr; - if ((op1->gtFlags & GTF_SIDE_EFFECT) != 0) - { - unsigned lclNum = lvaGrabTemp(true DEBUGARG("SIMD Select")); - lvaSetStruct(lclNum, typeHnd, false); - tmp = gtNewLclvNode(lclNum, op1->TypeGet()); - asg = gtNewTempAssign(lclNum, op1); - } - - GenTree* andExpr = gtNewSIMDNode(simdType, op2, tmp, SIMDIntrinsicBitwiseAnd, baseType, size); - GenTree* dupOp1 = gtCloneExpr(tmp); - assert(dupOp1 != nullptr); -#ifdef TARGET_ARM64 - // ARM64 implements SIMDIntrinsicBitwiseAndNot as Left & ~Right - GenTree* andNotExpr = gtNewSIMDNode(simdType, op3, dupOp1, SIMDIntrinsicBitwiseAndNot, baseType, size); -#else - // XARCH implements SIMDIntrinsicBitwiseAndNot as ~Left & Right - GenTree* andNotExpr = gtNewSIMDNode(simdType, dupOp1, op3, SIMDIntrinsicBitwiseAndNot, baseType, size); -#endif - GenTree* simdTree = gtNewSIMDNode(simdType, andExpr, andNotExpr, SIMDIntrinsicBitwiseOr, baseType, size); - - // If asg not null, create a GT_COMMA tree. - if (asg != nullptr) - { - simdTree = gtNewOperNode(GT_COMMA, simdTree->TypeGet(), asg, simdTree); - } - - return simdTree; -} - -// Creates a GT_SIMD tree for Min/Max operation -// -// Arguments: -// IntrinsicId - SIMD intrinsic Id, either Min or Max -// typeHnd - type handle of SIMD vector -// baseType - base type of SIMD vector -// size - SIMD vector size -// op1 - first operand = va -// op2 - second operand = vb -// -// Return Value: -// Returns GT_SIMD tree that computes Max(va, vb) -// -GenTree* Compiler::impSIMDMinMax(SIMDIntrinsicID intrinsicId, - CORINFO_CLASS_HANDLE typeHnd, - var_types baseType, - unsigned size, - GenTree* op1, - GenTree* op2) -{ - assert(intrinsicId == SIMDIntrinsicMin || intrinsicId == SIMDIntrinsicMax); - assert(varTypeIsSIMD(op1)); - var_types simdType = op1->TypeGet(); - assert(op2->TypeGet() == simdType); - -#if defined(TARGET_XARCH) || defined(TARGET_ARM64) - GenTree* simdTree = nullptr; - -#ifdef TARGET_XARCH - // SSE2 has direct support for float/double/signed word/unsigned byte. - // SSE4.1 has direct support for int32/uint32/signed byte/unsigned word. - // For other integer types we compute min/max as follows - // - // int32/uint32 (SSE2) - // int64/uint64 (SSE2&SSE4): - // compResult = (op1 < op2) in case of Min - // (op1 > op2) in case of Max - // Min/Max(op1, op2) = Select(compResult, op1, op2) - // - // unsigned word (SSE2): - // op1 = op1 - 2^15 ; to make it fit within a signed word - // op2 = op2 - 2^15 ; to make it fit within a signed word - // result = SSE2 signed word Min/Max(op1, op2) - // result = result + 2^15 ; readjust it back - // - // signed byte (SSE2): - // op1 = op1 + 2^7 ; to make it unsigned - // op1 = op1 + 2^7 ; to make it unsigned - // result = SSE2 unsigned byte Min/Max(op1, op2) - // result = result - 2^15 ; readjust it back - - if (varTypeIsFloating(baseType) || baseType == TYP_SHORT || baseType == TYP_UBYTE || - (getSIMDSupportLevel() >= SIMD_SSE4_Supported && - (baseType == TYP_BYTE || baseType == TYP_INT || baseType == TYP_UINT || baseType == TYP_USHORT))) - { - // SSE2 or SSE4.1 has direct support - simdTree = gtNewSIMDNode(simdType, op1, op2, intrinsicId, baseType, size); - } - else if (baseType == TYP_USHORT || baseType == TYP_BYTE) - { - assert(getSIMDSupportLevel() == SIMD_SSE2_Supported); - int constVal; - SIMDIntrinsicID operIntrinsic; - SIMDIntrinsicID adjustIntrinsic; - var_types minMaxOperBaseType; - if (baseType == TYP_USHORT) - { - constVal = 0x80008000; - operIntrinsic = SIMDIntrinsicSub; - adjustIntrinsic = SIMDIntrinsicAdd; - minMaxOperBaseType = TYP_SHORT; - } - else - { - assert(baseType == TYP_BYTE); - constVal = 0x80808080; - operIntrinsic = SIMDIntrinsicAdd; - adjustIntrinsic = SIMDIntrinsicSub; - minMaxOperBaseType = TYP_UBYTE; - } - - GenTree* initVal = gtNewIconNode(constVal); - GenTree* constVector = gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, TYP_INT, size); - - // Assign constVector to a temp, since we intend to use it more than once - // TODO-CQ: We have quite a few such constant vectors constructed during - // the importation of SIMD intrinsics. Make sure that we have a single - // temp per distinct constant per method. - GenTree* tmp = fgInsertCommaFormTemp(&constVector, typeHnd); - - // op1 = op1 - constVector - // op2 = op2 - constVector - op1 = gtNewSIMDNode(simdType, op1, constVector, operIntrinsic, baseType, size); - op2 = gtNewSIMDNode(simdType, op2, tmp, operIntrinsic, baseType, size); - - // compute min/max of op1 and op2 considering them as if minMaxOperBaseType - simdTree = gtNewSIMDNode(simdType, op1, op2, intrinsicId, minMaxOperBaseType, size); - - // re-adjust the value by adding or subtracting constVector - tmp = gtNewLclvNode(tmp->AsLclVarCommon()->GetLclNum(), tmp->TypeGet()); - simdTree = gtNewSIMDNode(simdType, simdTree, tmp, adjustIntrinsic, baseType, size); - } -#elif defined(TARGET_ARM64) - // Arm64 has direct support for all types except int64/uint64 - // For which we compute min/max as follows - // - // int64/uint64 - // compResult = (op1 < op2) in case of Min - // (op1 > op2) in case of Max - // Min/Max(op1, op2) = Select(compResult, op1, op2) - if (baseType != TYP_ULONG && baseType != TYP_LONG) - { - simdTree = gtNewSIMDNode(simdType, op1, op2, intrinsicId, baseType, size); - } -#endif - else - { - GenTree* dupOp1 = nullptr; - GenTree* dupOp2 = nullptr; - GenTree* op1Assign = nullptr; - GenTree* op2Assign = nullptr; - unsigned op1LclNum; - unsigned op2LclNum; - - if ((op1->gtFlags & GTF_SIDE_EFFECT) != 0) - { - op1LclNum = lvaGrabTemp(true DEBUGARG("SIMD Min/Max")); - lvaSetStruct(op1LclNum, typeHnd, false); - dupOp1 = gtNewLclvNode(op1LclNum, op1->TypeGet()); - op1Assign = gtNewTempAssign(op1LclNum, op1); - op1 = gtNewLclvNode(op1LclNum, op1->TypeGet()); - } - else - { - dupOp1 = gtCloneExpr(op1); - } - - if ((op2->gtFlags & GTF_SIDE_EFFECT) != 0) - { - op2LclNum = lvaGrabTemp(true DEBUGARG("SIMD Min/Max")); - lvaSetStruct(op2LclNum, typeHnd, false); - dupOp2 = gtNewLclvNode(op2LclNum, op2->TypeGet()); - op2Assign = gtNewTempAssign(op2LclNum, op2); - op2 = gtNewLclvNode(op2LclNum, op2->TypeGet()); - } - else - { - dupOp2 = gtCloneExpr(op2); - } - - SIMDIntrinsicID relOpIntrinsic = - (intrinsicId == SIMDIntrinsicMin) ? SIMDIntrinsicLessThan : SIMDIntrinsicGreaterThan; - var_types relOpBaseType = baseType; - - // compResult = op1 relOp op2 - // simdTree = Select(compResult, op1, op2); - assert(dupOp1 != nullptr); - assert(dupOp2 != nullptr); - relOpIntrinsic = impSIMDRelOp(relOpIntrinsic, typeHnd, size, &relOpBaseType, &dupOp1, &dupOp2); - GenTree* compResult = gtNewSIMDNode(simdType, dupOp1, dupOp2, relOpIntrinsic, relOpBaseType, size); - unsigned compResultLclNum = lvaGrabTemp(true DEBUGARG("SIMD Min/Max")); - lvaSetStruct(compResultLclNum, typeHnd, false); - GenTree* compResultAssign = gtNewTempAssign(compResultLclNum, compResult); - compResult = gtNewLclvNode(compResultLclNum, compResult->TypeGet()); - simdTree = impSIMDSelect(typeHnd, baseType, size, compResult, op1, op2); - simdTree = gtNewOperNode(GT_COMMA, simdTree->TypeGet(), compResultAssign, simdTree); - - // Now create comma trees if we have created assignments of op1/op2 to temps - if (op2Assign != nullptr) - { - simdTree = gtNewOperNode(GT_COMMA, simdTree->TypeGet(), op2Assign, simdTree); - } - - if (op1Assign != nullptr) - { - simdTree = gtNewOperNode(GT_COMMA, simdTree->TypeGet(), op1Assign, simdTree); - } - } - - assert(simdTree != nullptr); - return simdTree; -#else // !(defined(TARGET_XARCH) || defined(TARGET_ARM64)) - assert(!"impSIMDMinMax() unimplemented on target arch"); - unreached(); -#endif // !(defined(TARGET_XARCH) || defined(TARGET_ARM64)) -} - //------------------------------------------------------------------------ // getOp1ForConstructor: Get the op1 for a constructor call. // @@ -2906,44 +2227,7 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, } break; - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicInstEquals: - { - op2 = impSIMDPopStack(simdType); - op1 = impSIMDPopStack(simdType, instMethod); - - assert(op1->TypeGet() == simdType); - assert(op2->TypeGet() == simdType); - - simdTree = gtNewSIMDNode(genActualType(callType), op1, op2, SIMDIntrinsicOpEquality, baseType, size); - if (simdType == TYP_SIMD12) - { - simdTree->gtFlags |= GTF_SIMD12_OP; - } - retVal = simdTree; - } - break; - - case SIMDIntrinsicOpInEquality: - { - // op1 is the first operand - // op2 is the second operand - op2 = impSIMDPopStack(simdType); - op1 = impSIMDPopStack(simdType, instMethod); - simdTree = gtNewSIMDNode(genActualType(callType), op1, op2, SIMDIntrinsicOpInEquality, baseType, size); - if (simdType == TYP_SIMD12) - { - simdTree->gtFlags |= GTF_SIMD12_OP; - } - retVal = simdTree; - } - break; - case SIMDIntrinsicEqual: - case SIMDIntrinsicLessThan: - case SIMDIntrinsicLessThanOrEqual: - case SIMDIntrinsicGreaterThan: - case SIMDIntrinsicGreaterThanOrEqual: { op2 = impSIMDPopStack(simdType); op1 = impSIMDPopStack(simdType, instMethod); @@ -2959,9 +2243,7 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, case SIMDIntrinsicMul: case SIMDIntrinsicDiv: case SIMDIntrinsicBitwiseAnd: - case SIMDIntrinsicBitwiseAndNot: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: { #if defined(DEBUG) // check for the cases where we don't support intrinsics. @@ -3010,48 +2292,11 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, op2 = impSIMDPopStack(simdType); op1 = impSIMDPopStack(simdType, instMethod); -#ifdef TARGET_XARCH - if (simdIntrinsicID == SIMDIntrinsicBitwiseAndNot) - { - // XARCH implements SIMDIntrinsicBitwiseAndNot as ~op1 & op2, while the - // software implementation does op1 & ~op2, so we need to swap the operands - - GenTree* tmp = op2; - op2 = op1; - op1 = tmp; - } -#endif // TARGET_XARCH - simdTree = gtNewSIMDNode(simdType, op1, op2, simdIntrinsicID, baseType, size); retVal = simdTree; } break; - case SIMDIntrinsicSelect: - { - // op3 is a SIMD variable that is the second source - // op2 is a SIMD variable that is the first source - // op1 is a SIMD variable which is the bit mask. - op3 = impSIMDPopStack(simdType); - op2 = impSIMDPopStack(simdType); - op1 = impSIMDPopStack(simdType); - - retVal = impSIMDSelect(clsHnd, baseType, size, op1, op2, op3); - } - break; - - case SIMDIntrinsicMin: - case SIMDIntrinsicMax: - { - // op1 is the first operand; if instance method, op1 is "this" arg - // op2 is the second operand - op2 = impSIMDPopStack(simdType); - op1 = impSIMDPopStack(simdType, instMethod); - - retVal = impSIMDMinMax(simdIntrinsicID, clsHnd, baseType, size, op1, op2); - } - break; - case SIMDIntrinsicGetItem: { // op1 is a SIMD variable that is "this" arg @@ -3118,43 +2363,6 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, } break; - case SIMDIntrinsicSqrt: - { -#if (defined(TARGET_XARCH) || defined(TARGET_ARM64)) && defined(DEBUG) - // SSE/AVX/ARM64 doesn't support sqrt on integer type vectors and hence - // should never be seen as an intrinsic here. See SIMDIntrinsicList.h - // for supported base types for this intrinsic. - if (!varTypeIsFloating(baseType)) - { - assert(!"Sqrt not supported on integer vectors\n"); - return nullptr; - } -#endif // (defined(TARGET_XARCH) || defined(TARGET_ARM64)) && defined(DEBUG) - - op1 = impSIMDPopStack(simdType); - - retVal = gtNewSIMDNode(genActualType(callType), op1, nullptr, simdIntrinsicID, baseType, size); - } - break; - - case SIMDIntrinsicCeil: - case SIMDIntrinsicFloor: -#if defined(TARGET_XARCH) - // Rounding instructions are only available from SSE4.1. - if (getSIMDSupportLevel() < SIMD_SSE4_Supported) - { - return nullptr; - } -#endif // defined(TARGET_XARCH) - op1 = impSIMDPopStack(simdType); - retVal = gtNewSIMDNode(genActualType(callType), op1, simdIntrinsicID, baseType, size); - break; - - case SIMDIntrinsicAbs: - op1 = impSIMDPopStack(simdType); - retVal = impSIMDAbs(clsHnd, baseType, size, op1); - break; - case SIMDIntrinsicGetW: retVal = impSIMDGetFixed(simdType, baseType, size, 3); break; diff --git a/src/coreclr/src/jit/simdashwintrinsic.cpp b/src/coreclr/src/jit/simdashwintrinsic.cpp index 1463ed30ca407..a4f07b0c2dc81 100644 --- a/src/coreclr/src/jit/simdashwintrinsic.cpp +++ b/src/coreclr/src/jit/simdashwintrinsic.cpp @@ -10,12 +10,12 @@ static const SimdAsHWIntrinsicInfo simdAsHWIntrinsicInfoArray[] = { // clang-format off #if defined(TARGET_XARCH) -#define SIMD_AS_HWINTRINSIC(classId, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ - {NI_##classId##_##name, #name, SimdAsHWIntrinsicClassId::classId, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, static_cast(flag)}, +#define SIMD_AS_HWINTRINSIC(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + {NI_##classId##_##id, name, SimdAsHWIntrinsicClassId::classId, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, static_cast(flag)}, #include "simdashwintrinsiclistxarch.h" #elif defined(TARGET_ARM64) -#define SIMD_AS_HWINTRINSIC(classId, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ - {NI_##classId##_##name, #name, SimdAsHWIntrinsicClassId::classId, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, static_cast(flag)}, +#define SIMD_AS_HWINTRINSIC(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + {NI_##classId##_##id, name, SimdAsHWIntrinsicClassId::classId, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, static_cast(flag)}, #include "simdashwintrinsiclistarm64.h" #else #error Unsupported platform @@ -65,6 +65,15 @@ NamedIntrinsic SimdAsHWIntrinsicInfo::lookupId(CORINFO_SIG_INFO* sig, return NI_Illegal; } + unsigned numArgs = sig->numArgs; + bool isInstanceMethod = false; + + if (sig->hasThis()) + { + numArgs++; + isInstanceMethod = true; + } + for (int i = 0; i < (NI_SIMD_AS_HWINTRINSIC_END - NI_SIMD_AS_HWINTRINSIC_START - 1); i++) { const SimdAsHWIntrinsicInfo& intrinsicInfo = simdAsHWIntrinsicInfoArray[i]; @@ -74,12 +83,12 @@ NamedIntrinsic SimdAsHWIntrinsicInfo::lookupId(CORINFO_SIG_INFO* sig, continue; } - if (sig->numArgs != static_cast(intrinsicInfo.numArgs)) + if (numArgs != static_cast(intrinsicInfo.numArgs)) { continue; } - if (sig->hasThis() != SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsicInfo.id)) + if (isInstanceMethod != SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsicInfo.id)) { continue; } @@ -170,30 +179,38 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, return nullptr; } - var_types retType = JITtype2varType(sig->retType); - var_types baseType = TYP_UNKNOWN; - var_types simdType = TYP_UNKNOWN; - unsigned simdSize = 0; + CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; + var_types retType = JITtype2varType(sig->retType); + var_types baseType = TYP_UNKNOWN; + var_types simdType = TYP_UNKNOWN; + unsigned simdSize = 0; + unsigned numArgs = sig->numArgs; + bool isInstanceMethod = false; // We want to resolve and populate the handle cache for this type even // if it isn't the basis for anything carried on the node. baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &simdSize); - assert(simdSize != 0); - - CORINFO_CLASS_HANDLE argClass; if (retType == TYP_STRUCT) { baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &simdSize); retType = getSIMDTypeForSize(simdSize); } - else + else if (numArgs != 0) { argClass = info.compCompHnd->getArgClass(sig, sig->args); baseType = getBaseTypeAndSizeOfSIMDType(argClass, &simdSize); } - if ((clsHnd == m_simdHandleCache->SIMDVectorHandle) && (sig->numArgs != 0)) + if (sig->hasThis()) + { + assert(SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsic)); + numArgs++; + + isInstanceMethod = true; + argClass = clsHnd; + } + else if ((clsHnd == m_simdHandleCache->SIMDVectorHandle) && (numArgs != 0)) { // We need to fixup the clsHnd in the case we are an intrinsic on Vector // The first argument will be the appropriate Vector handle to use @@ -206,15 +223,16 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &simdSize); } - simdType = getSIMDTypeForSize(simdSize); - assert(varTypeIsSIMD(simdType)); - - if (!varTypeIsArithmetic(baseType)) + if (!varTypeIsArithmetic(baseType) || (simdSize == 0)) { - // We only support intrinsics on the 10 primitive arithmetic types + // We get here for a devirtualization of IEquatable`1.Equals + // or if the user tries to use Vector with an unsupported type return nullptr; } + simdType = getSIMDTypeForSize(simdSize); + assert(varTypeIsSIMD(simdType)); + NamedIntrinsic hwIntrinsic = SimdAsHWIntrinsicInfo::lookupHWIntrinsic(intrinsic, baseType); if ((hwIntrinsic == NI_Illegal) || !varTypeIsSIMD(simdType)) @@ -250,14 +268,19 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, GenTree* op1 = nullptr; GenTree* op2 = nullptr; - bool isInstanceMethod = SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsic); - - switch (sig->numArgs) + switch (numArgs) { + case 0: + { + assert(!SimdAsHWIntrinsicInfo::NeedsOperandsSwapped(intrinsic)); + return gtNewSimdAsHWIntrinsicNode(retType, hwIntrinsic, baseType, simdSize); + } + case 1: { - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + argType = isInstanceMethod ? simdType + : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); assert(!SimdAsHWIntrinsicInfo::NeedsOperandsSwapped(intrinsic)); return gtNewSimdAsHWIntrinsicNode(retType, op1, hwIntrinsic, baseType, simdSize); @@ -265,12 +288,13 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, case 2: { - CORINFO_ARG_LIST_HANDLE arg2 = info.compCompHnd->getArgNext(argList); + CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + argType = isInstanceMethod ? simdType + : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); if (SimdAsHWIntrinsicInfo::NeedsOperandsSwapped(intrinsic)) { @@ -311,18 +335,31 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, assert(retType != TYP_UNKNOWN); assert(varTypeIsArithmetic(baseType)); assert(simdSize != 0); - assert(varTypeIsSIMD(getSIMDTypeForSize(simdSize))); assert(SimdAsHWIntrinsicInfo::lookupHWIntrinsic(intrinsic, baseType) == intrinsic); - CORINFO_ARG_LIST_HANDLE argList = sig->args; - var_types argType = TYP_UNKNOWN; - CORINFO_CLASS_HANDLE argClass; + var_types simdType = getSIMDTypeForSize(simdSize); + assert(varTypeIsSIMD(simdType)); + + CORINFO_ARG_LIST_HANDLE argList = sig->args; + var_types argType = TYP_UNKNOWN; + CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; GenTree* op1 = nullptr; GenTree* op2 = nullptr; + GenTree* op3 = nullptr; SimdAsHWIntrinsicClassId classId = SimdAsHWIntrinsicInfo::lookupClassId(intrinsic); - bool isInstanceMethod = SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsic); + unsigned numArgs = sig->numArgs; + bool isInstanceMethod = false; + + if (sig->hasThis()) + { + assert(SimdAsHWIntrinsicInfo::IsInstanceMethod(intrinsic)); + numArgs++; + + isInstanceMethod = true; + argClass = clsHnd; + } #if defined(TARGET_XARCH) bool isVectorT256 = (SimdAsHWIntrinsicInfo::lookupClassId(intrinsic) == SimdAsHWIntrinsicClassId::VectorT256); @@ -342,12 +379,64 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, assert(!isVectorT256 || compIsaSupportedDebugOnly(InstructionSet_AVX2)); #endif - switch (sig->numArgs) + switch (numArgs) { + case 0: + { + switch (intrinsic) + { +#if defined(TARGET_XARCH) + case NI_VectorT128_get_Count: + case NI_VectorT256_get_Count: + { + GenTreeIntCon* countNode = gtNewIconNode(getSIMDVectorLength(simdSize, baseType), TYP_INT); + countNode->gtFlags |= GTF_ICON_SIMD_COUNT; + return countNode; + } +#elif defined(TARGET_ARM64) + case NI_VectorT128_get_Count: + { + GenTreeIntCon* countNode = gtNewIconNode(getSIMDVectorLength(simdSize, baseType), TYP_INT); + countNode->gtFlags |= GTF_ICON_SIMD_COUNT; + return countNode; + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + default: + { + // Some platforms warn about unhandled switch cases + // We handle it more generally via the assert and nullptr return below. + break; + } + } + } + case 1: { - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + bool isOpExplicit = (intrinsic == NI_VectorT128_op_Explicit); + +#if defined(TARGET_XARCH) + isOpExplicit |= (intrinsic == NI_VectorT256_op_Explicit); +#endif + + if (isOpExplicit) + { + // We fold away the cast here, as it only exists to satisfy the + // type system. It is safe to do this here since the op1 type + // and the signature return type are both the same TYP_SIMD. + + op1 = impSIMDPopStack(retType, /* expectAddr: */ false, sig->retTypeClass); + SetOpLclRelatedToSIMDIntrinsic(op1); + assert(op1->gtType == getSIMDTypeForSize(getSIMDTypeSizeInBytes(sig->retTypeSigClass))); + + return op1; + } + + argType = isInstanceMethod ? simdType + : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); assert(!SimdAsHWIntrinsicInfo::NeedsOperandsSwapped(intrinsic)); @@ -447,12 +536,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, case 2: { - CORINFO_ARG_LIST_HANDLE arg2 = info.compCompHnd->getArgNext(argList); + CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); - argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); - op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + argType = isInstanceMethod ? simdType + : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); assert(!SimdAsHWIntrinsicInfo::NeedsOperandsSwapped(intrinsic)); @@ -681,7 +771,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #else #error Unsupported platform -#endif // TARGET_XARCH +#endif // !TARGET_XARCH && !TARGET_ARM64 default: { @@ -692,6 +782,49 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } break; } + + case 3: + { + CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); + CORINFO_ARG_LIST_HANDLE arg3 = info.compCompHnd->getArgNext(arg2); + + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg3, &argClass))); + op3 = getArgForHWIntrinsic(argType, argClass); + + argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); + op2 = getArgForHWIntrinsic(argType, argClass); + + argType = isInstanceMethod ? simdType + : JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass))); + op1 = getArgForHWIntrinsic(argType, argClass, isInstanceMethod); + + assert(!SimdAsHWIntrinsicInfo::NeedsOperandsSwapped(intrinsic)); + + switch (intrinsic) + { +#if defined(TARGET_XARCH) + case NI_VectorT128_ConditionalSelect: + case NI_VectorT256_ConditionalSelect: + { + return impSimdAsHWIntrinsicCndSel(clsHnd, retType, baseType, simdSize, op1, op2, op3); + } +#elif defined(TARGET_ARM64) + case NI_VectorT128_ConditionalSelect: + { + return impSimdAsHWIntrinsicCndSel(clsHnd, retType, baseType, simdSize, op1, op2, op3); + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + default: + { + // Some platforms warn about unhandled switch cases + // We handle it more generally via the assert and nullptr return below. + break; + } + } + } } assert(!"Unexpected SimdAsHWIntrinsic"); @@ -723,7 +856,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicCndSel(CORINFO_CLASS_HANDLE clsHnd, { assert(featureSIMD); assert(retType != TYP_UNKNOWN); - assert(varTypeIsIntegral(baseType)); + assert(varTypeIsArithmetic(baseType)); assert(simdSize != 0); assert(varTypeIsSIMD(getSIMDTypeForSize(simdSize))); assert(op1 != nullptr); diff --git a/src/coreclr/src/jit/simdashwintrinsiclistarm64.h b/src/coreclr/src/jit/simdashwintrinsiclistarm64.h index cfd47939cf3dc..9621486e69657 100644 --- a/src/coreclr/src/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/simdashwintrinsiclistarm64.h @@ -6,12 +6,24 @@ #ifndef SIMD_AS_HWINTRINSIC #error Define SIMD_AS_HWINTRINSIC before including this file #endif + +#if defined(SIMD_AS_HWINTRINSIC_ID) || defined(SIMD_AS_HWINTRINSIC_NM) +#error SIMD_AS_HWINTRINSIC_ID and SIMD_AS_HWINTRINSIC_NM should not be defined before including this file +#endif /*****************************************************************************/ // clang-format off #ifdef FEATURE_HW_INTRINSICS +// Defines a SimdAsHWIntrinsic where the name is implicitly taken from the id +#define SIMD_AS_HWINTRINSIC_ID(classId, id, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + SIMD_AS_HWINTRINSIC(classId, id, #id, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) + +// Defines a SimdAsHWIntrinsic where the name is explicit +#define SIMD_AS_HWINTRINSIC_NM(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + SIMD_AS_HWINTRINSIC(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) + /* Note * Each intrinsic has a unique Intrinsic ID with type of `enum NamedIntrinsic` * Each intrinsic has a `NumArg` for number of parameters @@ -22,65 +34,94 @@ */ // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector2 Intrinsics -SIMD_AS_HWINTRINSIC(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Vector2, EqualsInstance, "Equals", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector64_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector64_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector64_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector64_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector3 Intrinsics -SIMD_AS_HWINTRINSIC(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Vector3, EqualsInstance, "Equals", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector4 Intrinsics -SIMD_AS_HWINTRINSIC(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Vector4, EqualsInstance, "Equals", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector Intrinsics -SIMD_AS_HWINTRINSIC(VectorT128, Abs, 1, {NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Arm64_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_AdvSimd_Arm64_Abs}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, AndNot, 2, {NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, Equals, 2, {NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_Arm64_CompareEqual, NI_AdvSimd_Arm64_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_Arm64_CompareEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, GreaterThan, 2, {NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_Arm64_CompareGreaterThan, NI_AdvSimd_Arm64_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_Arm64_CompareGreaterThan}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, GreaterThanOrEqual, 2, {NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_Arm64_CompareGreaterThanOrEqual, NI_AdvSimd_Arm64_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_Arm64_CompareGreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, LessThan, 2, {NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_Arm64_CompareLessThan, NI_AdvSimd_Arm64_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_Arm64_CompareLessThan}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, LessThanOrEqual, 2, {NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_Arm64_CompareLessThanOrEqual, NI_AdvSimd_Arm64_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_Arm64_CompareLessThanOrEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, Max, 2, {NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_AdvSimd_Max, NI_AdvSimd_Arm64_Max}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, Min, 2, {NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_AdvSimd_Min, NI_AdvSimd_Arm64_Min}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Addition, 2, {NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Arm64_Add}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_BitwiseAnd, 2, {NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_BitwiseOr, 2, {NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_AdvSimd_Arm64_Divide}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_ExclusiveOr, 2, {NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Multiply, 2, {NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_AdvSimd_Arm64_Multiply}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Subtraction, 2, {NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Arm64_Subtract}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Abs, 1, {NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Arm64_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_AdvSimd_Arm64_Abs}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, AndNot, 2, {NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Ceiling, NI_AdvSimd_Ceiling}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConditionalSelect, 3, {NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Equals, 2, {NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_Arm64_CompareEqual, NI_AdvSimd_Arm64_CompareEqual, NI_AdvSimd_CompareEqual, NI_AdvSimd_Arm64_CompareEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(VectorT128, EqualsInstance, "Equals", 2, {NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Floor, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Floor, NI_AdvSimd_Floor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, get_AllBitsSet, 0, {NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, get_Count, 0, {NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, get_Zero, 0, {NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, GreaterThan, 2, {NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_Arm64_CompareGreaterThan, NI_AdvSimd_Arm64_CompareGreaterThan, NI_AdvSimd_CompareGreaterThan, NI_AdvSimd_Arm64_CompareGreaterThan}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, GreaterThanOrEqual, 2, {NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_Arm64_CompareGreaterThanOrEqual, NI_AdvSimd_Arm64_CompareGreaterThanOrEqual, NI_AdvSimd_CompareGreaterThanOrEqual, NI_AdvSimd_Arm64_CompareGreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, LessThan, 2, {NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_Arm64_CompareLessThan, NI_AdvSimd_Arm64_CompareLessThan, NI_AdvSimd_CompareLessThan, NI_AdvSimd_Arm64_CompareLessThan}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, LessThanOrEqual, 2, {NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_Arm64_CompareLessThanOrEqual, NI_AdvSimd_Arm64_CompareLessThanOrEqual, NI_AdvSimd_CompareLessThanOrEqual, NI_AdvSimd_Arm64_CompareLessThanOrEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Max, 2, {NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_AdvSimd_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_AdvSimd_Max, NI_AdvSimd_Arm64_Max}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Min, 2, {NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_AdvSimd_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_AdvSimd_Min, NI_AdvSimd_Arm64_Min}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Addition, 2, {NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Add, NI_AdvSimd_Arm64_Add}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_BitwiseAnd, 2, {NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And, NI_AdvSimd_And}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_BitwiseOr, 2, {NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or, NI_AdvSimd_Or}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Divide, NI_AdvSimd_Arm64_Divide}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Equality, 2, {NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_ExclusiveOr, 2, {NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor, NI_AdvSimd_Xor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Explicit, 1, {NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Inequality, 2, {NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Multiply, 2, {NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_AdvSimd_Multiply, NI_Illegal, NI_Illegal, NI_AdvSimd_Multiply, NI_AdvSimd_Arm64_Multiply}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Subtraction, 2, {NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Subtract, NI_AdvSimd_Arm64_Subtract}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Arm64_Sqrt, NI_AdvSimd_Arm64_Sqrt}, SimdAsHWIntrinsicFlag::None) + +#undef SIMD_AS_HWINTRINSIC_NM +#undef SIMD_AS_HWINTRINSIC_ID #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/src/jit/simdashwintrinsiclistxarch.h b/src/coreclr/src/jit/simdashwintrinsiclistxarch.h index 8f2ac6264041c..d13153db4aad7 100644 --- a/src/coreclr/src/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/src/jit/simdashwintrinsiclistxarch.h @@ -6,12 +6,24 @@ #ifndef SIMD_AS_HWINTRINSIC #error Define SIMD_AS_HWINTRINSIC before including this file #endif + +#if defined(SIMD_AS_HWINTRINSIC_ID) || defined(SIMD_AS_HWINTRINSIC_NM) +#error SIMD_AS_HWINTRINSIC_ID and SIMD_AS_HWINTRINSIC_NM should not be defined before including this file +#endif /*****************************************************************************/ // clang-format off #ifdef FEATURE_HW_INTRINSICS +// Defines a SimdAsHWIntrinsic where the name is implicitly taken from the id +#define SIMD_AS_HWINTRINSIC_ID(classId, id, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + SIMD_AS_HWINTRINSIC(classId, id, #id, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) + +// Defines a SimdAsHWIntrinsic where the name is explicit +#define SIMD_AS_HWINTRINSIC_NM(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) \ + SIMD_AS_HWINTRINSIC(classId, id, name, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, flag) + /* Note * Each intrinsic has a unique Intrinsic ID with type of `enum NamedIntrinsic` * Each intrinsic has a `NumArg` for number of parameters @@ -22,87 +34,127 @@ */ // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector2 Intrinsics -SIMD_AS_HWINTRINSIC(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector2, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Vector2, EqualsInstance, "Equals", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector3 Intrinsics -SIMD_AS_HWINTRINSIC(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector3, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Vector3, EqualsInstance, "Equals", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector4 Intrinsics -SIMD_AS_HWINTRINSIC(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(Vector4, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Vector4, EqualsInstance, "Equals", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector128_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector Intrinsics -SIMD_AS_HWINTRINSIC(VectorT128, Abs, 1, {NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, AndNot, 2, {NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE_AndNot, NI_SSE2_AndNot}, SimdAsHWIntrinsicFlag::NeedsOperandsSwapped) -SIMD_AS_HWINTRINSIC(VectorT128, Equals, 2, {NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_VectorT128_Equals, NI_VectorT128_Equals, NI_SSE_CompareEqual, NI_SSE2_CompareEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, GreaterThan, 2, {NI_SSE2_CompareGreaterThan, NI_VectorT128_GreaterThan, NI_SSE2_CompareGreaterThan, NI_VectorT128_GreaterThan, NI_SSE2_CompareGreaterThan, NI_VectorT128_GreaterThan, NI_VectorT128_GreaterThan, NI_VectorT128_GreaterThan, NI_SSE_CompareGreaterThan, NI_SSE2_CompareGreaterThan}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, GreaterThanOrEqual, 2, {NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_SSE_CompareGreaterThanOrEqual, NI_SSE2_CompareGreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, LessThan, 2, {NI_SSE2_CompareLessThan, NI_VectorT128_LessThan, NI_SSE2_CompareLessThan, NI_VectorT128_LessThan, NI_SSE2_CompareLessThan, NI_VectorT128_LessThan, NI_VectorT128_LessThan, NI_VectorT128_LessThan, NI_SSE_CompareLessThan, NI_SSE2_CompareLessThan}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, LessThanOrEqual, 2, {NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_SSE_CompareLessThanOrEqual, NI_SSE2_CompareLessThanOrEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, Max, 2, {NI_VectorT128_Max, NI_SSE2_Max, NI_SSE2_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_SSE_Max, NI_SSE2_Max}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, Min, 2, {NI_VectorT128_Min, NI_SSE2_Min, NI_SSE2_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_SSE_Min, NI_SSE2_Min}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Addition, 2, {NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE_Add, NI_SSE2_Add}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_BitwiseAnd, 2, {NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE_And, NI_SSE2_And}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_BitwiseOr, 2, {NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE_Or, NI_SSE2_Or}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Divide, NI_SSE2_Divide}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_ExclusiveOr, 2, {NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE_Xor, NI_SSE2_Xor}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_SSE2_MultiplyLow, NI_Illegal, NI_VectorT128_op_Multiply, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_SSE2_Multiply}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT128, op_Subtraction, 2, {NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE_Subtract, NI_SSE2_Subtract}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Abs, 1, {NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, AndNot, 2, {NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE_AndNot, NI_SSE2_AndNot}, SimdAsHWIntrinsicFlag::NeedsOperandsSwapped) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE41_Ceiling, NI_SSE41_Ceiling}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, ConditionalSelect, 3, {NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Equals, 2, {NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_SSE2_CompareEqual, NI_VectorT128_Equals, NI_VectorT128_Equals, NI_SSE_CompareEqual, NI_SSE2_CompareEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(VectorT128, EqualsInstance, "Equals", 2, {NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Floor, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE41_Floor, NI_SSE41_Floor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, get_AllBitsSet, 0, {NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet, NI_Vector128_get_AllBitsSet}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, get_Count, 0, {NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count, NI_VectorT128_get_Count}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, get_Zero, 0, {NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero, NI_Vector128_get_Zero}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, GreaterThan, 2, {NI_SSE2_CompareGreaterThan, NI_VectorT128_GreaterThan, NI_SSE2_CompareGreaterThan, NI_VectorT128_GreaterThan, NI_SSE2_CompareGreaterThan, NI_VectorT128_GreaterThan, NI_VectorT128_GreaterThan, NI_VectorT128_GreaterThan, NI_SSE_CompareGreaterThan, NI_SSE2_CompareGreaterThan}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, GreaterThanOrEqual, 2, {NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_VectorT128_GreaterThanOrEqual, NI_SSE_CompareGreaterThanOrEqual, NI_SSE2_CompareGreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, LessThan, 2, {NI_SSE2_CompareLessThan, NI_VectorT128_LessThan, NI_SSE2_CompareLessThan, NI_VectorT128_LessThan, NI_SSE2_CompareLessThan, NI_VectorT128_LessThan, NI_VectorT128_LessThan, NI_VectorT128_LessThan, NI_SSE_CompareLessThan, NI_SSE2_CompareLessThan}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, LessThanOrEqual, 2, {NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_VectorT128_LessThanOrEqual, NI_SSE_CompareLessThanOrEqual, NI_SSE2_CompareLessThanOrEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Max, 2, {NI_VectorT128_Max, NI_SSE2_Max, NI_SSE2_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_VectorT128_Max, NI_SSE_Max, NI_SSE2_Max}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, Min, 2, {NI_VectorT128_Min, NI_SSE2_Min, NI_SSE2_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_VectorT128_Min, NI_SSE_Min, NI_SSE2_Min}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Addition, 2, {NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE2_Add, NI_SSE_Add, NI_SSE2_Add}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_BitwiseAnd, 2, {NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE2_And, NI_SSE_And, NI_SSE2_And}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_BitwiseOr, 2, {NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE2_Or, NI_SSE_Or, NI_SSE2_Or}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Divide, NI_SSE2_Divide}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Equality, 2, {NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality, NI_Vector128_op_Equality}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_ExclusiveOr, 2, {NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE2_Xor, NI_SSE_Xor, NI_SSE2_Xor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Explicit, 1, {NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit, NI_VectorT128_op_Explicit}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Inequality, 2, {NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality, NI_Vector128_op_Inequality}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_SSE2_MultiplyLow, NI_Illegal, NI_VectorT128_op_Multiply, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Multiply, NI_SSE2_Multiply}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, op_Subtraction, 2, {NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE2_Subtract, NI_SSE_Subtract, NI_SSE2_Subtract}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE_Sqrt, NI_SSE2_Sqrt}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* -// ISA Function name NumArg Instructions Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector Intrinsics -SIMD_AS_HWINTRINSIC(VectorT256, Abs, 1, {NI_AVX2_Abs, NI_VectorT256_Abs, NI_AVX2_Abs, NI_VectorT256_Abs, NI_AVX2_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, AndNot, 2, {NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX_AndNot, NI_AVX_AndNot}, SimdAsHWIntrinsicFlag::NeedsOperandsSwapped) -SIMD_AS_HWINTRINSIC(VectorT256, Equals, 2, {NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX_CompareEqual, NI_AVX_CompareEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, GreaterThan, 2, {NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX_CompareGreaterThan, NI_AVX_CompareGreaterThan}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, GreaterThanOrEqual, 2, {NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_AVX_CompareGreaterThanOrEqual, NI_AVX_CompareGreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, LessThan, 2, {NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX_CompareLessThan, NI_AVX_CompareLessThan}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, LessThanOrEqual, 2, {NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_AVX_CompareLessThanOrEqual, NI_AVX_CompareLessThanOrEqual}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, Max, 2, {NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_VectorT256_Max, NI_VectorT256_Max, NI_AVX_Max, NI_AVX_Max}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, Min, 2, {NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_VectorT256_Min, NI_VectorT256_Min, NI_AVX_Min, NI_AVX_Min}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_Addition, 2, {NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX_Add, NI_AVX_Add}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_BitwiseAnd, 2, {NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX_And, NI_AVX_And}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_BitwiseOr, 2, {NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX_Or, NI_AVX_Or}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Divide, NI_AVX_Divide}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_ExclusiveOr, 2, {NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX_Xor, NI_AVX_Xor}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_AVX2_MultiplyLow, NI_Illegal, NI_AVX2_MultiplyLow, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Multiply, NI_AVX_Multiply}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC(VectorT256, op_Subtraction, 2, {NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX_Subtract, NI_AVX_Subtract}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, Abs, 1, {NI_AVX2_Abs, NI_VectorT256_Abs, NI_AVX2_Abs, NI_VectorT256_Abs, NI_AVX2_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, AndNot, 2, {NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX_AndNot, NI_AVX_AndNot}, SimdAsHWIntrinsicFlag::NeedsOperandsSwapped) +SIMD_AS_HWINTRINSIC_ID(VectorT256, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Ceiling, NI_AVX_Ceiling}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, ConditionalSelect, 3, {NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, Equals, 2, {NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX2_CompareEqual, NI_AVX_CompareEqual, NI_AVX_CompareEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(VectorT256, EqualsInstance, "Equals", 2, {NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(VectorT256, Floor, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Floor, NI_AVX_Floor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, get_AllBitsSet, 0, {NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet, NI_Vector256_get_AllBitsSet}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, get_Count, 0, {NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count, NI_VectorT256_get_Count}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, get_Zero, 0, {NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero, NI_Vector256_get_Zero}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, GreaterThan, 2, {NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX2_CompareGreaterThan, NI_VectorT256_GreaterThan, NI_AVX_CompareGreaterThan, NI_AVX_CompareGreaterThan}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, GreaterThanOrEqual, 2, {NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_VectorT256_GreaterThanOrEqual, NI_AVX_CompareGreaterThanOrEqual, NI_AVX_CompareGreaterThanOrEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, LessThan, 2, {NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX2_CompareLessThan, NI_VectorT256_LessThan, NI_AVX_CompareLessThan, NI_AVX_CompareLessThan}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, LessThanOrEqual, 2, {NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_VectorT256_LessThanOrEqual, NI_AVX_CompareLessThanOrEqual, NI_AVX_CompareLessThanOrEqual}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, Max, 2, {NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_AVX2_Max, NI_VectorT256_Max, NI_VectorT256_Max, NI_AVX_Max, NI_AVX_Max}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, Min, 2, {NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_AVX2_Min, NI_VectorT256_Min, NI_VectorT256_Min, NI_AVX_Min, NI_AVX_Min}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Addition, 2, {NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX2_Add, NI_AVX_Add, NI_AVX_Add}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_BitwiseAnd, 2, {NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX2_And, NI_AVX_And, NI_AVX_And}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_BitwiseOr, 2, {NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX2_Or, NI_AVX_Or, NI_AVX_Or}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Divide, NI_AVX_Divide}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Equality, 2, {NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality, NI_Vector256_op_Equality}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_ExclusiveOr, 2, {NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX2_Xor, NI_AVX_Xor, NI_AVX_Xor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Explicit, 1, {NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit, NI_VectorT256_op_Explicit}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Inequality, 2, {NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality, NI_Vector256_op_Inequality}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_AVX2_MultiplyLow, NI_Illegal, NI_AVX2_MultiplyLow, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Multiply, NI_AVX_Multiply}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, op_Subtraction, 2, {NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX2_Subtract, NI_AVX_Subtract, NI_AVX_Subtract}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT256, SquareRoot, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Sqrt, NI_AVX_Sqrt}, SimdAsHWIntrinsicFlag::None) + +#undef SIMD_AS_HWINTRINSIC_NM +#undef SIMD_AS_HWINTRINSIC_ID #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/src/jit/simdcodegenxarch.cpp b/src/coreclr/src/jit/simdcodegenxarch.cpp index 8ca69e35be37a..e6aa4db08fe54 100644 --- a/src/coreclr/src/jit/simdcodegenxarch.cpp +++ b/src/coreclr/src/jit/simdcodegenxarch.cpp @@ -130,21 +130,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type } break; - case SIMDIntrinsicSqrt: - if (baseType == TYP_FLOAT) - { - result = INS_sqrtps; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_sqrtpd; - } - else - { - unreached(); - } - break; - case SIMDIntrinsicAdd: if (baseType == TYP_FLOAT) { @@ -233,108 +218,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type } break; - case SIMDIntrinsicMin: - if (baseType == TYP_FLOAT) - { - result = INS_minps; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_minpd; - } - else if (baseType == TYP_UBYTE) - { - result = INS_pminub; - } - else if (baseType == TYP_SHORT) - { - result = INS_pminsw; - } - else if (compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported) - { - if (baseType == TYP_BYTE) - { - result = INS_pminsb; - } - else if (baseType == TYP_USHORT) - { - result = INS_pminuw; - } - else if (baseType == TYP_INT) - { - result = INS_pminsd; - } - else if (baseType == TYP_UINT) - { - result = INS_pminud; - } - } - else - { - unreached(); - } - break; - - case SIMDIntrinsicMax: - if (baseType == TYP_FLOAT) - { - result = INS_maxps; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_maxpd; - } - else if (baseType == TYP_UBYTE) - { - result = INS_pmaxub; - } - else if (baseType == TYP_SHORT) - { - result = INS_pmaxsw; - } - else if (compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported) - { - if (baseType == TYP_BYTE) - { - result = INS_pmaxsb; - } - else if (baseType == TYP_USHORT) - { - result = INS_pmaxuw; - } - else if (baseType == TYP_INT) - { - result = INS_pmaxsd; - } - else if (baseType == TYP_UINT) - { - result = INS_pmaxud; - } - } - else - { - unreached(); - } - break; - - case SIMDIntrinsicAbs: - if (compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported) - { - if (baseType == TYP_INT) - { - result = INS_pabsd; - } - else if (baseType == TYP_SHORT) - { - result = INS_pabsw; - } - else if (baseType == TYP_BYTE) - { - result = INS_pabsb; - } - } - break; - case SIMDIntrinsicEqual: if (baseType == TYP_FLOAT) { @@ -367,65 +250,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type } break; - case SIMDIntrinsicLessThan: - // Packed integers use > with swapped operands - assert(baseType != TYP_INT); - - if (baseType == TYP_FLOAT) - { - result = INS_cmpps; - assert(ival != nullptr); - *ival = 1; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_cmppd; - assert(ival != nullptr); - *ival = 1; - } - break; - - case SIMDIntrinsicLessThanOrEqual: - // Packed integers use (a==b) || ( b > a) in place of a <= b. - assert(baseType != TYP_INT); - - if (baseType == TYP_FLOAT) - { - result = INS_cmpps; - assert(ival != nullptr); - *ival = 2; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_cmppd; - assert(ival != nullptr); - *ival = 2; - } - break; - - case SIMDIntrinsicGreaterThan: - // Packed float/double use < with swapped operands - assert(!varTypeIsFloating(baseType)); - - // SSE2 supports only signed > - if (baseType == TYP_INT) - { - result = INS_pcmpgtd; - } - else if (baseType == TYP_SHORT) - { - result = INS_pcmpgtw; - } - else if (baseType == TYP_BYTE) - { - result = INS_pcmpgtb; - } - else if ((baseType == TYP_LONG) && (compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported)) - { - result = INS_pcmpgtq; - } - break; - case SIMDIntrinsicBitwiseAnd: if (baseType == TYP_FLOAT) { @@ -441,25 +265,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type } break; - case SIMDIntrinsicBitwiseAndNot: - if (baseType == TYP_FLOAT) - { - result = INS_andnps; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_andnpd; - } - else if (baseType == TYP_INT) - { - result = INS_pandn; - } - else if (varTypeIsIntegral(baseType)) - { - result = INS_pandn; - } - break; - case SIMDIntrinsicBitwiseOr: if (baseType == TYP_FLOAT) { @@ -475,21 +280,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type } break; - case SIMDIntrinsicBitwiseXor: - if (baseType == TYP_FLOAT) - { - result = INS_xorps; - } - else if (baseType == TYP_DOUBLE) - { - result = INS_xorpd; - } - else if (varTypeIsIntegral(baseType)) - { - result = INS_pxor; - } - break; - case SIMDIntrinsicCast: result = INS_movaps; break; @@ -645,26 +435,6 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type result = INS_insertps; break; - case SIMDIntrinsicCeil: - case SIMDIntrinsicFloor: - if (compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported) - { - if (baseType == TYP_FLOAT) - { - result = INS_roundps; - } - else - { - assert(baseType == TYP_DOUBLE); - result = INS_roundpd; - } - - assert(ival != nullptr); - *ival = (intrinsicId == SIMDIntrinsicCeil) ? ROUNDPS_TOWARD_POSITIVE_INFINITY_IMM - : ROUNDPS_TOWARD_NEGATIVE_INFINITY_IMM; - } - break; - default: assert(!"Unsupported SIMD intrinsic"); unreached(); @@ -760,10 +530,10 @@ void CodeGen::genSIMDScalarMove( void CodeGen::genSIMDZero(var_types targetType, var_types baseType, regNumber targetReg) { - // We just use `INS_xorps` instead of `getOpForSIMDIntrinsic(SIMDIntrinsicBitwiseXor, baseType)` - // since `genSIMDZero` is used for both `System.Numerics.Vectors` and HardwareIntrinsics. Modern - // CPUs handle this specially in the renamer and it never hits the execution pipeline, additionally - // `INS_xorps` is always available (when using either the legacy or VEX encoding). + // We just use `INS_xorps` since `genSIMDZero` is used for both `System.Numerics.Vectors` and + // HardwareIntrinsics. Modern CPUs handle this specially in the renamer and it never hits the + // execution pipeline, additionally `INS_xorps` is always available (when using either the + // legacy or VEX encoding). inst_RV_RV(INS_xorps, targetReg, targetReg, targetType, emitActualTypeSize(targetType)); } @@ -1062,8 +832,7 @@ void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode) // void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode) { - assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicSqrt || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicCast || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicAbs); + assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicCast); GenTree* op1 = simdNode->gtGetOp1(); var_types baseType = simdNode->gtSIMDBaseType; @@ -1080,32 +849,6 @@ void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode) genProduceReg(simdNode); } -//---------------------------------------------------------------------------------- -// genSIMDIntrinsicUnOpWithImm: Generate code for SIMD Intrinsic unary operations with an imm8, such as Ceil. -// -// Arguments: -// simdNode - The GT_SIMD node -// -// Return Value: -// None. -// -void CodeGen::genSIMDIntrinsicUnOpWithImm(GenTreeSIMD* simdNode) -{ - assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicCeil || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicFloor); - - GenTree* op1 = simdNode->gtGetOp1(); - var_types baseType = simdNode->gtSIMDBaseType; - regNumber targetReg = simdNode->GetRegNum(); - assert(targetReg != REG_NA); - var_types targetType = simdNode->TypeGet(); - - regNumber op1Reg = genConsumeReg(op1); - unsigned ival; - instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType, &ival); - assert((ival >= 0) && (ival <= 255)); - GetEmitter()->emitIns_R_R_I(ins, emitActualTypeSize(targetType), targetReg, op1Reg, (int8_t)ival); -} - //---------------------------------------------------------------------------------- // genSIMDIntrinsic32BitConvert: Generate code for 32-bit SIMD Convert (int/uint <-> float) // @@ -1627,7 +1370,26 @@ void CodeGen::genSIMDIntrinsicWiden(GenTreeSIMD* simdNode) genSIMDZero(simdType, baseType, tmpReg); if (!varTypeIsUnsigned(baseType)) { - instruction compareIns = getOpForSIMDIntrinsic(SIMDIntrinsicGreaterThan, baseType); + instruction compareIns = INS_invalid; + + if (baseType == TYP_INT) + { + compareIns = INS_pcmpgtd; + } + else if (baseType == TYP_SHORT) + { + compareIns = INS_pcmpgtw; + } + else if (baseType == TYP_BYTE) + { + compareIns = INS_pcmpgtb; + } + else if ((baseType == TYP_LONG) && (compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported)) + { + compareIns = INS_pcmpgtq; + } + + assert(compareIns != INS_invalid); inst_RV_RV(compareIns, tmpReg, targetReg, simdType, emitSize); } inst_RV_RV(widenIns, targetReg, tmpReg, simdType); @@ -1797,10 +1559,7 @@ void CodeGen::genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode) assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicAdd || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicSub || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicMul || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicDiv || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseAnd || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseAndNot || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseOr || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseXor || simdNode->gtSIMDIntrinsicID == SIMDIntrinsicMin || - simdNode->gtSIMDIntrinsicID == SIMDIntrinsicMax); + simdNode->gtSIMDIntrinsicID == SIMDIntrinsicBitwiseOr); GenTree* op1 = simdNode->gtGetOp1(); GenTree* op2 = simdNode->gtGetOp2(); @@ -1997,7 +1756,6 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) switch (simdNode->gtSIMDIntrinsicID) { case SIMDIntrinsicEqual: - case SIMDIntrinsicGreaterThan: { assert(targetReg != REG_NA); @@ -2010,12 +1768,6 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) } #endif - // Greater-than: Floating point vectors use "<" with swapped operands - if (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicGreaterThan) - { - assert(!varTypeIsFloating(baseType)); - } - unsigned ival = 0; instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType, &ival); @@ -2047,124 +1799,6 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) } break; - case SIMDIntrinsicLessThan: - case SIMDIntrinsicLessThanOrEqual: - { - assert(targetReg != REG_NA); - - // Int vectors use ">" and ">=" with swapped operands - assert(varTypeIsFloating(baseType)); - - // Get the instruction opcode for compare operation - unsigned ival; - instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType, &ival); - - // targetReg = op1reg RelOp op2reg - // Thefore, we can optimize if op1Reg == targetReg - if (op1Reg != targetReg) - { - inst_RV_RV(ins_Copy(targetType), targetReg, op1Reg, targetType, emitActualTypeSize(targetType)); - } - - assert((ival >= 0) && (ival <= 255)); - GetEmitter()->emitIns_R_R_I(ins, emitActualTypeSize(targetType), targetReg, op2Reg, (int8_t)ival); - } - break; - - // (In)Equality that produces bool result instead of a bit vector - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: - { - // We're only setting condition flags, if a 0/1 value is desired then Lowering should have inserted a SETCC. - assert(targetReg == REG_NA); - - var_types simdType = op1->TypeGet(); - // TODO-1stClassStructs: Temporary to minimize asmDiffs - if (simdType == TYP_DOUBLE) - { - simdType = TYP_SIMD8; - } - - // Here we should consider TYP_SIMD12 operands as if they were TYP_SIMD16 - // since both the operands will be in XMM registers. - if (simdType == TYP_SIMD12) - { - simdType = TYP_SIMD16; - } - - // On SSE4/AVX, we can generate optimal code for (in)equality against zero using ptest. - if (op2->isContained()) - { - assert((compiler->getSIMDSupportLevel() >= SIMD_SSE4_Supported) && op2->IsIntegralConstVector(0)); - inst_RV_RV(INS_ptest, op1->GetRegNum(), op1->GetRegNum(), simdType, emitActualTypeSize(simdType)); - } - else - { - // We need one additional SIMD register to store the result of the SIMD compare. - regNumber tmpReg1 = simdNode->GetSingleTempReg(RBM_ALLFLOAT); - - // tmpReg1 = (op1Reg == op2Reg) - // Call this value of tmpReg1 as 'compResult' for further reference below. - regNumber otherReg = op2Reg; - if (tmpReg1 != op2Reg) - { - if (tmpReg1 != op1Reg) - { - inst_RV_RV(ins_Copy(simdType), tmpReg1, op1Reg, simdType, emitActualTypeSize(simdType)); - } - } - else - { - otherReg = op1Reg; - } - - // For all integer types we can use TYP_INT comparison. - unsigned ival = 0; - instruction ins = - getOpForSIMDIntrinsic(SIMDIntrinsicEqual, varTypeIsFloating(baseType) ? baseType : TYP_INT, &ival); - - if (varTypeIsFloating(baseType)) - { - assert((ival >= 0) && (ival <= 255)); - GetEmitter()->emitIns_R_R_I(ins, emitActualTypeSize(simdType), tmpReg1, otherReg, (int8_t)ival); - } - else - { - inst_RV_RV(ins, tmpReg1, otherReg, simdType, emitActualTypeSize(simdType)); - } - - regNumber intReg = simdNode->GetSingleTempReg(RBM_ALLINT); - inst_RV_RV(INS_pmovmskb, intReg, tmpReg1, simdType, emitActualTypeSize(simdType)); - // There's no pmovmskw/pmovmskd/pmovmskq but they're not needed anyway. Vector compare - // instructions produce "all ones"/"all zeroes" components and pmovmskb extracts a - // subset of each component's ones/zeroes. In the end we need to know if the result is - // "all ones" where the number of ones is given by the vector byte size, not by the - // vector component count. So, for AVX registers we need to compare to 0xFFFFFFFF and - // for SSE registers we need to compare to 0x0000FFFF. - // The SIMD12 case is handled specially, because we can't rely on the upper bytes being - // zero, so we must compare only the lower 3 floats (hence the byte mask of 0xFFF). - // Note that -1 is used instead of 0xFFFFFFFF, on x64 emit doesn't correctly recognize - // that 0xFFFFFFFF can be encoded in a single byte and emits the longer 3DFFFFFFFF - // encoding instead of 83F8FF. - ssize_t mask; - if ((simdNode->gtFlags & GTF_SIMD12_OP) != 0) - { - mask = 0x00000FFF; - GetEmitter()->emitIns_R_I(INS_and, EA_4BYTE, intReg, mask); - } - else if (emitActualTypeSize(simdType) == 32) - { - mask = -1; - } - else - { - mask = 0x0000FFFF; - } - GetEmitter()->emitIns_R_I(INS_cmp, EA_4BYTE, intReg, mask); - } - } - break; - default: noway_assert(!"Unimplemented SIMD relational operation."); unreached(); @@ -2973,13 +2607,26 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode) offs = treeNode->AsLclFld()->GetLclOffs(); } - GenTree* op1 = treeNode->AsOp()->gtOp1; + regNumber tmpReg = treeNode->GetSingleTempReg(); + GenTree* op1 = treeNode->AsOp()->gtOp1; + if (op1->isContained()) + { + // This is only possible for a zero-init. + assert(op1->IsIntegralConst(0) || op1->IsSIMDZero()); + genSIMDZero(TYP_SIMD16, op1->AsSIMD()->gtSIMDBaseType, tmpReg); + + // store lower 8 bytes + GetEmitter()->emitIns_S_R(ins_Store(TYP_DOUBLE), EA_8BYTE, tmpReg, varNum, offs); + + // Store upper 4 bytes + GetEmitter()->emitIns_S_R(ins_Store(TYP_FLOAT), EA_4BYTE, tmpReg, varNum, offs + 8); + + return; + } + assert(!op1->isContained()); regNumber operandReg = genConsumeReg(op1); - // Need an addtional Xmm register to extract upper 4 bytes from data. - regNumber tmpReg = treeNode->GetSingleTempReg(); - // store lower 8 bytes GetEmitter()->emitIns_S_R(ins_Store(TYP_DOUBLE), EA_8BYTE, operandReg, varNum, offs); @@ -3211,9 +2858,7 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) genSIMDIntrinsicInitN(simdNode); break; - case SIMDIntrinsicSqrt: case SIMDIntrinsicCast: - case SIMDIntrinsicAbs: genSIMDIntrinsicUnOp(simdNode); break; @@ -3241,21 +2886,11 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) case SIMDIntrinsicMul: case SIMDIntrinsicDiv: case SIMDIntrinsicBitwiseAnd: - case SIMDIntrinsicBitwiseAndNot: case SIMDIntrinsicBitwiseOr: - case SIMDIntrinsicBitwiseXor: - case SIMDIntrinsicMin: - case SIMDIntrinsicMax: genSIMDIntrinsicBinOp(simdNode); break; - case SIMDIntrinsicOpEquality: - case SIMDIntrinsicOpInEquality: case SIMDIntrinsicEqual: - case SIMDIntrinsicLessThan: - case SIMDIntrinsicGreaterThan: - case SIMDIntrinsicLessThanOrEqual: - case SIMDIntrinsicGreaterThanOrEqual: genSIMDIntrinsicRelOp(simdNode); break; @@ -3285,11 +2920,6 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) genSIMDIntrinsicUpperRestore(simdNode); break; - case SIMDIntrinsicCeil: - case SIMDIntrinsicFloor: - genSIMDIntrinsicUnOpWithImm(simdNode); - break; - default: noway_assert(!"Unimplemented SIMD intrinsic."); unreached(); diff --git a/src/coreclr/src/jit/simdintrinsiclist.h b/src/coreclr/src/jit/simdintrinsiclist.h index 7b535c0112dc8..813a937fd056b 100644 --- a/src/coreclr/src/jit/simdintrinsiclist.h +++ b/src/coreclr/src/jit/simdintrinsiclist.h @@ -76,13 +76,6 @@ SIMD_INTRINSIC("set_Y", true, SetY, SIMD_INTRINSIC("set_Z", true, SetZ, "setZ", TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) SIMD_INTRINSIC("set_W", true, SetW, "setW", TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) -// Object.Equals() -SIMD_INTRINSIC("Equals", true, InstEquals, "equals", TYP_BOOL, 2, {TYP_BYREF, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) - -// Operator == and != -SIMD_INTRINSIC("op_Equality", false, OpEquality, "==", TYP_BOOL, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("op_Inequality", false, OpInEquality, "!=", TYP_BOOL, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) - // Arithmetic Operations SIMD_INTRINSIC("op_Addition", false, Add, "+", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) SIMD_INTRINSIC("op_Subtraction", false, Sub, "-", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) @@ -96,28 +89,12 @@ SIMD_INTRINSIC("op_Multiply", false, Mul, SIMD_INTRINSIC("op_Division", false, Div, "/", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) -// SquareRoot is recognized as an intrinsic only for float or double vectors -SIMD_INTRINSIC("SquareRoot", false, Sqrt, "sqrt", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) - -SIMD_INTRINSIC("Ceiling", false, Ceil, "ceil", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) -SIMD_INTRINSIC("Floor", false, Floor, "floor", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) - -SIMD_INTRINSIC("Min", false, Min, "min", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("Max", false, Max, "max", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("Abs", false, Abs, "abs", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF }, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) - // Vector Relational operators SIMD_INTRINSIC("Equals", false, Equal, "eq", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("LessThan", false, LessThan, "lt", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("LessThanOrEqual", false, LessThanOrEqual, "le", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("GreaterThan", false, GreaterThan, "gt", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("GreaterThanOrEqual", false, GreaterThanOrEqual, "ge", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) // Bitwise operations SIMD_INTRINSIC("op_BitwiseAnd", false, BitwiseAnd, "&", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("AndNot", false, BitwiseAndNot, "&~", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) SIMD_INTRINSIC("op_BitwiseOr", false, BitwiseOr, "|", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) -SIMD_INTRINSIC("op_ExclusiveOr", false, BitwiseXor, "^", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) // Dot Product #if defined(TARGET_XARCH) @@ -128,9 +105,6 @@ SIMD_INTRINSIC("Dot", false, DotProduct, SIMD_INTRINSIC("Dot", false, DotProduct, "Dot", TYP_UNKNOWN, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_UNDEF, TYP_UNDEF}) #endif -// Select -SIMD_INTRINSIC("ConditionalSelect", false, Select, "Select", TYP_STRUCT, 3, {TYP_STRUCT, TYP_STRUCT, TYP_STRUCT}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) - // Cast SIMD_INTRINSIC("op_Explicit", false, Cast, "Cast", TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) diff --git a/src/coreclr/src/jit/ssabuilder.cpp b/src/coreclr/src/jit/ssabuilder.cpp index 53cffb67c9e34..8730a277c6fd6 100644 --- a/src/coreclr/src/jit/ssabuilder.cpp +++ b/src/coreclr/src/jit/ssabuilder.cpp @@ -1650,6 +1650,10 @@ bool SsaBuilder::IncludeInSsa(unsigned lclNum) // return false; } + else if (varDsc->lvIsStructField && m_pCompiler->lvaGetDesc(varDsc->lvParentLcl)->lvIsMultiRegRet) + { + return false; + } // otherwise this variable is included in SSA return true; } diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h index cbd6d46ceb267..6fd88968026c3 100644 --- a/src/coreclr/src/jit/target.h +++ b/src/coreclr/src/jit/target.h @@ -232,10 +232,10 @@ typedef unsigned char regNumberSmall; #define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). - #define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments (note this seems wrong as MAX_ARG_REG_COUNT is 2) + #define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments #define MAX_RET_MULTIREG_BYTES 8 // Maximum size of a struct that could be returned in more than one register - #define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass an argument. + #define MAX_ARG_REG_COUNT 1 // Maximum registers used to pass an argument. #define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. #define MAX_MULTIREG_COUNT 2 // Maxiumum number of registers defined by a single instruction (including calls). diff --git a/src/coreclr/src/jit/treelifeupdater.cpp b/src/coreclr/src/jit/treelifeupdater.cpp index b903c903b7ee4..d1a574c071fe8 100644 --- a/src/coreclr/src/jit/treelifeupdater.cpp +++ b/src/coreclr/src/jit/treelifeupdater.cpp @@ -74,9 +74,27 @@ void TreeLifeUpdater::UpdateLifeVar(GenTree* tree) } // if it's a partial definition then variable "x" must have had a previous, original, site to be born. - bool isBorn = ((lclVarTree->gtFlags & GTF_VAR_DEF) != 0 && (lclVarTree->gtFlags & GTF_VAR_USEASG) == 0); - bool isDying = ((lclVarTree->gtFlags & GTF_VAR_DEATH) != 0); - bool spill = ((lclVarTree->gtFlags & GTF_SPILL) != 0); + bool isBorn; + bool isDying; + bool spill; + bool isMultiRegLocal = lclVarTree->IsMultiRegLclVar(); + if (isMultiRegLocal) + { + assert((tree->gtFlags & GTF_VAR_USEASG) == 0); + isBorn = ((tree->gtFlags & GTF_VAR_DEF) != 0); + // Note that for multireg locals we can have definitions for which some of those are last uses. + // We don't want to add those to the varDeltaSet because otherwise they will be added as newly + // live. + isDying = !isBorn && tree->AsLclVar()->HasLastUse(); + // GTF_SPILL will be set if any registers need to be spilled. + spill = ((tree->gtFlags & GTF_SPILL) != 0); + } + else + { + isBorn = ((lclVarTree->gtFlags & GTF_VAR_DEF) != 0 && (lclVarTree->gtFlags & GTF_VAR_USEASG) == 0); + isDying = ((lclVarTree->gtFlags & GTF_VAR_DEATH) != 0); + spill = ((lclVarTree->gtFlags & GTF_SPILL) != 0); + } // Since all tracked vars are register candidates, but not all are in registers at all times, // we maintain two separate sets of variables - the total set of variables that are either @@ -108,6 +126,10 @@ void TreeLifeUpdater::UpdateLifeVar(GenTree* tree) } } } + else if (ForCodeGen && lclVarTree->IsMultiRegLclVar()) + { + assert(!"MultiRegLclVars not yet supported"); + } else if (varDsc->lvPromoted) { // If hasDeadTrackedFieldVars is true, then, for a LDOBJ(ADDR()), @@ -126,15 +148,17 @@ void TreeLifeUpdater::UpdateLifeVar(GenTree* tree) } } - for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i) + unsigned firstFieldVarNum = varDsc->lvFieldLclStart; + for (unsigned i = 0; i < varDsc->lvFieldCnt; ++i) { - LclVarDsc* fldVarDsc = &(compiler->lvaTable[i]); + LclVarDsc* fldVarDsc = compiler->lvaGetDesc(firstFieldVarNum + i); noway_assert(fldVarDsc->lvIsStructField); if (fldVarDsc->lvTracked) { unsigned fldVarIndex = fldVarDsc->lvVarIndex; - bool isInReg = fldVarDsc->lvIsInReg(); - bool isInMemory = !isInReg || fldVarDsc->lvLiveInOutOfHndlr; + // We should never see enregistered fields in a struct local unless + // IsMultiRegLclVar() returns true, in which case we've handled this above. + assert(!fldVarDsc->lvIsInReg()); noway_assert(fldVarIndex < compiler->lvaTrackedCount); if (!hasDeadTrackedFieldVars) { @@ -143,34 +167,12 @@ void TreeLifeUpdater::UpdateLifeVar(GenTree* tree) { // We repeat this call here and below to avoid the VarSetOps::IsMember // test in this, the common case, where we have no deadTrackedFieldVars. - if (isInReg) - { - if (isBorn) - { - compiler->codeGen->genUpdateVarReg(fldVarDsc, tree); - } - compiler->codeGen->genUpdateRegLife(fldVarDsc, isBorn, isDying DEBUGARG(tree)); - } - if (isInMemory) - { - VarSetOps::AddElemD(compiler, stackVarDeltaSet, fldVarIndex); - } + VarSetOps::AddElemD(compiler, stackVarDeltaSet, fldVarIndex); } } else if (ForCodeGen && VarSetOps::IsMember(compiler, varDeltaSet, fldVarIndex)) { - if (isInReg) - { - if (isBorn) - { - compiler->codeGen->genUpdateVarReg(fldVarDsc, tree); - } - compiler->codeGen->genUpdateRegLife(fldVarDsc, isBorn, isDying DEBUGARG(tree)); - } - if (isInMemory) - { - VarSetOps::AddElemD(compiler, stackVarDeltaSet, fldVarIndex); - } + VarSetOps::AddElemD(compiler, stackVarDeltaSet, fldVarIndex); } } } diff --git a/src/coreclr/src/jit/vartype.h b/src/coreclr/src/jit/vartype.h index d69a75e5bfb54..e34ee7e5a8df8 100644 --- a/src/coreclr/src/jit/vartype.h +++ b/src/coreclr/src/jit/vartype.h @@ -113,6 +113,12 @@ inline bool varTypeIsUnsigned(T vt) return ((varTypeClassification[TypeGet(vt)] & (VTF_UNS)) != 0); } +template +inline bool varTypeIsSigned(T vt) +{ + return varTypeIsIntegralOrI(vt) && !varTypeIsUnsigned(vt); +} + // If "vt" is an unsigned integral type, returns the corresponding signed integral type, otherwise // return "vt". inline var_types varTypeUnsignedToSigned(var_types vt) @@ -140,6 +146,32 @@ inline var_types varTypeUnsignedToSigned(var_types vt) } } +// If "vt" is a signed integral type, returns the corresponding unsigned integral type, otherwise +// return "vt". +inline var_types varTypeSignedToUnsigned(var_types vt) +{ + if (varTypeIsSigned(vt)) + { + switch (vt) + { + case TYP_BYTE: + return TYP_UBYTE; + case TYP_SHORT: + return TYP_USHORT; + case TYP_INT: + return TYP_UINT; + case TYP_LONG: + return TYP_ULONG; + default: + unreached(); + } + } + else + { + return vt; + } +} + template inline bool varTypeIsFloating(T vt) { diff --git a/src/coreclr/src/md/runtime/mdinternaldisp.h b/src/coreclr/src/md/runtime/mdinternaldisp.h index 510e87351f354..530a141989565 100644 --- a/src/coreclr/src/md/runtime/mdinternaldisp.h +++ b/src/coreclr/src/md/runtime/mdinternaldisp.h @@ -16,7 +16,6 @@ #include "mdinternalro.h" - enum MDFileFormat { MDFormat_ReadOnly = 0, @@ -25,8 +24,6 @@ enum MDFileFormat MDFormat_Invalid = 3 }; - -HRESULT CheckFileFormat(LPVOID pData, ULONG cbData, MDFileFormat *pFormat); STDAPI GetMDInternalInterface( LPVOID pData, // [IN] Buffer with the metadata. ULONG cbData, // [IN] Size of the data in the buffer. @@ -34,11 +31,6 @@ STDAPI GetMDInternalInterface( REFIID riid, // [in] The interface desired. void **ppIUnk); // [out] Return interface on success. -HRESULT GetAssemblyMDInternalImportHelper(HCORMODULE hModule, - REFIID riid, - MDInternalImportFlags flags, - IUnknown **ppIUnk); - #endif //FEATURE_METADATA_INTERNAL_APIS #endif // __MDInternalDispenser__h__ diff --git a/src/coreclr/src/nativeresources/processrc.awk b/src/coreclr/src/nativeresources/processrc.awk index 4e6ad55c45871..f8eec8d091d92 100644 --- a/src/coreclr/src/nativeresources/processrc.awk +++ b/src/coreclr/src/nativeresources/processrc.awk @@ -51,7 +51,7 @@ BEGIN { var = var + 0; # Extract string content starting with either " or L" - idx = match($0, /L?\"/); + idx = match($0, /L?"/); content = substr($0, idx); # remove the L prefix from strings diff --git a/src/coreclr/src/pal/inc/pal.h b/src/coreclr/src/pal/inc/pal.h index 861a10f842da7..7ffdc2b7ec320 100644 --- a/src/coreclr/src/pal/inc/pal.h +++ b/src/coreclr/src/pal/inc/pal.h @@ -47,6 +47,9 @@ Module Name: #include #include #include +#include +#include +#include #endif #ifdef __cplusplus @@ -2543,6 +2546,7 @@ Abstract Parameters: IN hFile - The file to load + IN offset - offset within hFile where the PE "file" is located Return value: A valid base address if successful. @@ -2551,7 +2555,7 @@ Return value: PALIMPORT PVOID PALAPI -PAL_LOADLoadPEFile(HANDLE hFile); +PAL_LOADLoadPEFile(HANDLE hFile, size_t offset); /*++ PAL_LOADUnloadPEFile diff --git a/src/coreclr/src/pal/prebuilt/inc/cordebug.h b/src/coreclr/src/pal/prebuilt/inc/cordebug.h index 96dc9c0eb1926..69c897575113f 100644 --- a/src/coreclr/src/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/src/pal/prebuilt/inc/cordebug.h @@ -6376,7 +6376,8 @@ enum CorGCReferenceType CorHandleStrongDependent = ( 1 << 6 ) , CorHandleStrongAsyncPinned = ( 1 << 7 ) , CorHandleStrongSizedByref = ( 1 << 8 ) , - CorHandleWeakWinRT = ( 1 << 9 ) , + CorHandleWeakNativeCom = ( 1 << 9 ) , + CorHandleWeakWinRT = CorHandleWeakNativeCom, CorReferenceStack = 0x80000001, CorReferenceFinalizer = 80000002, CorHandleStrongOnly = 0x1e3, diff --git a/src/coreclr/src/pal/src/exception/machexception.cpp b/src/coreclr/src/pal/src/exception/machexception.cpp index 4acafddbce74e..01130e80978cf 100644 --- a/src/coreclr/src/pal/src/exception/machexception.cpp +++ b/src/coreclr/src/pal/src/exception/machexception.cpp @@ -357,17 +357,11 @@ PAL_ERROR CorUnix::CPalThread::DisableMachExceptions() return palError; } -#if !defined(HOST_AMD64) -extern "C" -void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) -#else // defined(HOST_AMD64) - // Since HijackFaultingThread pushed the context, exception record and info on the stack, we need to adjust the // signature of PAL_DispatchException such that the corresponding arguments are considered to be on the stack // per GCC64 calling convention rules. Hence, the first 6 dummy arguments (corresponding to RDI, RSI, RDX,RCX, R8, R9). extern "C" void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 dwRCX, DWORD64 dwR8, DWORD64 dwR9, PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) -#endif // !defined(HOST_AMD64) { CPalThread *pThread = InternalGetCurrentThread(); @@ -414,10 +408,8 @@ void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 } } -#if defined(HOST_X86) || defined(HOST_AMD64) extern "C" void PAL_DispatchExceptionWrapper(); extern "C" int PAL_DispatchExceptionReturnOffset; -#endif // HOST_X86 || HOST_AMD64 /*++ Function : @@ -477,7 +469,6 @@ BuildExceptionRecord( { switch (exceptionInfo.Subcodes[0]) { -#if defined(HOST_X86) || defined(HOST_AMD64) case EXC_I386_DIV: exceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; break; @@ -490,9 +481,6 @@ BuildExceptionRecord( case EXC_I386_BOUND: exceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; break; -#else -#error Trap code to exception mapping not defined for this architecture -#endif default: exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; @@ -501,16 +489,11 @@ BuildExceptionRecord( break; case EXC_SOFTWARE: -#if defined(HOST_X86) || defined(HOST_AMD64) exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; -#else -#error Trap code to exception mapping not defined for this architecture -#endif // Trace, breakpoint, etc. Details in subcode field. case EXC_BREAKPOINT: -#if defined(HOST_X86) || defined(HOST_AMD64) if (exceptionInfo.Subcodes[0] == EXC_I386_SGL) { exceptionCode = EXCEPTION_SINGLE_STEP; @@ -519,9 +502,6 @@ BuildExceptionRecord( { exceptionCode = EXCEPTION_BREAKPOINT; } -#else -#error Trap code to exception mapping not defined for this architecture -#endif else { WARN("unexpected subcode %d for EXC_BREAKPOINT", exceptionInfo.Subcodes[0]); @@ -615,17 +595,12 @@ HijackFaultingThread( // Fill in the exception record from the exception info BuildExceptionRecord(exceptionInfo, &exceptionRecord); -#ifdef HOST_X86 - threadContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; -#else threadContext.ContextFlags = CONTEXT_FLOATING_POINT; -#endif CONTEXT_GetThreadContextFromThreadState(x86_FLOAT_STATE, (thread_state_t)&exceptionInfo.FloatState, &threadContext); threadContext.ContextFlags |= CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS; CONTEXT_GetThreadContextFromThreadState(x86_THREAD_STATE, (thread_state_t)&exceptionInfo.ThreadState, &threadContext); -#if defined(CORECLR) && (defined(HOST_X86) || defined(HOST_AMD64)) // For CoreCLR we look more deeply at access violations to determine whether they're the result of a stack // overflow. If so we'll terminate the process immediately (the current default policy of the CoreCLR EE). // Otherwise we'll either A/V ourselves trying to set up the SEH exception record and context on the @@ -671,7 +646,6 @@ HijackFaultingThread( // corrupted). Our managed jits always generate code which does this as does MSVC. GCC, however, // does not do this by default. We have to explicitly provide the -fstack-check compiler option // to enable the behavior. -#if (defined(HOST_X86) || defined(HOST_AMD64)) && defined(__APPLE__) // Assume that AV isn't an SO to begin with. bool fIsStackOverflow = false; @@ -680,11 +654,7 @@ HijackFaultingThread( // Calculate the page base addresses for the fault and the faulting thread's SP. int cbPage = getpagesize(); char *pFaultPage = (char*)(exceptionRecord.ExceptionInformation[1] & ~(cbPage - 1)); -#ifdef HOST_X86 - char *pStackTopPage = (char*)(threadContext.Esp & ~(cbPage - 1)); -#elif defined(HOST_AMD64) char *pStackTopPage = (char*)(threadContext.Rsp & ~(cbPage - 1)); -#endif if (pFaultPage == pStackTopPage || pFaultPage == (pStackTopPage - cbPage)) { @@ -699,24 +669,14 @@ HijackFaultingThread( vm_size_t vm_size; vm_region_flavor_t vm_flavor; mach_msg_type_number_t infoCnt; -#ifdef HOST_64BIT vm_region_basic_info_data_64_t info; infoCnt = VM_REGION_BASIC_INFO_COUNT_64; vm_flavor = VM_REGION_BASIC_INFO_64; -#else - vm_region_basic_info_data_t info; - infoCnt = VM_REGION_BASIC_INFO_COUNT; - vm_flavor = VM_REGION_BASIC_INFO; -#endif mach_port_t object_name; vm_address = (vm_address_t)(pFaultPage + cbPage); -#ifdef HOST_64BIT machret = vm_region_64( -#else - machret = vm_region( -#endif mach_task_self(), &vm_address, &vm_size, @@ -724,11 +684,7 @@ HijackFaultingThread( (vm_region_info_t)&info, &infoCnt, &object_name); -#ifdef HOST_X86 - CHECK_MACH("vm_region", machret); -#elif defined(HOST_AMD64) CHECK_MACH("vm_region_64", machret); -#endif // If vm_region updated the address we gave it then that address was not part of a region at all // (and so this cannot be an SO). Otherwise check that the ESP lies in the region returned. @@ -738,7 +694,6 @@ HijackFaultingThread( fIsStackOverflow = true; } -#if defined(HOST_AMD64) if (!fIsStackOverflow) { // Check if we can read pointer sizeD bytes below the target thread's stack pointer. @@ -755,79 +710,8 @@ HijackFaultingThread( fIsStackOverflow = true; } } -#endif // HOST_AMD64 - } -#else // (HOST_X86 || HOST_AMD64) && __APPLE__ -#error Platform not supported for correct stack overflow handling -#endif // (HOST_X86 || HOST_AMD64) && __APPLE__ -#endif // CORECLR && HOST_X86 - -#if defined(HOST_X86) - NONPAL_ASSERTE(exceptionInfo.ThreadState.tsh.flavor == x86_THREAD_STATE32); - - // Make a copy of the thread state because the one in exceptionInfo needs to be preserved to restore - // the state if the exception is forwarded. - x86_thread_state32_t ts32 = exceptionInfo.ThreadState.uts.ts32; - - // If we're in single step mode, disable it since we're going to call PAL_DispatchException - if (exceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) - { - ts32.eflags &= ~EFL_TF; } - exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; - exceptionRecord.ExceptionRecord = NULL; - exceptionRecord.ExceptionAddress = (void *)ts32.eip; - - void **FramePointer = (void **)ts32.esp; - - *--FramePointer = (void *)ts32.eip; - - // Construct a stack frame for a pretend activation of the function - // PAL_DispatchExceptionWrapper that serves only to make the stack - // correctly unwindable by the system exception unwinder. - // PAL_DispatchExceptionWrapper has an ebp frame, its local variables - // are the context and exception record, and it has just "called" - // PAL_DispatchException. - *--FramePointer = (void *)ts32.ebp; - ts32.ebp = (unsigned)FramePointer; - - // Put the context on the stack - FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(CONTEXT)); - // Make sure it's aligned - CONTEXT has 8-byte alignment - FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 8)); - CONTEXT *pContext = (CONTEXT *)FramePointer; - *pContext = threadContext; - - // Put the exception record on the stack - FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(EXCEPTION_RECORD)); - EXCEPTION_RECORD *pExceptionRecord = (EXCEPTION_RECORD *)FramePointer; - *pExceptionRecord = exceptionRecord; - - FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(MachExceptionInfo)); - MachExceptionInfo *pMachExceptionInfo = (MachExceptionInfo *)FramePointer; - *pMachExceptionInfo = exceptionInfo; - - // Push arguments to PAL_DispatchException - FramePointer = (void **)((ULONG_PTR)FramePointer - 3 * sizeof(void *)); - - // Make sure it's aligned - ABI requires 16-byte alignment - FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16)); - FramePointer[0] = pContext; - FramePointer[1] = pExceptionRecord; - FramePointer[2] = pMachExceptionInfo; - - // Place the return address to right after the fake call in PAL_DispatchExceptionWrapper - FramePointer[-1] = (void *)((ULONG_PTR)PAL_DispatchExceptionWrapper + PAL_DispatchExceptionReturnOffset); - - // Make the instruction register point to DispatchException - ts32.eip = (unsigned)PAL_DispatchException; - ts32.esp = (unsigned)&FramePointer[-1]; // skip return address - - // Now set the thread state for the faulting thread so that PAL_DispatchException executes next - machret = thread_set_state(thread, x86_THREAD_STATE32, (thread_state_t)&ts32, x86_THREAD_STATE32_COUNT); - CHECK_MACH("thread_set_state(thread)", machret); -#elif defined(HOST_AMD64) NONPAL_ASSERTE(exceptionInfo.ThreadState.tsh.flavor == x86_THREAD_STATE64); // Make a copy of the thread state because the one in exceptionInfo needs to be preserved to restore @@ -919,9 +803,6 @@ HijackFaultingThread( // Now set the thread state for the faulting thread so that PAL_DispatchException executes next machret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&ts64, x86_THREAD_STATE64_COUNT); CHECK_MACH("thread_set_state(thread)", machret); -#else -#error HijackFaultingThread not defined for this architecture -#endif } /*++ @@ -1234,13 +1115,7 @@ void MachExceptionInfo::RestoreState(mach_port_t thread) { if (Subcodes[0] == EXC_I386_BPT) { -#ifdef HOST_X86 - ThreadState.uts.ts32.eip--; -#elif defined(HOST_AMD64) ThreadState.uts.ts64.__rip--; -#else -#error Platform not supported -#endif } } kern_return_t machret = thread_set_state(thread, x86_THREAD_STATE, (thread_state_t)&ThreadState, x86_THREAD_STATE_COUNT); diff --git a/src/coreclr/src/pal/src/include/pal/map.hpp b/src/coreclr/src/pal/src/include/pal/map.hpp index eba0d8844bb27..b8c584f83c526 100644 --- a/src/coreclr/src/pal/src/include/pal/map.hpp +++ b/src/coreclr/src/pal/src/include/pal/map.hpp @@ -79,13 +79,14 @@ extern "C" Parameters: IN hFile - file to map + IN offset - offset within hFile where the PE "file" is located Return value: non-NULL - the base address of the mapped image NULL - error, with last error set. --*/ - void * MAPMapPEFile(HANDLE hFile); + void* MAPMapPEFile(HANDLE hFile, off_t offset); /*++ Function : diff --git a/src/coreclr/src/pal/src/include/pal/module.h b/src/coreclr/src/pal/src/include/pal/module.h index bb409b8fcd449..6a5e080d499d2 100644 --- a/src/coreclr/src/pal/src/include/pal/module.h +++ b/src/coreclr/src/pal/src/include/pal/module.h @@ -145,12 +145,13 @@ Abstract Parameters: IN hFile - The file to load + IN offset - offset within hFile where the PE "file" is located Return value: A valid base address if successful. 0 if failure --*/ -void * PAL_LOADLoadPEFile(HANDLE hFile); +void* PAL_LOADLoadPEFile(HANDLE hFile, size_t offset); /*++ PAL_LOADUnloadPEFile diff --git a/src/coreclr/src/pal/src/include/pal/mutex.hpp b/src/coreclr/src/pal/src/include/pal/mutex.hpp index 8aa9a53bdafc2..d5f6cef009537 100644 --- a/src/coreclr/src/pal/src/include/pal/mutex.hpp +++ b/src/coreclr/src/pal/src/include/pal/mutex.hpp @@ -146,7 +146,6 @@ class NamedMutexProcessData : public SharedMemoryProcessDataBase private: SharedMemoryProcessDataHeader *m_processDataHeader; - NamedMutexSharedData *m_sharedData; SIZE_T m_lockCount; #if !NAMED_MUTEX_USE_PTHREAD_MUTEX HANDLE m_processLockHandle; @@ -154,6 +153,7 @@ class NamedMutexProcessData : public SharedMemoryProcessDataBase #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX CorUnix::CPalThread *m_lockOwnerThread; NamedMutexProcessData *m_nextInThreadOwnedNamedMutexList; + bool m_hasRefFromLockOwnerThread; public: static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool acquireLockIfCreated, bool *createdRef); @@ -169,8 +169,19 @@ class NamedMutexProcessData : public SharedMemoryProcessDataBase int sharedLockFileDescriptor #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX ); + +public: + virtual bool CanClose() const override; + virtual bool HasImplicitRef() const override; + virtual void SetHasImplicitRef(bool value) override; virtual void Close(bool isAbruptShutdown, bool releaseSharedData) override; +public: + bool IsLockOwnedByCurrentThread() const + { + return GetSharedData()->IsLockOwnedByCurrentThread(); + } + private: NamedMutexSharedData *GetSharedData() const; void SetLockOwnerThread(CorUnix::CPalThread *lockOwnerThread); diff --git a/src/coreclr/src/pal/src/include/pal/sharedmemory.h b/src/coreclr/src/pal/src/include/pal/sharedmemory.h index 74e1cd4aedc39..ff64e20b5aa74 100644 --- a/src/coreclr/src/pal/src/include/pal/sharedmemory.h +++ b/src/coreclr/src/pal/src/include/pal/sharedmemory.h @@ -188,9 +188,10 @@ class SharedMemorySharedDataHeader class SharedMemoryProcessDataBase { public: - virtual void Close(bool isAbruptShutdown, bool releaseSharedData) - { - } + virtual bool CanClose() const = 0; + virtual bool HasImplicitRef() const = 0; + virtual void SetHasImplicitRef(bool value) = 0; + virtual void Close(bool isAbruptShutdown, bool releaseSharedData) = 0; virtual ~SharedMemoryProcessDataBase() { diff --git a/src/coreclr/src/pal/src/include/pal/synchobjects.hpp b/src/coreclr/src/pal/src/include/pal/synchobjects.hpp index 66d4710acb24b..ab51a005bae06 100644 --- a/src/coreclr/src/pal/src/include/pal/synchobjects.hpp +++ b/src/coreclr/src/pal/src/include/pal/synchobjects.hpp @@ -118,7 +118,6 @@ namespace CorUnix Volatile m_lSharedSynchLockCount; LIST_ENTRY m_leOwnedObjsList; - CRITICAL_SECTION m_ownedNamedMutexListLock; NamedMutexProcessData *m_ownedNamedMutexListHead; ThreadNativeWaitData m_tnwdNativeData; @@ -178,6 +177,7 @@ namespace CorUnix void RemoveOwnedNamedMutex(NamedMutexProcessData *processData); NamedMutexProcessData *RemoveFirstOwnedNamedMutex(); bool OwnsNamedMutex(NamedMutexProcessData *processData); + bool OwnsAnyNamedMutex() const; // The following methods provide access to the native wait lock for // those implementations that need a lock to protect the support for diff --git a/src/coreclr/src/pal/src/loader/module.cpp b/src/coreclr/src/pal/src/loader/module.cpp index 8418ef776d4be..65168978ba743 100644 --- a/src/coreclr/src/pal/src/loader/module.cpp +++ b/src/coreclr/src/pal/src/loader/module.cpp @@ -752,6 +752,7 @@ PAL_UnregisterModule( Parameters: IN hFile - file to map + IN offset - offset within hFile where the PE "file" is located Return value: non-NULL - the base address of the mapped image @@ -759,11 +760,11 @@ Return value: --*/ PVOID PALAPI -PAL_LOADLoadPEFile(HANDLE hFile) +PAL_LOADLoadPEFile(HANDLE hFile, size_t offset) { - ENTRY("PAL_LOADLoadPEFile (hFile=%p)\n", hFile); + ENTRY("PAL_LOADLoadPEFile (hFile=%p, offset=%zx)\n", hFile, offset); - void * loadedBase = MAPMapPEFile(hFile); + void* loadedBase = MAPMapPEFile(hFile, offset); #ifdef _DEBUG if (loadedBase != nullptr) @@ -775,7 +776,7 @@ PAL_LOADLoadPEFile(HANDLE hFile) { TRACE("Forcing failure of PE file map, and retry\n"); PAL_LOADUnloadPEFile(loadedBase); // unload it - loadedBase = MAPMapPEFile(hFile); // load it again + loadedBase = MAPMapPEFile(hFile, offset); // load it again } free(envVar); @@ -1547,7 +1548,8 @@ static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryN { /* found the handle. increment the refcount and return the existing module structure */ - TRACE("Found matching module %p for module name %s\n", module, libraryNameOrPath); + TRACE("Found matching module %p for module name %s\n", module, + (libraryNameOrPath != nullptr) ? libraryNameOrPath : "nullptr"); if (module->refcount != -1) { diff --git a/src/coreclr/src/pal/src/map/map.cpp b/src/coreclr/src/pal/src/map/map.cpp index cac736460bb3f..90936b19fd916 100644 --- a/src/coreclr/src/pal/src/map/map.cpp +++ b/src/coreclr/src/pal/src/map/map.cpp @@ -1088,6 +1088,8 @@ CorUnix::InternalMapViewOfFile( CFileMappingImmutableData *pImmutableData = NULL; CFileMappingProcessLocalData *pProcessLocalData = NULL; IDataLock *pProcessLocalDataLock = NULL; + INT64 offset = ((INT64)dwFileOffsetHigh << 32) | (INT64)dwFileOffsetLow; + #if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS PMAPPED_VIEW_LIST pReusedMapping = NULL; #endif @@ -1102,9 +1104,9 @@ CorUnix::InternalMapViewOfFile( goto InternalMapViewOfFileExit; } - if ( 0 != dwFileOffsetHigh || 0 != dwFileOffsetLow ) + if (offset < 0) { - ASSERT( "dwFileOffsetHigh and dwFileOffsetLow are always 0.\n" ); + ASSERT("dwFileOffsetHigh | dwFileOffsetLow should be non-negative.\n"); palError = ERROR_INVALID_PARAMETER; goto InternalMapViewOfFileExit; } @@ -1182,7 +1184,7 @@ CorUnix::InternalMapViewOfFile( PROT_READ|PROT_WRITE, flags, pProcessLocalData->UnixFd, - 0 + offset ); } else @@ -1205,7 +1207,7 @@ CorUnix::InternalMapViewOfFile( prot, flags, pProcessLocalData->UnixFd, - 0 + offset ); #if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS @@ -2210,13 +2212,14 @@ MAPmmapAndRecord( Parameters: IN hFile - file to map + IN offset - offset within hFile where the PE "file" is located Return value: non-NULL - the base address of the mapped image NULL - error, with last error set. --*/ -void * MAPMapPEFile(HANDLE hFile) +void * MAPMapPEFile(HANDLE hFile, off_t offset) { PAL_ERROR palError = 0; IPalObject *pFileObject = NULL; @@ -2231,7 +2234,7 @@ void * MAPMapPEFile(HANDLE hFile) char* envVar; #endif - ENTRY("MAPMapPEFile (hFile=%p)\n", hFile); + ENTRY("MAPMapPEFile (hFile=%p offset=%zx)\n", hFile, offset); //Step 0: Verify values, find internal pal data structures. if (INVALID_HANDLE_VALUE == hFile) @@ -2270,13 +2273,13 @@ void * MAPMapPEFile(HANDLE hFile) //Step 1: Read the PE headers and reserve enough space for the whole image somewhere. IMAGE_DOS_HEADER dosHeader; IMAGE_NT_HEADERS ntHeader; - if (sizeof(dosHeader) != pread(fd, &dosHeader, sizeof(dosHeader), 0)) + if (sizeof(dosHeader) != pread(fd, &dosHeader, sizeof(dosHeader), offset)) { palError = FILEGetLastErrorFromErrno(); ERROR_(LOADER)( "reading dos header failed\n" ); goto done; } - if (sizeof(ntHeader) != pread(fd, &ntHeader, sizeof(ntHeader), dosHeader.e_lfanew)) + if (sizeof(ntHeader) != pread(fd, &ntHeader, sizeof(ntHeader), offset + dosHeader.e_lfanew)) { palError = FILEGetLastErrorFromErrno(); goto done; @@ -2418,7 +2421,7 @@ void * MAPMapPEFile(HANDLE hFile) //first, map the PE header to the first page in the image. Get pointers to the section headers palError = MAPmmapAndRecord(pFileObject, loadedBase, - loadedBase, headerSize, PROT_READ, MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, 0, + loadedBase, headerSize, PROT_READ, MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, offset, (void**)&loadedHeader); if (NO_ERROR != palError) { @@ -2511,7 +2514,7 @@ void * MAPMapPEFile(HANDLE hFile) prot, MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, - currentHeader.PointerToRawData, + offset + currentHeader.PointerToRawData, §ionData); if (NO_ERROR != palError) { @@ -2541,7 +2544,7 @@ void * MAPMapPEFile(HANDLE hFile) palError = MAPRecordMapping(pFileObject, loadedBase, prevSectionEnd, - (char*)imageEnd - (char*)prevSectionEnd, + offset + (char*)imageEnd - (char*)prevSectionEnd, PROT_NONE); if (NO_ERROR != palError) { diff --git a/src/coreclr/src/pal/src/map/virtual.cpp b/src/coreclr/src/pal/src/map/virtual.cpp index d6a33c793143c..3d796d9efc17a 100644 --- a/src/coreclr/src/pal/src/map/virtual.cpp +++ b/src/coreclr/src/pal/src/map/virtual.cpp @@ -2276,6 +2276,12 @@ void *ExecutableMemoryAllocator::AllocateMemoryWithinRange(const void *beginAddr at which the allocator should start allocating memory from its reserved memory range. --*/ +#ifdef __sun +// The upper limit of the random() function on SunOS derived operating systems is not RAND_MAX, but 2^31-1. +#define OFFSET_RAND_MAX 0x7FFFFFFF +#else +#define OFFSET_RAND_MAX RAND_MAX +#endif int32_t ExecutableMemoryAllocator::GenerateRandomStartOffset() { int32_t pageCount; @@ -2284,7 +2290,7 @@ int32_t ExecutableMemoryAllocator::GenerateRandomStartOffset() // This code is similar to what coreclr runtime does on Windows. // It generates a random number of pages to skip between 0...MaxStartPageOffset. srandom(time(NULL)); - pageCount = (int32_t)(MaxStartPageOffset * (int64_t)random() / RAND_MAX); + pageCount = (int32_t)(MaxStartPageOffset * (int64_t)random() / OFFSET_RAND_MAX); return pageCount * GetVirtualPageSize(); } diff --git a/src/coreclr/src/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/src/pal/src/sharedmemory/sharedmemory.cpp index 619fae0852826..d61b92c939fd0 100644 --- a/src/coreclr/src/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/src/pal/src/sharedmemory/sharedmemory.cpp @@ -878,6 +878,7 @@ void SharedMemoryProcessDataHeader::Close() // nonzero, don't clean up any object or global process-local state. if (m_refCount == 0) { + _ASSERTE(m_data == nullptr || m_data->CanClose()); SharedMemoryManager::RemoveProcessDataHeader(this); } @@ -1015,7 +1016,12 @@ void SharedMemoryProcessDataHeader::IncRefCount() _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); _ASSERTE(m_refCount != 0); - ++m_refCount; + if (++m_refCount == 2 && m_data != nullptr && m_data->HasImplicitRef()) + { + // The synchronization object got an explicit ref that will govern its lifetime, remove the implicit ref + --m_refCount; + m_data->SetHasImplicitRef(false); + } } void SharedMemoryProcessDataHeader::DecRefCount() @@ -1023,10 +1029,21 @@ void SharedMemoryProcessDataHeader::DecRefCount() _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); _ASSERTE(m_refCount != 0); - if (--m_refCount == 0) + if (--m_refCount != 0) + { + return; + } + + if (m_data != nullptr && !m_data->CanClose()) { - InternalDelete(this); + // Extend the lifetime of the synchronization object. The process data object is responsible for removing this extra ref + // when the synchronization object transitions into a state where it can be closed. + ++m_refCount; + m_data->SetHasImplicitRef(true); + return; } + + InternalDelete(this); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/src/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/src/pal/src/synchmgr/synchmanager.cpp index 9d868c00e09f9..52b8843889d23 100644 --- a/src/coreclr/src/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/src/pal/src/synchmgr/synchmanager.cpp @@ -568,6 +568,17 @@ namespace CorUnix CThreadSynchronizationInfo * pSynchInfo = &pthrTarget->synchronizationInfo; CPalSynchronizationManager * pSynchManager = GetInstance(); + // The shared memory manager's process lock is acquired before calling into some PAL synchronization primitives that may + // take the PAL synchronization manager's synch lock (acquired below). For example, when using a file lock + // implementation for a named mutex (see NamedMutexProcessData::NamedMutexProcessData()), under the shared memory + // manager's process lock, CreateMutex is called, which acquires the PAL synchronization manager's synch lock. The same + // lock order needs to be maintained here to avoid a deadlock. + bool abandonNamedMutexes = pSynchInfo->OwnsAnyNamedMutex(); + if (abandonNamedMutexes) + { + SharedMemoryManager::AcquireCreationDeletionProcessLock(); + } + // Local lock AcquireLocalSynchLock(pthrCurrent); @@ -610,15 +621,18 @@ namespace CorUnix pSynchManager->m_cacheOwnedObjectsListNodes.Add(pthrCurrent, poolnItem); } - // Abandon owned named mutexes - while (true) + if (abandonNamedMutexes) { - NamedMutexProcessData *processData = pSynchInfo->RemoveFirstOwnedNamedMutex(); - if (processData == nullptr) + // Abandon owned named mutexes + while (true) { - break; + NamedMutexProcessData *processData = pSynchInfo->RemoveFirstOwnedNamedMutex(); + if (processData == nullptr) + { + break; + } + processData->Abandon(); } - processData->Abandon(); } if (pthrTarget != pthrCurrent) @@ -660,6 +674,12 @@ namespace CorUnix } ReleaseLocalSynchLock(pthrCurrent); + + if (abandonNamedMutexes) + { + SharedMemoryManager::ReleaseCreationDeletionProcessLock(); + } + DiscardAllPendingAPCs(pthrCurrent, pthrTarget); return palErr; @@ -4036,7 +4056,6 @@ namespace CorUnix m_ownedNamedMutexListHead(nullptr) { InitializeListHead(&m_leOwnedObjsList); - InitializeCriticalSection(&m_ownedNamedMutexListLock); #ifdef SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING m_lPendingSignalingCount = 0; @@ -4046,7 +4065,6 @@ namespace CorUnix CThreadSynchronizationInfo::~CThreadSynchronizationInfo() { - DeleteCriticalSection(&m_ownedNamedMutexListLock); if (NULL != m_shridWaitAwakened) { free(m_shridWaitAwakened); @@ -4283,20 +4301,21 @@ namespace CorUnix void CThreadSynchronizationInfo::AddOwnedNamedMutex(NamedMutexProcessData *processData) { + _ASSERTE(this == &GetCurrentPalThread()->synchronizationInfo); _ASSERTE(processData != nullptr); + _ASSERTE(processData->IsLockOwnedByCurrentThread()); _ASSERTE(processData->GetNextInThreadOwnedNamedMutexList() == nullptr); - EnterCriticalSection(&m_ownedNamedMutexListLock); processData->SetNextInThreadOwnedNamedMutexList(m_ownedNamedMutexListHead); m_ownedNamedMutexListHead = processData; - LeaveCriticalSection(&m_ownedNamedMutexListLock); } void CThreadSynchronizationInfo::RemoveOwnedNamedMutex(NamedMutexProcessData *processData) { + _ASSERTE(this == &GetCurrentPalThread()->synchronizationInfo); _ASSERTE(processData != nullptr); + _ASSERTE(processData->IsLockOwnedByCurrentThread()); - EnterCriticalSection(&m_ownedNamedMutexListLock); if (m_ownedNamedMutexListHead == processData) { m_ownedNamedMutexListHead = processData->GetNextInThreadOwnedNamedMutexList(); @@ -4321,38 +4340,44 @@ namespace CorUnix } _ASSERTE(found); } - LeaveCriticalSection(&m_ownedNamedMutexListLock); } NamedMutexProcessData *CThreadSynchronizationInfo::RemoveFirstOwnedNamedMutex() { - EnterCriticalSection(&m_ownedNamedMutexListLock); + _ASSERTE(this == &GetCurrentPalThread()->synchronizationInfo); + NamedMutexProcessData *processData = m_ownedNamedMutexListHead; if (processData != nullptr) { + _ASSERTE(processData->IsLockOwnedByCurrentThread()); m_ownedNamedMutexListHead = processData->GetNextInThreadOwnedNamedMutexList(); processData->SetNextInThreadOwnedNamedMutexList(nullptr); } - LeaveCriticalSection(&m_ownedNamedMutexListLock); return processData; } bool CThreadSynchronizationInfo::OwnsNamedMutex(NamedMutexProcessData *processData) { - EnterCriticalSection(&m_ownedNamedMutexListLock); - bool found = false; + _ASSERTE(this == &GetCurrentPalThread()->synchronizationInfo); + for (NamedMutexProcessData *current = m_ownedNamedMutexListHead; current != nullptr; current = current->GetNextInThreadOwnedNamedMutexList()) { + _ASSERTE(current->IsLockOwnedByCurrentThread()); if (current == processData) { - found = true; - break; + return true; } } - LeaveCriticalSection(&m_ownedNamedMutexListLock); - return found; + + return false; + } + + bool CThreadSynchronizationInfo::OwnsAnyNamedMutex() const + { + _ASSERTE(this == &GetCurrentPalThread()->synchronizationInfo); + return m_ownedNamedMutexListHead != nullptr; } #if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING diff --git a/src/coreclr/src/pal/src/synchobj/mutex.cpp b/src/coreclr/src/pal/src/synchobj/mutex.cpp index a4bb340a436a9..d36752a204057 100644 --- a/src/coreclr/src/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/src/pal/src/synchobj/mutex.cpp @@ -1247,7 +1247,8 @@ NamedMutexProcessData::NamedMutexProcessData( m_sharedLockFileDescriptor(sharedLockFileDescriptor), #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX m_lockOwnerThread(nullptr), - m_nextInThreadOwnedNamedMutexList(nullptr) + m_nextInThreadOwnedNamedMutexList(nullptr), + m_hasRefFromLockOwnerThread(false) { _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); _ASSERTE(processDataHeader != nullptr); @@ -1263,6 +1264,39 @@ NamedMutexProcessData::NamedMutexProcessData( #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX } +bool NamedMutexProcessData::CanClose() const +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + + // When using a pthread robust mutex, the mutex may only be unlocked and destroyed by the thread that owns the lock. When + // using file locks, even though any thread could release that lock, the behavior is kept consistent to the more + // conservative case. If the last handle to the mutex is closed when a different thread owns the lock, the mutex cannot be + // closed. Due to these limitations, the behavior in this corner case is necessarily different from Windows. The caller will + // extend the lifetime of the mutex and will call OnLifetimeExtendedDueToCannotClose() shortly. + return m_lockOwnerThread == nullptr || m_lockOwnerThread == GetCurrentPalThread(); +} + +bool NamedMutexProcessData::HasImplicitRef() const +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + return m_hasRefFromLockOwnerThread; +} + +void NamedMutexProcessData::SetHasImplicitRef(bool value) +{ + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + _ASSERTE(m_hasRefFromLockOwnerThread != value); + _ASSERTE(!value || !CanClose()); + + // If value == true: + // The mutex could not be closed and the caller extended the lifetime of the mutex. Record that the lock owner thread + // should release the ref when the lock is released on that thread. + // Else: + // The mutex has an implicit ref and got the first explicit reference from this process. Remove the implicit ref from the + // lock owner thread. + m_hasRefFromLockOwnerThread = value; +} + void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData) { _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); @@ -1272,20 +1306,23 @@ void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData) // active references to the mutex. So when shutting down abruptly, don't clean up any object or global process-local state. if (!isAbruptShutdown) { + _ASSERTE(CanClose()); + _ASSERTE(!m_hasRefFromLockOwnerThread); + CPalThread *lockOwnerThread = m_lockOwnerThread; - if (lockOwnerThread != nullptr) + if (lockOwnerThread == GetCurrentPalThread()) { - // The mutex was not released before it was closed. If the lock is owned by the current thread, abandon the mutex. - // In both cases, clean up the owner thread's list of owned mutexes. + // The mutex was not released before the last handle to it from this process was closed on the lock-owning thread. + // Another process may still have a handle to the mutex, but since it appears as though this process would not be + // releasing the mutex, abandon the mutex. The only way for this process to otherwise release the mutex is to open + // another handle to it and release the lock on the same thread, which would be incorrect-looking code. The behavior + // in this corner case is different from Windows. lockOwnerThread->synchronizationInfo.RemoveOwnedNamedMutex(this); - if (lockOwnerThread == GetCurrentPalThread()) - { - Abandon(); - } - else - { - m_lockOwnerThread = nullptr; - } + Abandon(); + } + else + { + _ASSERTE(lockOwnerThread == nullptr); } if (releaseSharedData) @@ -1337,18 +1374,20 @@ NamedMutexSharedData *NamedMutexProcessData::GetSharedData() const void NamedMutexProcessData::SetLockOwnerThread(CorUnix::CPalThread *lockOwnerThread) { _ASSERTE(lockOwnerThread == nullptr || lockOwnerThread == GetCurrentPalThread()); - _ASSERTE(GetSharedData()->IsLockOwnedByCurrentThread()); + _ASSERTE(IsLockOwnedByCurrentThread()); m_lockOwnerThread = lockOwnerThread; } NamedMutexProcessData *NamedMutexProcessData::GetNextInThreadOwnedNamedMutexList() const { + _ASSERTE(IsLockOwnedByCurrentThread()); return m_nextInThreadOwnedNamedMutexList; } void NamedMutexProcessData::SetNextInThreadOwnedNamedMutexList(NamedMutexProcessData *next) { + _ASSERTE(IsLockOwnedByCurrentThread()); m_nextInThreadOwnedNamedMutexList = next; } @@ -1367,7 +1406,7 @@ MutexTryAcquireLockResult NamedMutexProcessData::TryAcquireLock(DWORD timeoutMil // at the appropriate time, see ReleaseLock(). if (m_lockCount != 0) { - _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); // otherwise, this thread would not have acquired the lock + _ASSERTE(IsLockOwnedByCurrentThread()); // otherwise, this thread would not have acquired the lock _ASSERTE(GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); if (m_lockCount + 1 < m_lockCount) @@ -1442,7 +1481,7 @@ MutexTryAcquireLockResult NamedMutexProcessData::TryAcquireLock(DWORD timeoutMil // Check if it's a recursive lock attempt if (m_lockCount != 0) { - _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); // otherwise, this thread would not have acquired the process lock + _ASSERTE(IsLockOwnedByCurrentThread()); // otherwise, this thread would not have acquired the process lock _ASSERTE(GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); if (m_lockCount + 1 < m_lockCount) @@ -1565,12 +1604,13 @@ MutexTryAcquireLockResult NamedMutexProcessData::TryAcquireLock(DWORD timeoutMil void NamedMutexProcessData::ReleaseLock() { - if (!GetSharedData()->IsLockOwnedByCurrentThread()) + if (!IsLockOwnedByCurrentThread()) { throw SharedMemoryException(static_cast(NamedMutexError::ThreadHasNotAcquiredMutex)); } _ASSERTE(GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); + _ASSERTE(!m_hasRefFromLockOwnerThread); _ASSERTE(m_lockCount != 0); --m_lockCount; @@ -1586,23 +1626,31 @@ void NamedMutexProcessData::ReleaseLock() void NamedMutexProcessData::Abandon() { + _ASSERTE(SharedMemoryManager::IsCreationDeletionProcessLockAcquired()); + NamedMutexSharedData *sharedData = GetSharedData(); - _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); + _ASSERTE(IsLockOwnedByCurrentThread()); _ASSERTE(m_lockCount != 0); sharedData->SetIsAbandoned(true); m_lockCount = 0; SetLockOwnerThread(nullptr); ActuallyReleaseLock(); + + if (m_hasRefFromLockOwnerThread) + { + m_hasRefFromLockOwnerThread = false; + m_processDataHeader->DecRefCount(); + } } void NamedMutexProcessData::ActuallyReleaseLock() { - NamedMutexSharedData *sharedData = GetSharedData(); - _ASSERTE(sharedData->IsLockOwnedByCurrentThread()); + _ASSERTE(IsLockOwnedByCurrentThread()); _ASSERTE(!GetCurrentPalThread()->synchronizationInfo.OwnsNamedMutex(this)); _ASSERTE(m_lockCount == 0); + NamedMutexSharedData *sharedData = GetSharedData(); sharedData->ClearLockOwner(); #if NAMED_MUTEX_USE_PTHREAD_MUTEX diff --git a/src/coreclr/src/pal/src/thread/thread.cpp b/src/coreclr/src/pal/src/thread/thread.cpp index a6a14c20f9ba8..fa4a663801353 100644 --- a/src/coreclr/src/pal/src/thread/thread.cpp +++ b/src/coreclr/src/pal/src/thread/thread.cpp @@ -43,6 +43,15 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do #include #include #include +#elif defined(__sun) +#ifndef _KERNEL +#define _KERNEL +#define UNDEF_KERNEL +#endif +#include +#ifdef UNDEF_KERNEL +#undef _KERNEL +#endif #endif #include @@ -1441,7 +1450,11 @@ CorUnix::GetThreadTimesInternal( CPalThread *pThread; CPalThread *pTargetThread; IPalObject *pobjThread = NULL; +#ifdef __sun + int fd; +#else // __sun clockid_t cid; +#endif // __sun pThread = InternalGetCurrentThread(); @@ -1463,7 +1476,6 @@ CorUnix::GetThreadTimesInternal( #if HAVE_PTHREAD_GETCPUCLOCKID if (pthread_getcpuclockid(pTargetThread->GetPThreadSelf(), &cid) != 0) -#endif { ASSERT("Unable to get clock from thread\n", hThread); SetLastError(ERROR_INTERNAL_ERROR); @@ -1479,6 +1491,33 @@ CorUnix::GetThreadTimesInternal( pTargetThread->Unlock(pThread); goto SetTimesToZero; } +#elif defined(__sun) + timestruc_t ts; + int readResult; + char statusFilename[64]; + snprintf(statusFilename, sizeof(statusFilename), "/proc/%d/lwp/%d/lwpstatus", getpid(), pTargetThread->GetLwpId()); + fd = open(statusFilename, O_RDONLY); + if (fd == -1) + { + ASSERT("open(%s) failed; errno is %d (%s)\n", statusFilename, errno, strerror(errno)); + SetLastError(ERROR_INTERNAL_ERROR); + pTargetThread->Unlock(pThread); + goto SetTimesToZero; + } + + lwpstatus_t status; + do + { + readResult = read(fd, &status, sizeof(status)); + } + while ((readResult == -1) && (errno == EINTR)); + + close(fd); + + ts = status.pr_utime; +#else // HAVE_PTHREAD_GETCPUCLOCKID +#error "Don't know how to obtain user cpu time on this platform." +#endif // HAVE_PTHREAD_GETCPUCLOCKID pTargetThread->Unlock(pThread); @@ -1641,6 +1680,13 @@ CorUnix::InternalSetThreadDescription( pTargetThread->Lock(pThread); + // Ignore requests to set the main thread name because + // it causes the value returned by Process.ProcessName to change. + if ((pid_t)pTargetThread->GetThreadId() == getpid()) + { + goto InternalSetThreadDescriptionExit; + } + /* translate the wide char lpThreadDescription string to multibyte string */ nameSize = WideCharToMultiByte(CP_ACP, 0, lpThreadDescription, -1, NULL, 0, NULL, NULL); diff --git a/src/coreclr/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt b/src/coreclr/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt index 37ff7de67a1fc..2d2d037ca29c6 100644 --- a/src/coreclr/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt +++ b/src/coreclr/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt @@ -26,10 +26,10 @@ if(CLR_CMAKE_TARGET_OSX) set(EXPORTS_LINKER_OPTION1 -Wl,-exported_symbols_list,${EXPORTS_FILE1}) endif(CLR_CMAKE_TARGET_OSX) -if(CLR_CMAKE_HOST_SUNOS) +if(CLR_CMAKE_TARGET_SUNOS) # Add linker exports file option set(EXPORTS_LINKER_OPTION -Wl,-M,${EXPORTS_FILE}) -endif(CLR_CMAKE_HOST_SUNOS) +endif(CLR_CMAKE_TARGET_SUNOS) set(DLL1SOURCES dlltest1.cpp) add_library(paltest_pal_sxs_test1_dll1 SHARED ${DLL1SOURCES}) diff --git a/src/coreclr/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp b/src/coreclr/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp index 6635d76a80a07..761bb47b5c6be 100644 --- a/src/coreclr/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp +++ b/src/coreclr/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp @@ -60,9 +60,12 @@ extern bool WriteHeaderInfo(const char *path, char sharedMemoryType, char versio { \ if (!g_isParent) \ { \ - Trace("Child process: "); \ + Trace("'paltest_namedmutex_test1' child process failed at line %u. Expression: " #expression "\n", __LINE__); \ + } \ + else \ + { \ + Trace("'paltest_namedmutex_test1' failed at line %u. Expression: " #expression "\n", __LINE__); \ } \ - Trace("'paltest_namedmutex_test1' failed at line %u. Expression: " #expression "\n", __LINE__); \ fflush(stdout); \ return false; \ } \ @@ -516,7 +519,7 @@ bool MutualExclusionTests_Parent() TestAssert(WaitForSingleObject(m, static_cast(-1)) == WAIT_OBJECT_0); // lock the mutex with no timeout and release TestAssert(m.Release()); - UninitializeParent(testName, parentEvents); + TestAssert(UninitializeParent(testName, parentEvents)); return true; } @@ -539,7 +542,7 @@ DWORD PALAPI MutualExclusionTests_Child(void *arg = nullptr) TestAssert(m.Release()); // release the lock } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); return 0; } @@ -622,7 +625,7 @@ bool LifetimeTests_Parent() TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes second reference TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); - UninitializeParent(testName, parentEvents); + TestAssert(UninitializeParent(testName, parentEvents)); return true; } @@ -653,7 +656,7 @@ DWORD PALAPI LifetimeTests_Child(void *arg = nullptr) TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); return 0; } @@ -702,11 +705,11 @@ bool AbandonTests_Parent() TestAssert(parentEvents[1].Release()); // child sleeps for short duration and abandons the mutex TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex - UninitializeParent(testName, parentEvents, false /* releaseParentEvents */); // parent events are released above + TestAssert(UninitializeParent(testName, parentEvents, false /* releaseParentEvents */)); // parent events are released above } // Verify that the mutex lock is owned by this thread, by starting a new thread and trying to lock it - StartThread(AbandonTests_Child_TryLock); + TestAssert(StartThread(AbandonTests_Child_TryLock)); { AutoCloseMutexHandle parentEvents[2], childEvents[2]; TestAssert(InitializeParent(testName, parentEvents, childEvents)); @@ -714,11 +717,11 @@ bool AbandonTests_Parent() TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child tries to lock mutex - UninitializeParent(testName, parentEvents); + TestAssert(UninitializeParent(testName, parentEvents)); } // Verify that the mutex lock is owned by this thread, by starting a new process and trying to lock it - StartProcess("AbandonTests_Child_TryLock"); + TestAssert(StartProcess("AbandonTests_Child_TryLock")); AutoCloseMutexHandle parentEvents[2], childEvents[2]; TestAssert(InitializeParent(testName, parentEvents, childEvents)); int ei = 0; @@ -730,7 +733,7 @@ bool AbandonTests_Parent() TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_OBJECT_0); // lock again to see it's not abandoned anymore TestAssert(m.Release()); - UninitializeParent(testName, parentEvents, false /* releaseParentEvents */); // parent events are released above + TestAssert(UninitializeParent(testName, parentEvents)); // Since the child abandons the mutex, and a child process may not release the file lock on the shared memory file before // indicating completion to the parent, make sure to delete the shared memory file by repeatedly opening/closing the mutex @@ -772,7 +775,7 @@ DWORD PALAPI AbandonTests_Child_GracefulExit_Close(void *arg = nullptr) m.Close(); // close mutex without releasing lock } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); return 0; } @@ -801,7 +804,7 @@ DWORD AbandonTests_Child_GracefulExit_NoClose(void *arg = nullptr) m.Abandon(); // don't close the mutex } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); return 0; } @@ -830,7 +833,7 @@ DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr) m.Abandon(); // don't close the mutex } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); } TestAssert(test_kill(currentPid) == 0); // abandon the mutex abruptly @@ -894,7 +897,7 @@ DWORD AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit(void *arg = null m.Close(); // close mutex without releasing lock (root parent expects the mutex to be abandoned) } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); return 0; } @@ -917,14 +920,12 @@ DWORD PALAPI AbandonTests_Child_TryLock(void *arg) TestAssert(WaitForSingleObject(m, g_expectedTimeoutMilliseconds) == WAIT_TIMEOUT); } - UninitializeChild(childRunningEvent, parentEvents, childEvents); + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); return 0; } bool AbandonTests() { - const char *testName = "AbandonTests"; - // Abandon by graceful exit where the lock owner closes the mutex before releasing it, unblocks a waiter TestAssert(StartThread(AbandonTests_Child_GracefulExit_Close)); TestAssert(AbandonTests_Parent()); @@ -945,6 +946,151 @@ bool AbandonTests() return true; } +bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnSameThread() +{ + const char *testName = "LockAndCloseWithoutThreadExitTests"; + + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex and closes second reference to mutex on lock-owner thread + TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // attempt to lock and fail + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes last reference to mutex on lock-owner thread + TestAssert(WaitForSingleObject(m, 0) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex + TestAssert(m.Release()); + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child exits + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + m.Close(); + TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + + TestAssert(UninitializeParent(testName, parentEvents)); + return true; +} + +DWORD PALAPI LockAndCloseWithoutThreadExitTests_Child_CloseOnSameThread(void *arg = nullptr) +{ + const char *testName = "LockAndCloseWithoutThreadExitTests"; + + TestAssert(test_getpid() != g_parentPid); // this test needs to run in a separate process + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + char name[MaxPathSize]; + + // ... parent waits for child to lock and close second reference to mutex + AutoCloseMutexHandle m(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits for child to close last reference to mutex + + m.Close(); // close mutex on lock-owner thread without releasing lock + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies while this thread is still active + + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); + return 0; +} + +DWORD PALAPI LockAndCloseWithoutThreadExitTests_ChildThread_CloseMutex(void *arg); + +bool LockAndCloseWithoutThreadExitTests_Parent_CloseOnDifferentThread() +{ + const char *testName = "LockAndCloseWithoutThreadExitTests"; + + AutoCloseMutexHandle parentEvents[2], childEvents[2]; + TestAssert(InitializeParent(testName, parentEvents, childEvents)); + int ei = 0; + char name[MaxPathSize]; + AutoCloseMutexHandle m; + + TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child locks mutex and closes second reference to mutex on lock-owner thread + TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // attempt to lock and fail + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes last reference to mutex on non-lock-owner thread + TestAssert(WaitForSingleObject(m, 0) == WAIT_TIMEOUT); // attempt to lock and fail + m.Close(); + m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); // child has implicit reference to mutex + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child closes new reference to mutex on lock-owner thread + TestAssert(WaitForSingleObject(m, 0) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex + TestAssert(m.Release()); + + TestAssert(YieldToChild(parentEvents, childEvents, ei)); // child exits + TestAssert(TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + m.Close(); + TestAssert(!TestFileExists(BuildGlobalShmFilePath(testName, name, NamePrefix))); + + TestAssert(UninitializeParent(testName, parentEvents)); + return true; +} + +DWORD PALAPI LockAndCloseWithoutThreadExitTests_Child_CloseOnDifferentThread(void *arg = nullptr) +{ + const char *testName = "LockAndCloseWithoutThreadExitTests"; + + TestAssert(test_getpid() != g_parentPid); // this test needs to run in a separate process + + AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2]; + TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents)); + int ei = 0; + char name[MaxPathSize]; + + // ... parent waits for child to lock and close second reference to mutex + AutoCloseMutexHandle m(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))); + TestAssert(m != nullptr); + TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0); + TestAssert(AutoCloseMutexHandle(TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix))) != nullptr); + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent waits for child to close last reference to mutex + + // Close the mutex on a thread that is not the lock-owner thread, without releasing the lock + HANDLE closeMutexThread = nullptr; + TestAssert(StartThread(LockAndCloseWithoutThreadExitTests_ChildThread_CloseMutex, (HANDLE)m, &closeMutexThread)); + TestAssert(closeMutexThread != nullptr); + TestAssert(WaitForSingleObject(closeMutexThread, FailTimeoutMilliseconds) == WAIT_OBJECT_0); + TestAssert(CloseHandle(closeMutexThread)); + m.Abandon(); // mutex is already closed, don't close it again + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies while this lock-owner thread is still active + + m = TestOpenMutex(BuildName(testName, name, GlobalPrefix, NamePrefix)); + TestAssert(m != nullptr); + m.Close(); // close mutex on lock-owner thread without releasing lock + TestAssert(YieldToParent(parentEvents, childEvents, ei)); // parent verifies while this thread is still active + + TestAssert(UninitializeChild(childRunningEvent, parentEvents, childEvents)); + return 0; +} + +DWORD PALAPI LockAndCloseWithoutThreadExitTests_ChildThread_CloseMutex(void *arg) +{ + TestAssert(arg != nullptr); + AutoCloseMutexHandle((HANDLE)arg).Close(); + return 0; +} + +bool LockAndCloseWithoutThreadExitTests() +{ + TestAssert(StartProcess("LockAndCloseWithoutThreadExitTests_Child_CloseOnSameThread")); + TestAssert(LockAndCloseWithoutThreadExitTests_Parent_CloseOnSameThread()); + + TestAssert(StartProcess("LockAndCloseWithoutThreadExitTests_Child_CloseOnDifferentThread")); + TestAssert(LockAndCloseWithoutThreadExitTests_Parent_CloseOnDifferentThread()); + + return true; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Test harness @@ -954,7 +1100,8 @@ bool (*const (TestList[]))() = HeaderMismatchTests, MutualExclusionTests, LifetimeTests, - AbandonTests + AbandonTests, + LockAndCloseWithoutThreadExitTests }; bool RunTests() @@ -1125,6 +1272,14 @@ int __cdecl main(int argc, char **argv) { AbandonTests_Child_TryLock(); } + else if (test_strcmp(argv[2], "LockAndCloseWithoutThreadExitTests_Child_CloseOnSameThread") == 0) + { + LockAndCloseWithoutThreadExitTests_Child_CloseOnSameThread(); + } + else if (test_strcmp(argv[2], "LockAndCloseWithoutThreadExitTests_Child_CloseOnDifferentThread") == 0) + { + LockAndCloseWithoutThreadExitTests_Child_CloseOnDifferentThread(); + } ExitProcess(PASS); return PASS; } diff --git a/src/coreclr/src/pal/tools/set-cmake-path.ps1 b/src/coreclr/src/pal/tools/set-cmake-path.ps1 index f367ad127c3ff..689c8c5596a55 100644 --- a/src/coreclr/src/pal/tools/set-cmake-path.ps1 +++ b/src/coreclr/src/pal/tools/set-cmake-path.ps1 @@ -33,7 +33,7 @@ function GetCMakeInfo($regKey) function LocateCMake { - $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from http://www.cmake.org/download/ and ensure it is on your path." + $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from https://cmake.org/download/ and ensure it is on your path." $inPathPath = (get-command cmake.exe -ErrorAction SilentlyContinue) if ($inPathPath -ne $null) { # Resolve the first version of CMake if multiple commands are found @@ -64,7 +64,7 @@ try { $version = [Version]$(& $cmakePath --version | Select-String -Pattern '\d+\.\d+\.\d+' | %{$_.Matches.Value}) if ($version -lt [Version]"3.14.0") { - Throw "This repository requires CMake 3.14. The newest version of CMake installed is $version. Please install CMake 3.14 or newer from http://www.cmake.org/download/ and ensure it is on your path." + Throw "This repository requires CMake 3.14. The newest version of CMake installed is $version. Please install CMake 3.14 or newer from https://cmake.org/download/ and ensure it is on your path." } [System.Console]::WriteLine("set CMakePath=" + $cmakePath) diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SettableReadOnlyDataBlob.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/MethodReadOnlyDataNode.cs similarity index 71% rename from src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SettableReadOnlyDataBlob.cs rename to src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/MethodReadOnlyDataNode.cs index bf7de904bb351..7c1ae117056b2 100644 --- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SettableReadOnlyDataBlob.cs +++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/MethodReadOnlyDataNode.cs @@ -10,24 +10,22 @@ namespace ILCompiler.DependencyAnalysis { - public class SettableReadOnlyDataBlob : ObjectNode, ISymbolDefinitionNode + public class MethodReadOnlyDataNode : ObjectNode, ISymbolDefinitionNode { - private Utf8String _name; - private ObjectNodeSection _section; + private MethodDesc _owningMethod; private ObjectData _data; - public SettableReadOnlyDataBlob(Utf8String name, ObjectNodeSection section) + public MethodReadOnlyDataNode(MethodDesc owningMethod) { - _name = name; - _section = section; + _owningMethod = owningMethod; } - public override ObjectNodeSection Section => _section; + public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection; public override bool StaticDependenciesAreComputed => _data != null; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(_name); + sb.Append("__readonlydata_" + nameMangler.GetMangledMethodName(_owningMethod)); } public int Offset => 0; public override bool IsShareable => true; @@ -50,7 +48,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { - return _name.CompareTo(((SettableReadOnlyDataBlob)other)._name); + return comparer.Compare(_owningMethod, ((MethodReadOnlyDataNode)other)._owningMethod); } #endif } diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs index b89b9482403b7..5a672f953c96b 100644 --- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs +++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs @@ -39,16 +39,17 @@ public bool IsStandardSection { get { - return this == DataSection || this == ReadOnlyDataSection || this == FoldableReadOnlyDataSection || this == TextSection || this == XDataSection; + return this == DataSection || this == ReadOnlyDataSection || this == FoldableReadOnlyDataSection || this == TextSection || this == XDataSection || this == BssSection; } } public static readonly ObjectNodeSection XDataSection = new ObjectNodeSection("xdata", SectionType.ReadOnly); public static readonly ObjectNodeSection DataSection = new ObjectNodeSection("data", SectionType.Writeable); public static readonly ObjectNodeSection ReadOnlyDataSection = new ObjectNodeSection("rdata", SectionType.ReadOnly); - public static readonly ObjectNodeSection FoldableReadOnlyDataSection = new ObjectNodeSection("rdata$F", SectionType.ReadOnly); + public static readonly ObjectNodeSection FoldableReadOnlyDataSection = new ObjectNodeSection("rdata", SectionType.ReadOnly); public static readonly ObjectNodeSection TextSection = new ObjectNodeSection("text", SectionType.Executable); public static readonly ObjectNodeSection TLSSection = new ObjectNodeSection("TLS", SectionType.Writeable); + public static readonly ObjectNodeSection BssSection = new ObjectNodeSection("bss", SectionType.Writeable); public static readonly ObjectNodeSection ManagedCodeWindowsContentSection = new ObjectNodeSection(".managedcode$I", SectionType.Executable); public static readonly ObjectNodeSection FoldableManagedCodeWindowsContentSection = new ObjectNodeSection(".managedcode$I", SectionType.Executable); public static readonly ObjectNodeSection ManagedCodeUnixContentSection = new ObjectNodeSection("__managedcode", SectionType.Executable); diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/Target_X64/TargetRegisterMap.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/Target_X64/TargetRegisterMap.cs index 808f8ed03c583..7d76bf5259b78 100644 --- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/Target_X64/TargetRegisterMap.cs +++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/Target_X64/TargetRegisterMap.cs @@ -34,6 +34,8 @@ public TargetRegisterMap(TargetOS os) case TargetOS.Linux: case TargetOS.OSX: case TargetOS.FreeBSD: + case TargetOS.SunOS: + case TargetOS.NetBSD: Arg0 = Register.RDI; Arg1 = Register.RSI; Arg2 = Register.RDX; diff --git a/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs b/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs index fbf7b61a618e0..1481a74e77b90 100644 --- a/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs +++ b/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs @@ -11,7 +11,7 @@ namespace ILCompiler { - public static class HardwareIntrinsicHelpers + public static partial class HardwareIntrinsicHelpers { /// /// Gets a value indicating whether this is a hardware intrinsic on the platform that we're compiling for. diff --git a/src/coreclr/src/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs index 5d3697c81f12e..12ded51464c64 100644 --- a/src/coreclr/src/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs +++ b/src/coreclr/src/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs @@ -90,13 +90,13 @@ public override bool ComputeContainsGCPointers(DefType type) public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) { - if (type.Context.Target.Architecture == TargetArchitecture.ARM64) + if (type.Context.Target.Architecture == TargetArchitecture.ARM64 && + type.Instantiation[0].IsPrimitiveNumeric) { return type.InstanceFieldSize.AsInt switch { 8 => ValueTypeShapeCharacteristics.Vector64Aggregate, 16 => ValueTypeShapeCharacteristics.Vector128Aggregate, - 32 => ValueTypeShapeCharacteristics.Vector256Aggregate, _ => ValueTypeShapeCharacteristics.None }; } @@ -109,8 +109,7 @@ public static bool IsVectorType(DefType type) type.Namespace == "System.Runtime.Intrinsics" && (type.Name == "Vector64`1" || type.Name == "Vector128`1" || - type.Name == "Vector256`1") && - type.Instantiation[0].IsPrimitive; + type.Name == "Vector256`1"); } } } diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.Intrinsics.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.Intrinsics.cs index a0538e9063fdf..30bc7f772362b 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.Intrinsics.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.Intrinsics.cs @@ -164,7 +164,7 @@ static IntrinsicHashtable InitializeIntrinsicHashtable() table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetRawHandle, "AllocatorOf", "System", "Activator"); // If this assert fails, make sure to add the new intrinsics to the table above and update the expected count below. - Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 55, "Please update intrinsic hash table"); + Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 56, "Please update intrinsic hash table"); return table; } diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs index 753fc0ab96da5..205304c49a36b 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs @@ -1759,23 +1759,10 @@ private CorInfoType getTypeForPrimitiveNumericClass(CORINFO_CLASS_STRUCT_* cls) { var type = HandleToObject(cls); - switch (type.Category) - { - case TypeFlags.Byte: - case TypeFlags.SByte: - case TypeFlags.UInt16: - case TypeFlags.Int16: - case TypeFlags.UInt32: - case TypeFlags.Int32: - case TypeFlags.UInt64: - case TypeFlags.Int64: - case TypeFlags.Single: - case TypeFlags.Double: - return asCorInfoType(type); + if (type.IsPrimitiveNumeric) + return asCorInfoType(type); - default: - return CorInfoType.CORINFO_TYPE_UNDEF; - } + return CorInfoType.CORINFO_TYPE_UNDEF; } private bool canCast(CORINFO_CLASS_STRUCT_* child, CORINFO_CLASS_STRUCT_* parent) @@ -2206,7 +2193,7 @@ private CorInfoType getHFAType(CORINFO_CLASS_STRUCT_* hClass) var type = (DefType)HandleToObject(hClass); // For 8-byte vectors return CORINFO_TYPE_DOUBLE, which is mapped by JIT to SIMD8. - // Otherwise, return CORINFO_TYPE_VALUECLASS, which is mapped by JIT to SIMD16. + // For 16-byte vectors return CORINFO_TYPE_VALUECLASS, which is mapped by JIT to SIMD16. // See MethodTable::GetHFAType and Compiler::GetHfaType. return (type.ValueTypeShapeCharacteristics & ValueTypeShapeCharacteristics.AggregateMask) switch { @@ -2214,7 +2201,6 @@ private CorInfoType getHFAType(CORINFO_CLASS_STRUCT_* hClass) ValueTypeShapeCharacteristics.Float64Aggregate => CorInfoType.CORINFO_TYPE_DOUBLE, ValueTypeShapeCharacteristics.Vector64Aggregate => CorInfoType.CORINFO_TYPE_DOUBLE, ValueTypeShapeCharacteristics.Vector128Aggregate => CorInfoType.CORINFO_TYPE_VALUECLASS, - ValueTypeShapeCharacteristics.Vector256Aggregate => CorInfoType.CORINFO_TYPE_VALUECLASS, _ => CorInfoType.CORINFO_TYPE_UNDEF }; } @@ -2565,7 +2551,7 @@ private bool getTailCallHelpers(ref CORINFO_RESOLVED_TOKEN callToken, CORINFO_SI private byte[] _roData; - private SettableReadOnlyDataBlob _roDataBlob; + private MethodReadOnlyDataNode _roDataBlob; private int _roDataAlignment; private int _numFrameInfos; @@ -2611,8 +2597,7 @@ private void allocMem(uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint _roData = new byte[roDataSize]; - _roDataBlob = _compilation.NodeFactory.SettableReadOnlyDataBlob( - "__readonlydata_" + _compilation.NameMangler.GetMangledMethodName(MethodBeingCompiled)); + _roDataBlob = new MethodReadOnlyDataNode(MethodBeingCompiled); roDataBlock = (void*)GetPin(_roData); } diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs index 51638ce5dae76..dae2003712ff1 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -254,6 +254,8 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X64_SSE2); if (resultflags.HasInstructionSet(InstructionSet.X64_POPCNT)) resultflags.AddInstructionSet(InstructionSet.X64_SSE42); + if (resultflags.HasInstructionSet(InstructionSet.X64_Vector256)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX); break; case TargetArchitecture.X86: @@ -285,6 +287,8 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X86_SSE2); if (resultflags.HasInstructionSet(InstructionSet.X86_POPCNT)) resultflags.AddInstructionSet(InstructionSet.X86_SSE42); + if (resultflags.HasInstructionSet(InstructionSet.X86_Vector256)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX); break; } @@ -373,6 +377,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X64_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet.X64_SSE42)) resultflags.AddInstructionSet(InstructionSet.X64_POPCNT); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX)) + resultflags.AddInstructionSet(InstructionSet.X64_Vector256); break; case TargetArchitecture.X86: @@ -404,6 +410,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X86_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet.X86_SSE42)) resultflags.AddInstructionSet(InstructionSet.X86_POPCNT); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX)) + resultflags.AddInstructionSet(InstructionSet.X86_Vector256); break; } diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt index 479aea6562cef..44a9139982108 100644 --- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt @@ -50,6 +50,7 @@ instructionset ,X86 ,Popcnt , ,15 ,POPCNT ,popcnt implication ,X86 ,POPCNT ,SSE42 instructionset ,X86 , , , ,Vector128, instructionset ,X86 , , , ,Vector256, +implication ,X86 ,Vector256 ,AVX ; Definition of X64 instruction sets (Define ) definearch ,X64 ,64Bit ,X64 diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs index 22b03fb4d0abe..cd7f45d7f4ce0 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs @@ -321,7 +321,6 @@ public int GetHomogeneousAggregateElementSize() ValueTypeShapeCharacteristics.Float64Aggregate => 8, ValueTypeShapeCharacteristics.Vector64Aggregate => 8, ValueTypeShapeCharacteristics.Vector128Aggregate => 16, - ValueTypeShapeCharacteristics.Vector256Aggregate => 16, _ => throw new InvalidOperationException() }; } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs index 7cda8ce7b648a..d43eb0039099d 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs @@ -132,11 +132,6 @@ public enum ValueTypeShapeCharacteristics /// Vector128Aggregate = 0x08, - /// - /// The type is an aggregate of 256-bit short-vector values. - /// - Vector256Aggregate = 0x10, - /// /// The mask for homogeneous aggregates of floating-point values. /// @@ -145,7 +140,7 @@ public enum ValueTypeShapeCharacteristics /// /// The mask for homogeneous aggregates of short-vector values. /// - ShortVectorAggregateMask = Vector64Aggregate | Vector128Aggregate | Vector256Aggregate, + ShortVectorAggregateMask = Vector64Aggregate | Vector128Aggregate, /// /// The mask for homogeneous aggregates. diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 729620e6f2013..4c7c5cfb6c599 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -906,7 +906,6 @@ private ValueTypeShapeCharacteristics ComputeHomogeneousAggregateCharacteristic( ValueTypeShapeCharacteristics.Float64Aggregate => 8, ValueTypeShapeCharacteristics.Vector64Aggregate => 8, ValueTypeShapeCharacteristics.Vector128Aggregate => 16, - ValueTypeShapeCharacteristics.Vector256Aggregate => 32, _ => throw new ArgumentOutOfRangeException() }; diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs index 162df18395aab..9337d7670904a 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs @@ -31,6 +31,7 @@ public enum TargetOS OSX, FreeBSD, NetBSD, + SunOS, WebAssembly, } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/TypeDesc.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/TypeDesc.cs index d9110d148e1d1..cf266f0c0990f 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/TypeDesc.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/TypeDesc.cs @@ -188,7 +188,7 @@ public bool IsValueType /// /// Gets a value indicating whether this is one of the primitive types (boolean, char, void, - /// a floating point, or an integer type). + /// a floating-point, or an integer type). /// public bool IsPrimitive { @@ -198,6 +198,34 @@ public bool IsPrimitive } } + /// + /// Gets a value indicating whether this is one of the primitive numeric types + /// (a floating-point or an integer type). + /// + public bool IsPrimitiveNumeric + { + get + { + switch (GetTypeFlags(TypeFlags.CategoryMask)) + { + case TypeFlags.SByte: + case TypeFlags.Byte: + case TypeFlags.Int16: + case TypeFlags.UInt16: + case TypeFlags.Int32: + case TypeFlags.UInt32: + case TypeFlags.Int64: + case TypeFlags.UInt64: + case TypeFlags.Single: + case TypeFlags.Double: + return true; + + default: + return false; + } + } + } + /// /// Gets a value indicating whether this is an enum type. /// Access to retrieve the underlying integral type. diff --git a/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaMethod.Sorting.cs b/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaMethod.Sorting.cs index b9cfbda285923..c5e20b5362b95 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaMethod.Sorting.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaMethod.Sorting.cs @@ -17,12 +17,14 @@ protected internal override int CompareToImpl(MethodDesc other, TypeSystemCompar EcmaModule module = _type.EcmaModule; EcmaModule otherModule = otherMethod._type.EcmaModule; - - int result = module.MetadataReader.GetToken(_handle) - otherModule.MetadataReader.GetToken(otherMethod._handle); + + // Sort by module in preference to by token. This will place methods of the same type near each other + // even when working with several modules + int result = module.CompareTo(otherModule); if (result != 0) return result; - return module.CompareTo(otherModule); + return module.MetadataReader.GetToken(_handle) - otherModule.MetadataReader.GetToken(otherMethod._handle); } } } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaType.Sorting.cs b/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaType.Sorting.cs index 246f36aa3f02a..77a3fbe46a762 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaType.Sorting.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaType.Sorting.cs @@ -13,12 +13,14 @@ partial class EcmaType protected internal override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer) { + // Sort by module in preference to by token. This will place types from the same module near each other + // even when working with several modules. var otherType = (EcmaType)other; - int result = _module.MetadataReader.GetToken(_handle) - otherType._module.MetadataReader.GetToken(otherType._handle); + int result = _module.CompareTo(otherType._module); if (result != 0) return result; - return _module.CompareTo(otherType._module); + return _module.MetadataReader.GetToken(_handle) - otherType._module.MetadataReader.GetToken(otherType._handle); } } } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index 8635957e67085..ac307a8b2c74f 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -158,6 +158,9 @@ public static partial class MarshalHelpers case MarshallerKind.AsAnyW: return context.GetWellKnownType(WellKnownType.IntPtr); + case MarshallerKind.ComInterface: + return context.GetWellKnownType(WellKnownType.IntPtr); + case MarshallerKind.Unknown: default: throw new NotSupportedException(); @@ -563,6 +566,10 @@ public static partial class MarshalHelpers else return MarshallerKind.Invalid; } + else if (type.IsInterface) + { + return MarshallerKind.ComInterface; + } else return MarshallerKind.Invalid; } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/Marshaller.cs b/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/Marshaller.cs index 50bbebb49f08b..50f9254171ea9 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/Marshaller.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Interop/IL/Marshaller.cs @@ -50,6 +50,7 @@ enum MarshallerKind LayoutClassPtr, AsAnyA, AsAnyW, + ComInterface, Invalid } public enum MarshalDirection @@ -909,7 +910,7 @@ protected override void EmitMarshalArgumentManagedToNative() protected override void EmitMarshalArgumentNativeToManaged() { - if (Out) + if (Out && !IsNativeByRef) { base.EmitMarshalArgumentNativeToManaged(); } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedMethod.Sorting.cs b/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedMethod.Sorting.cs index 17b270780ce79..065c122721360 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedMethod.Sorting.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedMethod.Sorting.cs @@ -12,21 +12,27 @@ partial class InstantiatedMethod protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) { var otherMethod = (InstantiatedMethod)other; - int result = _instantiation.Length - otherMethod._instantiation.Length; - if (result != 0) - return result; - - result = comparer.Compare(_methodDef, otherMethod._methodDef); - if (result != 0) - return result; - + // Sort by instantiation before sorting by associated method definition + // The goal of this is to keep methods which work with the same types near + // to each other. This is a better heuristic than sorting by method definition + // then by instantiation. + // + // The goal is to sort methods like SomeClass.SomeMethod, + // near SomeOtherClass.SomeOtherMethod + int result = 0; + // Sort instantiations of the same type together for (int i = 0; i < _instantiation.Length; i++) { + if (i >= otherMethod._instantiation.Length) + return 1; result = comparer.Compare(_instantiation[i], otherMethod._instantiation[i]); if (result != 0) - break; + return result; } + if (_instantiation.Length < otherMethod._instantiation.Length) + return -1; + result = comparer.Compare(_methodDef, otherMethod._methodDef); return result; } } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedType.Sorting.cs b/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedType.Sorting.cs index f749b4559406a..b983382f6268c 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedType.Sorting.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Sorting/InstantiatedType.Sorting.cs @@ -14,20 +14,28 @@ partial class InstantiatedType protected internal override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer) { var otherType = (InstantiatedType)other; + // Sort by instantiation before sorting by associated method definition + // The goal of this is to keep methods which work with the same types near + // to each other. This is a better heuristic than sorting by method definition + // then by instantiation. + // + // The goal is to sort classes like SomeClass, + // near SomeOtherClass - int result = comparer.Compare(_typeDef, otherType._typeDef); - if (result == 0) + int result = 0; + // Sort instantiations of the same type together + for (int i = 0; i < _instantiation.Length; i++) { - Debug.Assert(_instantiation.Length == otherType._instantiation.Length); - for (int i = 0; i < _instantiation.Length; i++) - { - result = comparer.Compare(_instantiation[i], otherType._instantiation[i]); - if (result != 0) - break; - } + if (i >= otherType._instantiation.Length) + return 1; + result = comparer.Compare(_instantiation[i], otherType._instantiation[i]); + if (result != 0) + return result; } + if (_instantiation.Length < otherType._instantiation.Length) + return -1; - return result; + return comparer.Compare(_typeDef, otherType._typeDef); } } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index c38cc8b6fa989..8238d9418f9ce 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -150,8 +150,6 @@ public void EmitPortableExecutable() if (node is NativeDebugDirectoryEntryNode nddeNode) { // There should be only one NativeDebugDirectoryEntry. - // This assert will need to be revisited when we implement the composite R2R format, where we'll need to figure - // out how native symbols will be emitted, and verify that the DiaSymReader library is able to consume them. Debug.Assert(nativeDebugDirectoryEntryNode == null); nativeDebugDirectoryEntryNode = nddeNode; } @@ -176,11 +174,8 @@ public void EmitPortableExecutable() EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section, _mapFileBuilder); } - if (!_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode || _componentModule != null) - { - r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); - r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size); - } + r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); + r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size); if (_nodeFactory.Win32ResourcesNode != null) { diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs index 5e7a96afa4c71..87772fa7079f7 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs @@ -51,7 +51,10 @@ private static DirectoryEntry ReadDirectoryEntry(ref BlobReader reader) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix); - sb.Append($"__CorHeader_{_module.Assembly.GetName().Name}"); + if (_module != null) + sb.Append($"__CorHeader_{_module.Assembly.GetName().Name}"); + else + sb.Append("__CompositeCorHeader_"); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); @@ -62,75 +65,116 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); - BlobReader reader = _module.PEReader.GetEntireImage().GetReader(); - reader.Offset = _module.PEReader.PEHeaders.CorHeaderStartOffset; - - // Header Size - int headerSize = reader.ReadInt32(); - builder.EmitInt(headerSize); - - // Runtime major, minor version - builder.EmitUShort(reader.ReadUInt16()); - builder.EmitUShort(reader.ReadUInt16()); + if (_module != null) + { + BlobReader reader = _module.PEReader.GetEntireImage().GetReader(); + reader.Offset = _module.PEReader.PEHeaders.CorHeaderStartOffset; + + // Header Size + int headerSize = reader.ReadInt32(); + builder.EmitInt(headerSize); + + // Runtime major, minor version + builder.EmitUShort(reader.ReadUInt16()); + builder.EmitUShort(reader.ReadUInt16()); + + // Metadata Directory + ReadDirectoryEntry(ref reader); + var metadataBlob = factory.CopiedMetadataBlob(_module); + builder.EmitReloc(metadataBlob, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitInt(metadataBlob.Size); + + // Flags + builder.EmitUInt((uint)(((CorFlags)reader.ReadUInt32() & ~CorFlags.ILOnly) | CorFlags.ILLibrary)); + + // Entrypoint + builder.EmitInt(reader.ReadInt32()); + + // Resources Directory + if (ReadDirectoryEntry(ref reader).Size > 0) + { + var managedResources = factory.CopiedManagedResources(_module); + builder.EmitReloc(managedResources, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitInt(managedResources.Size); + } + else + { + WriteEmptyDirectoryEntry(ref builder); + } + + // Strong Name Signature Directory + if (ReadDirectoryEntry(ref reader).Size > 0) + { + var strongNameSignature = factory.CopiedStrongNameSignature(_module); + builder.EmitReloc(strongNameSignature, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitInt(strongNameSignature.Size); + } + else + { + WriteEmptyDirectoryEntry(ref builder); + } + + // Code Manager Table Directory + ReadDirectoryEntry(ref reader); + WriteEmptyDirectoryEntry(ref builder); - // Metadata Directory - ReadDirectoryEntry(ref reader); - var metadataBlob = factory.CopiedMetadataBlob(_module); - builder.EmitReloc(metadataBlob, RelocType.IMAGE_REL_BASED_ADDR32NB); - builder.EmitInt(metadataBlob.Size); + // VTable Fixups Directory + ReadDirectoryEntry(ref reader); + WriteEmptyDirectoryEntry(ref builder); - // Flags - builder.EmitUInt((uint)(((CorFlags)reader.ReadUInt32() & ~CorFlags.ILOnly) | CorFlags.ILLibrary)); + // Export Address Table Jumps Directory + ReadDirectoryEntry(ref reader); + WriteEmptyDirectoryEntry(ref builder); - // Entrypoint - builder.EmitInt(reader.ReadInt32()); + // Managed Native (ReadyToRun) Header Directory + ReadDirectoryEntry(ref reader); + builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_SYMBOL_SIZE); - // Resources Directory - if (ReadDirectoryEntry(ref reader).Size > 0) - { - var managedResources = factory.CopiedManagedResources(_module); - builder.EmitReloc(managedResources, RelocType.IMAGE_REL_BASED_ADDR32NB); - builder.EmitInt(managedResources.Size); + // Did we fully read the header? + Debug.Assert(reader.Offset - headerSize == _module.PEReader.PEHeaders.CorHeaderStartOffset); + Debug.Assert(builder.CountBytes == headerSize); + Debug.Assert(headerSize == Size); } else { - WriteEmptyDirectoryEntry(ref builder); - } + // Generating CORHeader for composite image + // Header Size + builder.EmitInt(Size); - // Strong Name Signature Directory - if (ReadDirectoryEntry(ref reader).Size > 0) - { - var strongNameSignature = factory.CopiedStrongNameSignature(_module); - builder.EmitReloc(strongNameSignature, RelocType.IMAGE_REL_BASED_ADDR32NB); - builder.EmitInt(strongNameSignature.Size); - } - else - { + // Runtime major, minor version + builder.EmitUShort(0); + builder.EmitUShort(0); + + // Metadata Directory + builder.EmitReloc(factory.ManifestMetadataTable, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitReloc(factory.ManifestMetadataTable, RelocType.IMAGE_REL_SYMBOL_SIZE); + + // Flags + builder.EmitUInt(0); + + // Entrypoint + builder.EmitInt(0); + + // Resources Directory WriteEmptyDirectoryEntry(ref builder); - } - - // Code Manager Table Directory - ReadDirectoryEntry(ref reader); - WriteEmptyDirectoryEntry(ref builder); + // Strong Name Signature Directory + WriteEmptyDirectoryEntry(ref builder); - // VTable Fixups Directory - ReadDirectoryEntry(ref reader); - WriteEmptyDirectoryEntry(ref builder); + // Code Manager Table Directory + WriteEmptyDirectoryEntry(ref builder); - // Export Address Table Jumps Directory - ReadDirectoryEntry(ref reader); - WriteEmptyDirectoryEntry(ref builder); + // VTable Fixups Directory + WriteEmptyDirectoryEntry(ref builder); - // Managed Native (ReadyToRun) Header Directory - ReadDirectoryEntry(ref reader); - builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_BASED_ADDR32NB); - builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_SYMBOL_SIZE); + // Export Address Table Jumps Directory + WriteEmptyDirectoryEntry(ref builder); - // Did we fully read the header? - Debug.Assert(reader.Offset - headerSize == _module.PEReader.PEHeaders.CorHeaderStartOffset); - Debug.Assert(builder.CountBytes == headerSize); - Debug.Assert(headerSize == Size); + // Managed Native (ReadyToRun) Header Directory + builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_SYMBOL_SIZE); + } return builder.ToObjectData(); } @@ -143,6 +187,17 @@ private void WriteEmptyDirectoryEntry(ref ObjectDataBuilder builder) public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { + if (_module == null) + { + if (((CopiedCorHeaderNode)other)._module == null) + return 0; + return -1; + } + else if (((CopiedCorHeaderNode)other)._module == null) + { + return 1; + } + return _module.CompareTo(((CopiedCorHeaderNode)other)._module); } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs index e88b2805d7369..6a691d831c199 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs @@ -56,14 +56,18 @@ public class NativeDebugDirectoryEntryNode : DebugDirectoryEntryNode public unsafe int Size => RSDSSize; - public NativeDebugDirectoryEntryNode(EcmaModule sourceModule) - : base(sourceModule) - { } + public NativeDebugDirectoryEntryNode(string pdbName) + : base(null) + { + _pdbName = pdbName; + } + + private string _pdbName; public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix); - sb.Append($"__NativeRvaBlob_{_module.Assembly.GetName().Name}"); + sb.Append($"__NativeDebugDirectory_{_pdbName.Replace('.','_')}"); } public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) @@ -99,7 +103,7 @@ public byte[] GenerateRSDSEntryData(byte[] md5Hash) // Age writer.Write(1); - string pdbFileName = _module.Assembly.GetName().Name + ".ni.pdb"; + string pdbFileName = _pdbName; byte[] pdbFileNameBytes = Encoding.UTF8.GetBytes(pdbFileName); writer.Write(pdbFileNameBytes); @@ -107,6 +111,11 @@ public byte[] GenerateRSDSEntryData(byte[] md5Hash) return rsdsEntry.ToArray(); } } + + public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) + { + return _pdbName.CompareTo(((NativeDebugDirectoryEntryNode)other)._pdbName); + } } public class CopiedDebugDirectoryEntryNode : DebugDirectoryEntryNode diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs index 52e49afe79828..5c1bd729b64cc 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Immutable; using System.Diagnostics; +using System.IO; using System.Reflection.PortableExecutable; using Internal.Text; using Internal.TypeSystem.Ecma; @@ -25,10 +26,17 @@ public class DebugDirectoryNode : ObjectNode, ISymbolDefinitionNode sizeof(int); // PointerToRawData private EcmaModule _module; + private NativeDebugDirectoryEntryNode _nativeEntry; - public DebugDirectoryNode(EcmaModule sourceModule) + public DebugDirectoryNode(EcmaModule sourceModule, string outputFileName) { _module = sourceModule; + string pdbNameRoot = Path.GetFileNameWithoutExtension(outputFileName); + if (sourceModule != null) + { + pdbNameRoot = sourceModule.Assembly.GetName().Name; + } + _nativeEntry = new NativeDebugDirectoryEntryNode(pdbNameRoot + ".ni.pdb"); } public override ObjectNodeSection Section => ObjectNodeSection.TextSection; @@ -48,13 +56,22 @@ public DebugDirectoryNode(EcmaModule sourceModule) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix); - sb.Append($"__DebugDirectory_{_module.Assembly.GetName().Name}"); + string directoryName; + if (_module != null) + directoryName = _module.Assembly.GetName().Name; + else + directoryName = "Composite"; + + sb.Append($"__DebugDirectory_{directoryName}"); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); int GetNumDebugDirectoryEntriesInModule() { + if (_module == null) + return 0; + ImmutableArray entries = _module.PEReader.ReadDebugDirectory(); return entries == null ? 0 : entries.Length; } @@ -65,12 +82,15 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); - ImmutableArray entries = _module.PEReader.ReadDebugDirectory(); + ImmutableArray entries = default(ImmutableArray); + if (_module != null) + entries = _module.PEReader.ReadDebugDirectory(); + int numEntries = GetNumDebugDirectoryEntriesInModule(); // First, write the native debug directory entry { - var entry = (NativeDebugDirectoryEntryNode)factory.DebugDirectoryEntry(_module, -1); + var entry = _nativeEntry; builder.EmitUInt(0 /* Characteristics */); if (numEntries > 0) @@ -121,6 +141,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { + if (_module == null) + { + if (((DebugDirectoryNode)other)._module == null) + return 0; + return -1; + } + else if (((DebugDirectoryNode)other)._module == null) + { + return 1; + } + return _module.CompareTo(((DebugDirectoryNode)other)._module); } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs index 31fd6ba9570e1..31540b3d302ae 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.IO; using Internal.JitInterface; @@ -81,6 +82,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) VertexArray vertexArray = new VertexArray(section); section.Place(vertexArray); + Dictionary blobCache = new Dictionary(ByteArrayComparer.Instance); + foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods()) { MemoryStream methodDebugBlob = new MemoryStream(); @@ -105,8 +108,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) methodDebugBlob.Write(vars, 0, vars.Length); } - BlobVertex debugBlob = new BlobVertex(methodDebugBlob.ToArray()); - + byte[] debugBlobArrayKey = methodDebugBlob.ToArray(); + if (!blobCache.TryGetValue(debugBlobArrayKey, out BlobVertex debugBlob)) + { + debugBlob = new BlobVertex(methodDebugBlob.ToArray()); + blobCache.Add(debugBlobArrayKey, debugBlob); + } vertexArray.Set(factory.RuntimeFunctionsTable.GetIndex(method), new DebugInfoVertex(debugBlob)); } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs index df834649fdc5f..d8f6c8f8d2c30 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs @@ -27,8 +27,8 @@ public class DelayLoadHelperImport : Import ReadyToRunHelper helper, Signature instanceSignature, bool useVirtualCall = false, - string callSite = null) - : base(importSectionNode, instanceSignature, callSite) + MethodDesc callingMethod = null) + : base(importSectionNode, instanceSignature, callingMethod) { _helper = helper; _useVirtualCall = useVirtualCall; @@ -45,10 +45,10 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde sb.Append(_helper.ToString()); sb.Append(") -> "); ImportSignature.AppendMangledName(nameMangler, sb); - if (CallSite != null) + if (CallingMethod != null) { sb.Append(" @ "); - sb.Append(CallSite); + sb.Append(nameMangler.GetMangledMethodName(CallingMethod)); } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs index 4002bfdbab0d7..656a68f40c841 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs @@ -30,8 +30,8 @@ public class DelayLoadHelperMethodImport : DelayLoadHelperImport, IMethodNode bool useVirtualCall, bool useInstantiatingStub, Signature instanceSignature, - string callSite = null) - : base(factory, importSectionNode, helper, instanceSignature, useVirtualCall, callSite) + MethodDesc callingMethod = null) + : base(factory, importSectionNode, helper, instanceSignature, useVirtualCall, callingMethod) { _method = method; _useInstantiatingStub = useInstantiatingStub; diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs index e276c75fa7718..ebd73a82552bd 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -17,12 +18,12 @@ public class Import : EmbeddedObjectNode, ISymbolDefinitionNode, ISortableSymbol internal readonly SignatureEmbeddedPointerIndirectionNode ImportSignature; - internal readonly string CallSite; + internal readonly MethodDesc CallingMethod; - public Import(ImportSectionNode tableNode, Signature importSignature, string callSite = null) + public Import(ImportSectionNode tableNode, Signature importSignature, MethodDesc callingMethod = null) { Table = tableNode; - CallSite = callSite; + CallingMethod = callingMethod; ImportSignature = new SignatureEmbeddedPointerIndirectionNode(this, importSignature); } @@ -66,7 +67,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { Import otherNode = (Import)other; - int result = string.Compare(CallSite, otherNode.CallSite); + int result = comparer.Compare(CallingMethod, otherNode.CallingMethod); if (result != 0) return result; diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs index eec93744449fb..c07b78b10e2fe 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs @@ -38,10 +38,10 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde { sb.Append("SignaturePointer_"); Target.AppendMangledName(nameMangler, sb); - if (_import.CallSite != null) + if (_import.CallingMethod != null) { sb.Append(" @ "); - sb.Append(_import.CallSite); + sb.Append(nameMangler.GetMangledMethodName(_import.CallingMethod)); } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs index 5113b41158e4c..9a9184e085d19 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs @@ -88,7 +88,6 @@ private static void EncodeTypeLayout(ObjectDataSignatureBuilder dataBuilder, Typ ValueTypeShapeCharacteristics.Vector64Aggregate => CorElementType.ELEMENT_TYPE_R8, // See MethodTable::GetHFAType ValueTypeShapeCharacteristics.Vector128Aggregate => CorElementType.ELEMENT_TYPE_VALUETYPE, - ValueTypeShapeCharacteristics.Vector256Aggregate => CorElementType.ELEMENT_TYPE_VALUETYPE, _ => CorElementType.Invalid }; dataBuilder.EmitUInt((uint)elementType); diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index e4b76f79f6278..eeb590bce993b 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -67,19 +67,20 @@ public void SetMarkingComplete() _markingComplete = true; } - public IMethodNode CompiledMethodNode(MethodDesc method) - { - EcmaModule module = ((EcmaMethod)method.GetTypicalMethodDefinition()).Module; - ModuleToken moduleToken = Resolver.GetModuleTokenForMethod(method, throwIfNotFound: true); + private NodeCache _localMethodCache; - return CreateMethodEntrypointNodeHelper(new MethodWithToken(method, moduleToken, constrainedType: null)); + public MethodWithGCInfo CompiledMethodNode(MethodDesc method) + { + Debug.Assert(CompilationModuleGroup.ContainsMethodBody(method, false)); + Debug.Assert(method == method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + return _localMethodCache.GetOrAdd(method); } private NodeCache _allMethodsOnType; public AllMethodsOnTypeNode AllMethodsOnType(TypeDesc type) { - return _allMethodsOnType.GetOrAdd(type); + return _allMethodsOnType.GetOrAdd(type.ConvertToCanonForm(CanonicalFormKind.Specific)); } private NodeCache _genericReadyToRunHelpersFromDict; @@ -96,13 +97,6 @@ public ISymbolNode ReadyToRunHelperFromTypeLookup(ReadyToRunHelperId id, Object return _genericReadyToRunHelpersFromType.GetOrAdd(new ReadyToRunGenericHelperKey(id, target, dictionaryOwner)); } - private NodeCache _readOnlyDataBlobs; - - public SettableReadOnlyDataBlob SettableReadOnlyDataBlob(Utf8String name) - { - return _readOnlyDataBlobs.GetOrAdd(name); - } - private struct ReadyToRunGenericHelperKey : IEquatable { public readonly object Target; @@ -139,11 +133,13 @@ public ModuleAndIntValueKey(int integer, EcmaModule module) Module = module; } - public bool Equals(ModuleAndIntValueKey other) => IntValue == other.IntValue && Module.Equals(other.Module); + public bool Equals(ModuleAndIntValueKey other) => IntValue == other.IntValue && ((Module == null && other.Module == null) || Module.Equals(other.Module)); public override bool Equals(object obj) => obj is ModuleAndIntValueKey && Equals((ModuleAndIntValueKey)obj); public override int GetHashCode() { int hashCode = IntValue * 0x5498341 + 0x832424; + if (Module == null) + return hashCode; return hashCode * 23 + Module.GetHashCode(); } } @@ -211,11 +207,6 @@ private void CreateNodeCaches() (TypeDesc)helperKey.Target)); }); - _readOnlyDataBlobs = new NodeCache(key => - { - return new SettableReadOnlyDataBlob(key, ObjectNodeSection.ReadOnlyDataSection); - }); - _constructedHelpers = new NodeCache(helperId => { return new Import(EagerImports, new ReadyToRunHelperSignature(helperId)); @@ -266,9 +257,6 @@ private void CreateNodeCaches() _debugDirectoryEntries = new NodeCache(key => { - if (key.IntValue < 0) - return new NativeDebugDirectoryEntryNode(key.Module); - else return new CopiedDebugDirectoryEntryNode(key.Module, key.IntValue); }); @@ -362,7 +350,8 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key) bool isUnboxingStub = key.IsUnboxingStub; bool isInstantiatingStub = key.IsInstantiatingStub; bool isPrecodeImportRequired = key.IsPrecodeImportRequired; - if (CompilationModuleGroup.ContainsMethodBody(method.Method, false)) + MethodDesc compilableMethod = method.Method.GetCanonMethodTarget(CanonicalFormKind.Specific); + if (CompilationModuleGroup.ContainsMethodBody(compilableMethod, false)) { if (isPrecodeImportRequired) { @@ -370,7 +359,7 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key) this, ReadyToRunFixupKind.MethodEntry, method, - CreateMethodEntrypointNodeHelper(method), + CompiledMethodNode(compilableMethod), isUnboxingStub, isInstantiatingStub); } @@ -380,7 +369,7 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key) this, ReadyToRunFixupKind.MethodEntry, method, - CreateMethodEntrypointNodeHelper(method), + CompiledMethodNode(compilableMethod), isUnboxingStub, isInstantiatingStub); } @@ -403,15 +392,6 @@ public IMethodNode MethodEntrypoint(MethodWithToken method, bool isUnboxingStub, return _importMethods.GetOrAdd(key); } - private NodeCache _localMethodCache; - - private MethodWithGCInfo CreateMethodEntrypointNodeHelper(MethodWithToken targetMethod) - { - Debug.Assert(CompilationModuleGroup.ContainsMethodBody(targetMethod.Method, false)); - - return _localMethodCache.GetOrAdd(targetMethod.Method); - } - public IEnumerable EnumerateCompiledMethods() { return EnumerateCompiledMethods(null, CompiledMethodCategory.All); @@ -676,10 +656,7 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph) graph.AddRoot(PrecodeImports, "Precode helper imports are always generated"); graph.AddRoot(StringImports, "String imports are always generated"); graph.AddRoot(Header, "ReadyToRunHeader is always generated"); - if (!CompilationModuleGroup.IsCompositeBuildMode) - { - graph.AddRoot(CopiedCorHeaderNode, "MSIL COR header is always generated for single-file R2R files"); - } + graph.AddRoot(CopiedCorHeaderNode, "MSIL COR header is always generated for R2R files"); graph.AddRoot(DebugDirectoryNode, "Debug Directory will always contain at least one entry"); if (Win32ResourcesNode != null) diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs index da85b63332288..aeca8c8da3b24 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs @@ -107,7 +107,7 @@ private void CreateNodeCaches() _codegenNodeFactory.MethodSignature(ReadyToRunFixupKind.VirtualEntry, cellKey.Method, cellKey.IsUnboxingStub, isInstantiatingStub: false), - cellKey.CallSite); + cellKey.CallingMethod); }); _delegateCtors = new NodeCache(ctorKey => @@ -423,9 +423,9 @@ public ISymbolNode FieldBaseOffset(TypeDesc typeDesc) private NodeCache _interfaceDispatchCells = new NodeCache(); - public ISymbolNode InterfaceDispatchCell(MethodWithToken method, bool isUnboxingStub, string callSite) + public ISymbolNode InterfaceDispatchCell(MethodWithToken method, bool isUnboxingStub, MethodDesc callingMethod) { - MethodAndCallSite cellKey = new MethodAndCallSite(method, isUnboxingStub, callSite); + MethodAndCallSite cellKey = new MethodAndCallSite(method, isUnboxingStub, callingMethod); return _interfaceDispatchCells.GetOrAdd(cellKey); } @@ -453,18 +453,18 @@ struct MethodAndCallSite : IEquatable { public readonly MethodWithToken Method; public readonly bool IsUnboxingStub; - public readonly string CallSite; + public readonly MethodDesc CallingMethod; - public MethodAndCallSite(MethodWithToken method, bool isUnboxingStub, string callSite) + public MethodAndCallSite(MethodWithToken method, bool isUnboxingStub, MethodDesc callingMethod) { - CallSite = callSite; IsUnboxingStub = isUnboxingStub; Method = method; + CallingMethod = callingMethod; } public bool Equals(MethodAndCallSite other) { - return CallSite == other.CallSite && Method.Equals(other.Method) && IsUnboxingStub == other.IsUnboxingStub; + return Method.Equals(other.Method) && IsUnboxingStub == other.IsUnboxingStub && CallingMethod == other.CallingMethod; } public override bool Equals(object obj) @@ -474,7 +474,7 @@ public override bool Equals(object obj) public override int GetHashCode() { - return (CallSite != null ? CallSite.GetHashCode() : 0) + return (CallingMethod != null ? unchecked(199 * CallingMethod.GetHashCode()) : 0) ^ unchecked(31 * Method.GetHashCode()) ^ (IsUnboxingStub ? -0x80000000 : 0); } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 3b3f323ff3a5f..bd08ba25809db 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -302,7 +302,7 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow EcmaModule inputModule = NodeFactory.TypeSystemContext.GetModuleFromPath(inputFile); CopiedCorHeaderNode copiedCorHeader = new CopiedCorHeaderNode(inputModule); - DebugDirectoryNode debugDirectory = new DebugDirectoryNode(inputModule); + DebugDirectoryNode debugDirectory = new DebugDirectoryNode(inputModule, outputFile); NodeFactory componentFactory = new NodeFactory( _nodeFactory.TypeSystemContext, _nodeFactory.CompilationModuleGroup, diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index a889d469051b0..a5e388083be3b 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -28,6 +28,7 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private InstructionSetSupport _instructionSetSupport; private string _jitPath; + private string _outputFile; // These need to provide reasonable defaults so that the user can optionally skip // calling the Use/Configure methods and still get something reasonable back. @@ -115,13 +116,20 @@ public ReadyToRunCodegenCompilationBuilder UseInstructionSetSupport(InstructionS return this; } + public ReadyToRunCodegenCompilationBuilder GenerateOutputFile(string outputFile) + { + _outputFile = outputFile; + return this; + } + public override ICompilation ToCompilation() { // TODO: only copy COR headers for single-assembly build and for composite build with embedded MSIL IEnumerable inputModules = _compilationGroup.CompilationModuleSet; - CopiedCorHeaderNode corHeaderNode = (_compilationGroup.IsCompositeBuildMode ? null : new CopiedCorHeaderNode(inputModules.First())); + EcmaModule singleModule = _compilationGroup.IsCompositeBuildMode ? null : inputModules.First(); + CopiedCorHeaderNode corHeaderNode = new CopiedCorHeaderNode(singleModule); // TODO: proper support for multiple input files - DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(inputModules.First()); + DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(singleModule, _outputFile); // Produce a ResourceData where the IBC PROFILE_DATA entry has been filtered out // TODO: proper support for multiple input files diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 6c0babecc023e..5183fbfc0f6c9 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -1,4 +1,4 @@ - + Library ILCompiler.ReadyToRun @@ -62,7 +62,7 @@ - + diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index a0691e4061bb5..883303110582a 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -626,6 +626,8 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL: case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL: case CorInfoHelpFunc.CORINFO_HELP_GETREFANY: + // For Vector256.Create and similar cases + case CorInfoHelpFunc.CORINFO_HELP_THROW_NOT_IMPLEMENTED: throw new RequiresRuntimeJitException(ftnNum.ToString()); default: @@ -1549,7 +1551,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO _compilation.SymbolNodeFactory.InterfaceDispatchCell( new MethodWithToken(targetMethod, HandleToModuleToken(ref pResolvedToken, targetMethod), constrainedType: null), isUnboxingStub: false, - _compilation.NameMangler.GetMangledMethodName(MethodBeingCompiled).ToString())); + MethodBeingCompiled)); } break; diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs index d4ba4683609c2..0b943d6233991 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs @@ -20,6 +20,7 @@ public enum MachineOSOverride : ushort Apple = 0x4644, FreeBSD = 0xADC4, NetBSD = 0x1993, + SunOS = 0x1992, } /// diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj index b3f0bd30acc1b..f07c29c417b97 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs index c59f99cbd1b3c..ee4290a80ef53 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs @@ -207,11 +207,6 @@ public class ReadyToRunMethod /// public MetadataReader MetadataReader { get; private set; } - /// - /// An unique index for the method - /// - public int Index { get; set; } - /// /// The name of the method /// @@ -288,7 +283,6 @@ public IReadOnlyList Fixups /// public ReadyToRunMethod( ReadyToRunReader readyToRunReader, - int index, MetadataReader metadataReader, EntityHandle methodHandle, int entryPointId, @@ -299,7 +293,6 @@ public IReadOnlyList Fixups { _readyToRunReader = readyToRunReader; _fixupOffset = fixupOffset; - Index = index; MethodHandle = methodHandle; EntryPointRuntimeFunctionId = entryPointId; diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs index 651c0cc36ac59..2da57b2b7b538 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs @@ -31,6 +31,7 @@ public enum OperatingSystem FreeBSD = 0xADC4, Linux = 0x7B79, NetBSD = 0x1993, + SunOS = 0x1992, Windows = 0, Unknown = -1 } @@ -97,6 +98,7 @@ public sealed class ReadyToRunReader // ImportSections private List _importSections; private Dictionary _importCellNames; + private Dictionary _importSignatures; // AvailableType private Dictionary> _availableTypes; @@ -308,6 +310,19 @@ public IReadOnlyList ImportSections } + /// + /// Map from import cell addresses to their symbolic names. + /// + public IReadOnlyDictionary ImportSignatures + { + get + { + EnsureImportSections(); + return _importSignatures; + } + + } + internal Dictionary RuntimeFunctionToDebugInfo { get @@ -396,14 +411,20 @@ private unsafe void Initialize(MetadataReader metadata) { if ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) == 0) { - throw new BadImageFormatException("The file is not a ReadyToRun image"); + if (!TryLocateNativeReadyToRunHeader()) + throw new BadImageFormatException("The file is not a ReadyToRun image"); + + Debug.Assert(Composite); } + else + { + _assemblyCache.Add(metadata); - _assemblyCache.Add(metadata); + DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory; + _readyToRunHeaderRVA = r2rHeaderDirectory.RelativeVirtualAddress; + Debug.Assert(!Composite); + } - DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory; - _readyToRunHeaderRVA = r2rHeaderDirectory.RelativeVirtualAddress; - Debug.Assert(!Composite); } else if (!TryLocateNativeReadyToRunHeader()) { @@ -687,7 +708,7 @@ private void ParseMethodDefEntrypointsSection(ReadyToRunSection section, Metadat int runtimeFunctionId; int? fixupOffset; GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset); - ReadyToRunMethod method = new ReadyToRunMethod(this, _methods.Count, metadataReader, methodHandle, runtimeFunctionId, owningType: null, constrainedType: null, instanceArgs: null, fixupOffset: fixupOffset); + ReadyToRunMethod method = new ReadyToRunMethod(this, metadataReader, methodHandle, runtimeFunctionId, owningType: null, constrainedType: null, instanceArgs: null, fixupOffset: fixupOffset); if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= isEntryPoint.Length) { @@ -772,7 +793,6 @@ private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint) GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixupOffset); ReadyToRunMethod method = new ReadyToRunMethod( this, - _methods.Count, mdReader, methodHandle, runtimeFunctionId, @@ -945,6 +965,7 @@ private void EnsureImportSections() } _importSections = new List(); _importCellNames = new Dictionary(); + _importSignatures = new Dictionary(); if (!ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.ImportSections, out ReadyToRunSection importSectionsSection)) { return; @@ -997,9 +1018,11 @@ private void EnsureImportSections() long section = NativeReader.ReadInt64(Image, ref sectionOffset); uint sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset); int sigOffset = GetOffset((int)sigRva); - string cellName = MetadataNameFormatter.FormatSignature(_assemblyResolver, this, sigOffset); + ReadyToRunSignature signature; + string cellName = MetadataNameFormatter.FormatSignature(_assemblyResolver, this, sigOffset, out signature); entries.Add(new ReadyToRunImportSection.ImportSectionEntry(entries.Count, entryOffset, entryOffset + rva, section, sigRva, cellName)); _importCellNames.Add(rva + entrySize * i, cellName); + _importSignatures.Add(rva + entrySize * i, signature); } int auxDataRVA = NativeReader.ReadInt32(Image, ref offset); diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs index 355af566a46b8..3804ef60d4326 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs @@ -12,6 +12,30 @@ namespace ILCompiler.Reflection.ReadyToRun { + /// + /// This represents all possible signatures that is + /// + public class ReadyToRunSignature + { + } + + /// + /// For now, this means the signature is not parsed yet + /// + public class TodoSignature : ReadyToRunSignature + { + } + + public class MethodDefEntrySignature : ReadyToRunSignature + { + public uint MethodDefToken { get; set; } + } + + public class MethodRefEntrySignature : ReadyToRunSignature + { + public uint MethodRefToken { get; set; } + } + /// /// Helper class for converting metadata tokens into their textual representation. /// @@ -39,11 +63,11 @@ public static string FormatHandle(MetadataReader metadataReader, Handle handle, return formatter.EmitHandleName(handle, namespaceQualified, owningTypeOverride, signaturePrefix); } - public static string FormatSignature(IAssemblyResolver assemblyResolver, ReadyToRunReader r2rReader, int imageOffset) + public static string FormatSignature(IAssemblyResolver assemblyResolver, ReadyToRunReader r2rReader, int imageOffset, out ReadyToRunSignature result) { SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, r2rReader.GetGlobalMetadataReader(), r2rReader, imageOffset); - string result = decoder.ReadR2RSignature(); - return result; + string answer = decoder.ReadR2RSignature(out result); + return answer; } /// @@ -518,13 +542,14 @@ public CorElementType PeekElementType() /// by custom encoding per fixup type. /// /// - public string ReadR2RSignature() + public string ReadR2RSignature(out ReadyToRunSignature result) { + result = null; StringBuilder builder = new StringBuilder(); int startOffset = _offset; try { - ParseSignature(builder); + result = ParseSignature(builder); EmitSignatureBinaryFrom(builder, startOffset); } catch (Exception ex) @@ -634,7 +659,7 @@ private void EmitSignatureBinaryFrom(StringBuilder builder, int startOffset) /// Parse the signature into a given output string builder. /// /// Output signature builder - private void ParseSignature(StringBuilder builder) + private ReadyToRunSignature ParseSignature(StringBuilder builder) { uint fixupType = ReadByte(); EmitInlineSignatureBinaryBytes(builder, 1); @@ -650,8 +675,9 @@ private void ParseSignature(StringBuilder builder) moduleDecoder = new SignatureDecoder(_options, refAsmEcmaReader, _image, _offset, refAsmEcmaReader, _contextReader); } - moduleDecoder.ParseSignature((ReadyToRunFixupKind)fixupType, builder); + ReadyToRunSignature result = moduleDecoder.ParseSignature((ReadyToRunFixupKind)fixupType, builder); _offset = moduleDecoder.Offset; + return result; } /// @@ -659,14 +685,16 @@ private void ParseSignature(StringBuilder builder) /// /// Fixup type to parse /// Output signature builder - private void ParseSignature(ReadyToRunFixupKind fixupType, StringBuilder builder) + private ReadyToRunSignature ParseSignature(ReadyToRunFixupKind fixupType, StringBuilder builder) { + ReadyToRunSignature result = new TodoSignature(); switch (fixupType) { case ReadyToRunFixupKind.ThisObjDictionaryLookup: builder.Append("THISOBJ_DICTIONARY_LOOKUP @ "); ParseType(builder); builder.Append(": "); + // It looks like ReadyToRunSignature is potentially a composite pattern ParseSignature(builder); break; @@ -702,15 +730,17 @@ private void ParseSignature(ReadyToRunFixupKind fixupType, StringBuilder builder break; case ReadyToRunFixupKind.MethodEntry_DefToken: - ParseMethodDefToken(builder, owningTypeOverride: null); + uint methodDefToken = ParseMethodDefToken(builder, owningTypeOverride: null); builder.Append(" (METHOD_ENTRY"); builder.Append(_options.Naked ? ")" : "_DEF_TOKEN)"); + result = new MethodDefEntrySignature { MethodDefToken = methodDefToken }; break; case ReadyToRunFixupKind.MethodEntry_RefToken: - ParseMethodRefToken(builder, owningTypeOverride: null); + uint methodRefToken = ParseMethodRefToken(builder, owningTypeOverride: null); builder.Append(" (METHOD_ENTRY"); builder.Append(_options.Naked ? ")" : "_REF_TOKEN)"); + result = new MethodRefEntrySignature { MethodRefToken = methodRefToken }; break; @@ -909,6 +939,7 @@ private void ParseSignature(ReadyToRunFixupKind fixupType, StringBuilder builder builder.Append(string.Format("Unknown fixup type: {0:X2}", fixupType)); break; } + return result; } /// @@ -1235,7 +1266,7 @@ private void ParseMethod(StringBuilder builder) /// Read a methodDef token from the signature and output the corresponding object to the builder. /// /// Output string builder - private void ParseMethodDefToken(StringBuilder builder, string owningTypeOverride) + private uint ParseMethodDefToken(StringBuilder builder, string owningTypeOverride) { StringBuilder signaturePrefixBuilder = new StringBuilder(); uint methodDefToken = ReadUIntAndEmitInlineSignatureBinary(signaturePrefixBuilder) | (uint)CorTokenType.mdtMethodDef; @@ -1245,6 +1276,7 @@ private void ParseMethodDefToken(StringBuilder builder, string owningTypeOverrid namespaceQualified: true, owningTypeOverride: owningTypeOverride, signaturePrefix: signaturePrefixBuilder.ToString())); + return methodDefToken; } /// @@ -1252,7 +1284,7 @@ private void ParseMethodDefToken(StringBuilder builder, string owningTypeOverrid /// /// Output string builder /// Explicit owning type override - private void ParseMethodRefToken(StringBuilder builder, string owningTypeOverride) + private uint ParseMethodRefToken(StringBuilder builder, string owningTypeOverride) { StringBuilder signaturePrefixBuilder = new StringBuilder(); uint methodRefToken = ReadUIntAndEmitInlineSignatureBinary(signaturePrefixBuilder) | (uint)CorTokenType.mdtMemberRef; @@ -1262,6 +1294,7 @@ private void ParseMethodRefToken(StringBuilder builder, string owningTypeOverrid namespaceQualified: false, owningTypeOverride: owningTypeOverride, signaturePrefix: signaturePrefixBuilder.ToString())); + return methodRefToken; } /// @@ -1690,12 +1723,11 @@ private void ParseHelper(StringBuilder builder) /// /// Read a string token from the signature stream and convert it to the actual string. /// - /// private void ParseStringHandle(StringBuilder builder) { uint rid = ReadUIntAndEmitInlineSignatureBinary(builder); UserStringHandle stringHandle = MetadataTokens.UserStringHandle((int)rid); - builder.Append(_metadataReader.GetUserString(stringHandle)); + builder.AppendEscapedString(_metadataReader.GetUserString(stringHandle)); } } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/StringExtensions.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/StringExtensions.cs new file mode 100644 index 0000000000000..9cf7ca6655e7d --- /dev/null +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/StringExtensions.cs @@ -0,0 +1,112 @@ +// 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.Globalization; +using System.Text; + +namespace ILCompiler.Reflection.ReadyToRun +{ + public static class StringBuilderExtensions + { + /// + /// Appends a C# string literal with the given value to the string builder. + /// + /// + /// This method closely follows the logic in + /// method in Roslyn .NET compiler; see its + /// sources for reference. + /// + public static StringBuilder AppendEscapedString(this StringBuilder builder, string value) + { + builder.Append('"'); + + for (int i = 0; i < value.Length; i++) + { + char c = value[i]; + UnicodeCategory category; + + // Fast check for printable ASCII characters + if ((c <= 0x7e) && (c >= 0x20) || !NeedsEscaping(category = CharUnicodeInfo.GetUnicodeCategory(c))) + { + if ((c == '"') || (c == '\\')) + { + builder.Append(@"\"); + } + builder.Append(c); + } + else if (category == UnicodeCategory.Surrogate) + { + // Check for a valid surrogate pair + category = CharUnicodeInfo.GetUnicodeCategory(value, i); + if (category == UnicodeCategory.Surrogate) + { + // Escape an unpaired surrogate + builder.Append(@"\u" + ((int)c).ToString("x4")); + } + else if (NeedsEscaping(category)) + { + // A surrogate pair that needs to be escaped + int codePoint = char.ConvertToUtf32(value, i); + builder.Append(@"\U" + codePoint.ToString("x8")); + i++; // Skip the already-encoded second surrogate of the pair + } + else + { + // Copy a printable surrogate pair + builder.Append(c); + builder.Append(value[++i]); + } + } + else + { + string escaped = c switch + { + '\0' => @"\0", + '\a' => @"\a", + '\b' => @"\b", + '\f' => @"\f", + '\n' => @"\n", + '\r' => @"\r", + '\t' => @"\t", + '\v' => @"\v", + _ => @"\u" + ((int)c).ToString("x4") + }; + builder.Append(escaped); + } + } + + builder.Append('"'); + return builder; + } + + /// + /// Determines whether characters of the given will be represented with escape sequences. + /// + private static bool NeedsEscaping(UnicodeCategory category) + { + switch (category) + { + case UnicodeCategory.LineSeparator: + case UnicodeCategory.ParagraphSeparator: + case UnicodeCategory.Control: + case UnicodeCategory.Surrogate: + case UnicodeCategory.OtherNotAssigned: + return true; + default: + return false; + } + } + } + + public static class StringExtensions + { + /// + /// Returns a C# string literal with the given value. + /// + public static string ToEscapedString(this string value) + { + return new StringBuilder(value.Length + 16).AppendEscapedString(value).ToString(); + } + } +} diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj index c034a83959686..15af6af32d334 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj @@ -21,10 +21,10 @@ 4.3.0 - 1.6.0 + 1.8.1 - 1.0.8 + 1.3.0 diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs b/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs index 72843451e10e2..3b52671fc6641 100644 --- a/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs +++ b/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs @@ -476,6 +476,7 @@ private int Run() .UseParallelism(_commandLineOptions.Parallelism) .UseJitPath(_commandLineOptions.JitPath) .UseInstructionSetSupport(instructionSetSupport) + .GenerateOutputFile(_commandLineOptions.OutputFilePath.FullName) .UseILProvider(ilProvider) .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/crossgen2.csproj b/src/coreclr/src/tools/crossgen2/crossgen2/crossgen2.csproj index 79a939ca1cdb2..b3c21b883c576 100644 --- a/src/coreclr/src/tools/crossgen2/crossgen2/crossgen2.csproj +++ b/src/coreclr/src/tools/crossgen2/crossgen2/crossgen2.csproj @@ -35,8 +35,8 @@ - - 0.3.0-alpha.19577.1 + + $(SystemCommandLineVersion) diff --git a/src/coreclr/src/tools/dotnet-pgo/dotnet-pgo.csproj b/src/coreclr/src/tools/dotnet-pgo/dotnet-pgo.csproj index ced46b34b19a0..aa2f8968c4200 100644 --- a/src/coreclr/src/tools/dotnet-pgo/dotnet-pgo.csproj +++ b/src/coreclr/src/tools/dotnet-pgo/dotnet-pgo.csproj @@ -14,8 +14,8 @@ - - - + + + diff --git a/src/coreclr/src/tools/r2rdump/CommandLineOptions.cs b/src/coreclr/src/tools/r2rdump/CommandLineOptions.cs index 5ddfd1dbeb6b3..6b3f53aa6ce35 100644 --- a/src/coreclr/src/tools/r2rdump/CommandLineOptions.cs +++ b/src/coreclr/src/tools/r2rdump/CommandLineOptions.cs @@ -12,30 +12,32 @@ internal static class CommandLineOptions public static RootCommand RootCommand() { RootCommand command = new RootCommand(); - command.AddOption(new Option(new[] { "--in", "-i" }, "Input file(s) to dump. Expects them to by ReadyToRun images", new Argument())); - command.AddOption(new Option(new[] { "--out", "-o" }, "Output file path. Dumps everything to the specified file except for help message and exception messages", new Argument())); - command.AddOption(new Option(new[] { "--raw" }, "Dump the raw bytes of each section or runtime function", new Argument())); - command.AddOption(new Option(new[] { "--header" }, "Dump R2R header", new Argument())); - command.AddOption(new Option(new[] { "--disasm", "-d" }, "Show disassembly of methods or runtime functions", new Argument())); - command.AddOption(new Option(new[] { "--naked" }, "Naked dump suppresses most compilation details like placement addresses", new Argument())); - command.AddOption(new Option(new[] { "--hide-offsets", "--ho" }, "Hide offsets in naked disassembly", new Argument())); - command.AddOption(new Option(new[] { "--query", "-q" }, "Query method by exact name, signature, row ID or token", new Argument())); - command.AddOption(new Option(new[] { "--keyword", "-k" }, "Search method by keyword", new Argument())); - command.AddOption(new Option(new[] { "--runtimefunction", "-f" }, "Get one runtime function by id or relative virtual address", new Argument())); - command.AddOption(new Option(new[] { "--section", "-s" }, "Get section by keyword", new Argument())); - command.AddOption(new Option(new[] { "--unwind" }, "Dump unwindInfo", new Argument())); - command.AddOption(new Option(new[] { "--gc" }, "Dump gcInfo and slot table", new Argument())); - command.AddOption(new Option(new[] { "--sectionContents", "--sc" }, "Dump section contents", new Argument())); - command.AddOption(new Option(new[] { "--entrypoints", "-e" }, "Dump list of method / instance entrypoints in the R2R file", new Argument())); - command.AddOption(new Option(new[] { "--normalize", "-n" }, "Normalize dump by sorting the various tables and methods (default = unsorted i.e. file order)", new Argument())); - command.AddOption(new Option(new[] { "--hide-transitions", "--ht" }, "Don't include GC transitions in disassembly output", new Argument())); - command.AddOption(new Option(new[] { "--verbose", "-v" }, "Dump disassembly, unwindInfo, gcInfo and sectionContents", new Argument())); - command.AddOption(new Option(new[] { "--diff" }, "Compare two R2R images", new Argument())); - command.AddOption(new Option(new[] { "--diff-hide-same-disasm" }, "In matching method diff dump, hide functions with identical disassembly", new Argument())); - command.AddOption(new Option(new[] { "--reference", "-r" }, "Explicit reference assembly files", new Argument())); - command.AddOption(new Option(new[] { "--referencePath", "--rp" }, "Search paths for reference assemblies", new Argument())); - command.AddOption(new Option(new[] { "--inlineSignatureBinary", "--isb" }, "Embed binary signature into its textual representation", new Argument())); - command.AddOption(new Option(new[] { "--signatureBinary", "--sb" }, "Append signature binary to its textual representation", new Argument())); + command.AddOption(new Option(new[] { "--in", "-i" }, "Input file(s) to dump. Expects them to by ReadyToRun images")); + command.AddOption(new Option(new[] { "--out", "-o" }, "Output file path. Dumps everything to the specified file except for help message and exception messages")); + command.AddOption(new Option(new[] { "--raw" }, "Dump the raw bytes of each section or runtime function")); + command.AddOption(new Option(new[] { "--header" }, "Dump R2R header")); + command.AddOption(new Option(new[] { "--disasm", "-d" }, "Show disassembly of methods or runtime functions")); + command.AddOption(new Option(new[] { "--naked" }, "Naked dump suppresses most compilation details like placement addresses")); + command.AddOption(new Option(new[] { "--hide-offsets", "--ho" }, "Hide offsets in naked disassembly")); + command.AddOption(new Option(new[] { "--query", "-q" }, "Query method by exact name, signature, row ID or token")); + command.AddOption(new Option(new[] { "--keyword", "-k" }, "Search method by keyword")); + command.AddOption(new Option(new[] { "--runtimefunction", "-f" }, "Get one runtime function by id or relative virtual address")); + command.AddOption(new Option(new[] { "--section", "-s" }, "Get section by keyword")); + command.AddOption(new Option(new[] { "--unwind" }, "Dump unwindInfo")); + command.AddOption(new Option(new[] { "--gc" }, "Dump gcInfo and slot table")); + command.AddOption(new Option(new[] { "--sectionContents", "--sc" }, "Dump section contents")); + command.AddOption(new Option(new[] { "--entrypoints", "-e" }, "Dump list of method / instance entrypoints in the R2R file")); + command.AddOption(new Option(new[] { "--normalize", "-n" }, "Normalize dump by sorting the various tables and methods (default = unsorted i.e. file order)")); + command.AddOption(new Option(new[] { "--hide-transitions", "--ht" }, "Don't include GC transitions in disassembly output")); + command.AddOption(new Option(new[] { "--verbose", "-v" }, "Dump disassembly, unwindInfo, gcInfo and sectionContents")); + command.AddOption(new Option(new[] { "--diff" }, "Compare two R2R images")); + command.AddOption(new Option(new[] { "--diff-hide-same-disasm" }, "In matching method diff dump, hide functions with identical disassembly")); + command.AddOption(new Option(new[] { "--reference", "-r" }, "Explicit reference assembly files")); + command.AddOption(new Option(new[] { "--referencePath", "--rp" }, "Search paths for reference assemblies")); + command.AddOption(new Option(new[] { "--inlineSignatureBinary", "--isb" }, "Embed binary signature into its textual representation")); + command.AddOption(new Option(new[] { "--signatureBinary", "--sb" }, "Append signature binary to its textual representation")); + command.AddOption(new Option(new[] { "--create-pdb" }, "Create PDB")); + command.AddOption(new Option(new[] { "--pdb-path" }, "PDB output path for --createpdb")); return command; } } diff --git a/src/coreclr/src/tools/r2rdump/CoreDisTools.cs b/src/coreclr/src/tools/r2rdump/CoreDisTools.cs index bbaf801ad3cb6..1f41eab41af66 100644 --- a/src/coreclr/src/tools/r2rdump/CoreDisTools.cs +++ b/src/coreclr/src/tools/r2rdump/CoreDisTools.cs @@ -45,7 +45,7 @@ public enum TargetArch public unsafe static int GetInstruction(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, int rtfOffset, byte[] image, out string instr) { - int instrSize = 1; + int instrSize; fixed (byte* p = image) { IntPtr ptr = (IntPtr)(p + imageOffset + rtfOffset); @@ -58,7 +58,7 @@ public unsafe static int GetInstruction(IntPtr Disasm, RuntimeFunction rtf, int public static IntPtr GetDisasm(Machine machine) { - TargetArch target = TargetArch.Target_Host; + TargetArch target; switch (machine) { case Machine.Amd64: @@ -86,6 +86,16 @@ public static IntPtr GetDisasm(Machine machine) /// public class Disassembler : IDisposable { + /// + /// Indentation of instruction mnemonics in naked mode with no offsets. + /// + private const int NakedNoOffsetIndentation = 4; + + /// + /// Indentation of instruction mnemonics in naked mode with offsets. + /// + private const int NakedWithOffsetIndentation = 11; + /// /// R2R reader is used to access architecture info, the PE image data and symbol table. /// @@ -101,6 +111,16 @@ public class Disassembler : IDisposable /// private readonly IntPtr _disasm; + /// + /// Indentation of instruction mnemonics. + /// + public int MnemonicIndentation { get; private set; } + + /// + /// Indentation of instruction mnemonics. + /// + public int OperandsIndentation { get; private set; } + /// /// Store the R2R reader and construct the disassembler for the appropriate architecture. /// @@ -110,6 +130,7 @@ public Disassembler(ReadyToRunReader reader, DumpOptions options) _reader = reader; _options = options; _disasm = CoreDisTools.GetDisasm(_reader.Machine); + SetIndentations(); } /// @@ -124,7 +145,52 @@ public void Dispose() } /// - /// Parse a single instruction and return the RVA of the next instruction. + /// Set indentations for mnemonics and operands. + /// + private void SetIndentations() + { + if (_options.Naked) + { + MnemonicIndentation = _options.HideOffsets ? NakedNoOffsetIndentation : NakedWithOffsetIndentation; + } + else + { + // The length of the byte dump starting with the first hexadecimal digit and ending with the final space + int byteDumpLength = _reader.Machine switch + { + // Most instructions are no longer than 7 bytes. CorDisasm::dumpInstruction always pads byte dumps + // to 7 * 3 characters; see https://github.com/dotnet/llilc/blob/master/lib/CoreDisTools/coredistools.cpp. + Machine.I386 => 7 * 3, + Machine.Amd64 => 7 * 3, + + // Instructions are either 2 or 4 bytes long + Machine.ArmThumb2 => 4 * 3, + + // Instructions are dumped as 4-byte hexadecimal integers + Machine.Arm64 => 4 * 2 + 1, + + _ => throw new NotImplementedException() + }; + + MnemonicIndentation = NakedWithOffsetIndentation + byteDumpLength; + } + + // This leaves 7 characters for the mnemonic + OperandsIndentation = MnemonicIndentation + 8; + } + + /// + /// Append spaces to the string builder to achieve at least the given indentation. + /// + private static void EnsureIndentation(StringBuilder builder, int lineStartIndex, int desiredIndentation) + { + int currentIndentation = builder.Length - lineStartIndex; + int spacesToAppend = Math.Max(desiredIndentation - currentIndentation, 1); + builder.Append(' ', spacesToAppend); + } + + /// + /// Parse and dump a single instruction and return its size in bytes. /// /// Runtime function to parse /// Offset within the PE image byte array @@ -142,47 +208,108 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o int instrSize = CoreDisTools.GetInstruction(_disasm, rtf, imageOffset, rtfOffset, _reader.Image, out instruction); CoreDisTools.ClearOutputBuffer(); - instruction = instruction.Replace('\t', ' '); + // CoreDisTools dumps instructions in the following format: + // + // address: bytes [padding] \t mnemonic [\t operands] \n + // + // However, due to an LLVM issue regarding instruction prefixes (https://bugs.llvm.org/show_bug.cgi?id=7709), + // multiple lines may be returned for a single x86/x64 instruction. - if (_options.Naked) + var builder = new StringBuilder(); + int lineNum = 0; + // The start index of the last line in builder + int lineStartIndex = 0; + + // Remove this foreach wrapper and line* variables after the aforementioned LLVM issue is fixed + foreach (string line in instruction.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) { - StringBuilder nakedInstruction = new StringBuilder(); - foreach (string line in instruction.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) + int colonIndex = line.IndexOf(':'); + int tab1Index = line.IndexOf('\t'); + + if ((0 < colonIndex) && (colonIndex < tab1Index)) { - int colon = line.IndexOf(':'); - if (colon >= 0) + // First handle the address and the byte dump + if (_options.Naked) { - colon += 2; - while (colon + 3 <= line.Length && - IsXDigit(line[colon]) && - IsXDigit(line[colon + 1]) && - line[colon + 2] == ' ') + if (!_options.HideOffsets) { - colon += 3; + // All lines but the last one must represent single-byte prefixes, so add lineNum to the offset + builder.Append($"{rtf.CodeOffset + rtfOffset + lineNum,8:x4}:"); } - - if (!_options.HideOffsets) + } + else + { + if (_reader.Machine == Machine.Arm64) { - nakedInstruction.Append($"{(rtfOffset + rtf.CodeOffset),8:x4}:"); - nakedInstruction.Append(" "); + // Replace " hh hh hh hh " byte dump with " hhhhhhhh ". + // CoreDisTools should be fixed to dump bytes this way for ARM64. + uint instructionBytes = BitConverter.ToUInt32(_reader.Image, imageOffset + rtfOffset); + builder.Append(line, 0, colonIndex + 1); + builder.Append(' '); + builder.Append(instructionBytes.ToString("x8")); } else { - nakedInstruction.Append(" "); + // Copy the offset and the byte dump + int byteDumpEndIndex = tab1Index; + do + { + byteDumpEndIndex--; + } + while (line[byteDumpEndIndex] == ' '); + builder.Append(line, 0, byteDumpEndIndex + 1); + } + builder.Append(' '); + } + + // Now handle the mnemonic and operands. Ensure proper indentation for the mnemonic. + EnsureIndentation(builder, lineStartIndex, MnemonicIndentation); + + int tab2Index = line.IndexOf('\t', tab1Index + 1); + if (tab2Index >= 0) + { + // Copy everything between the first and the second tabs + builder.Append(line, tab1Index + 1, tab2Index - tab1Index - 1); + // Ensure proper indentation for the operands + EnsureIndentation(builder, lineStartIndex, OperandsIndentation); + int afterTab2Index = tab2Index + 1; + + // Work around an LLVM issue causing an extra space to be output before operands; + // see https://reviews.llvm.org/D35946. + if ((afterTab2Index < line.Length) && + ((line[afterTab2Index] == ' ') || (line[afterTab2Index] == '\t'))) + { + afterTab2Index++; + } + + // Copy everything after the second tab + int savedLength = builder.Length; + builder.Append(line, afterTab2Index, line.Length - afterTab2Index); + // There should be no extra tabs. Should we encounter them, replace them with a single space. + if (line.IndexOf('\t', afterTab2Index) >= 0) + { + builder.Replace('\t', ' ', savedLength, builder.Length - savedLength); } - nakedInstruction.Append(line.Substring(colon).TrimStart()); - nakedInstruction.Append('\n'); } else { - nakedInstruction.Append(' ', 7); - nakedInstruction.Append(line.TrimStart()); - nakedInstruction.Append('\n'); + // Copy everything after the first tab + builder.Append(line, tab1Index + 1, line.Length - tab1Index - 1); } } - instruction = nakedInstruction.ToString(); + else + { + // Should not happen. Just replace tabs with spaces. + builder.Append(line.Replace('\t', ' ')); + } + + builder.Append('\n'); + lineNum++; + lineStartIndex = builder.Length; } + instruction = builder.ToString(); + switch (_reader.Machine) { case Machine.Amd64: @@ -194,7 +321,6 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o break; case Machine.ArmThumb2: - case Machine.Thumb: break; case Machine.Arm64: @@ -208,11 +334,6 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o return instrSize; } - private static bool IsXDigit(char c) - { - return Char.IsDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); - } - const string RelIPTag = "[rip "; /// diff --git a/src/coreclr/src/tools/r2rdump/ISymNGenWriter.cs b/src/coreclr/src/tools/r2rdump/ISymNGenWriter.cs new file mode 100644 index 0000000000000..8a4eb8074fb6f --- /dev/null +++ b/src/coreclr/src/tools/r2rdump/ISymNGenWriter.cs @@ -0,0 +1,85 @@ +// 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. + +#pragma warning disable 436 // SuppressUnmanagedCodeSecurityAttribute defined in source and mscorlib + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace Microsoft.DiaSymReader +{ + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D682FD12-43dE-411C-811B-BE8404CEA126"), SuppressUnmanagedCodeSecurity] + internal interface ISymNGenWriter + { + // Add a new public symbol to the NGEN PDB. + void AddSymbol([MarshalAs(UnmanagedType.BStr)] string pSymbol, + ushort iSection, + ulong rva); + + // Adds a new section to the NGEN PDB. + void AddSection(ushort iSection, + OMF flags, + int offset, + int cb); + } + + [Flags] + internal enum OMF : ushort + { + Const_Read = 0x0001, + Const_Write = 0x0002, + Const_Exec = 0x0004, + Const_F32Bit = 0x0008, + Const_ReservedBits1 = 0x00f0, + Const_FSel = 0x0100, + Const_FAbs = 0x0200, + Const_ReservedBits2 = 0x0C00, + Const_FGroup = 0x1000, + Const_ReservedBits3 = 0xE000, + + + StandardText = (Const_FSel|Const_F32Bit|Const_Exec|Const_Read), // 0x10D + SentinelType = (Const_FAbs|Const_F32Bit) // 0x208 + } + + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4"), SuppressUnmanagedCodeSecurity] + internal interface ISymNGenWriter2 : ISymNGenWriter + { + // Add a new public symbol to the NGEN PDB. + new void AddSymbol([MarshalAs(UnmanagedType.BStr)] string pSymbol, + ushort iSection, + ulong rva); + + // Adds a new section to the NGEN PDB. + new void AddSection(ushort iSection, + OMF flags, + int offset, + int cb); + + void OpenModW([MarshalAs(UnmanagedType.LPWStr)] string wszModule, + [MarshalAs(UnmanagedType.LPWStr)] string wszObjFile, + out UIntPtr ppmod); + + void CloseMod(UIntPtr pmod); + + void ModAddSymbols(UIntPtr pmod, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSym, int cb); + + void ModAddSecContribEx( + UIntPtr pmod, + ushort isect, + int off, + int cb, + uint dwCharacteristics, + uint dwDataCrc, + uint dwRelocCrc); + + void QueryPDBNameExW( + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pdb, + IntPtr cchMax); + } +} diff --git a/src/coreclr/src/tools/r2rdump/PdbWriter.cs b/src/coreclr/src/tools/r2rdump/PdbWriter.cs new file mode 100644 index 0000000000000..bbf6c5f1f1cbe --- /dev/null +++ b/src/coreclr/src/tools/r2rdump/PdbWriter.cs @@ -0,0 +1,394 @@ +// 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.Collections.Generic; +using System.IO; +using System.Reflection.PortableExecutable; +using System.Runtime.InteropServices; +using System.Text; + +using Microsoft.DiaSymReader; + +namespace ILCompiler.PdbWriter +{ + // NGEN always generates PDBs with public symbols lists (so tools can map IP ranges to + // methods). This bitmask indicates what extra info should be added to the PDB + [Flags] + public enum PDBExtraData + { + None = 0, + // Add string table subsection, files checksum subsection, and lines subsection to + // allow tools to map IP ranges to source lines. + kPDBLines = 0x00000001, + }; + + struct MethodInfo + { + public string AssemblyName; + public uint MethodToken; + public uint HotRVA; + public string Name; + public uint ColdRVA; + } + + interface IModuleData + { + IEnumerable Methods { get; } + } + + public enum SymChecksumType : byte + { + None = 0, // indicates no checksum is available + MD5, + SHA1, + SHA_256, + }; + + class SymDocument : IEquatable + { + public string Name; + public SymChecksumType ChecksumType; + public byte[] Checksum; + + + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + public override bool Equals(object other) + { + if (other is SymDocument documentOther) + { + return Equals(documentOther); + } + + return false; + } + + public bool Equals(SymDocument other) + { + if (Name != other.Name) + return false; + if (ChecksumType != other.ChecksumType) + return false; + if (Checksum.Length != other.Checksum.Length) + return false; + for (int i = 0; i < Checksum.Length; i++) + { + if (Checksum[i] != other.Checksum[i]) + return false; + } + + return true; + } + } + + class PdbWriter + { + string _pdbPath; + PDBExtraData _pdbExtraData; + + string _pdbFilePath; + string _tempSourceDllName; + + List _symDocuments = new List(); + Dictionary _stringTableToOffsetMapping; + Dictionary _documentToChecksumOffsetMapping; + + UIntPtr _pdbMod; + ISymNGenWriter2 _ngenWriter; + + private const string DiaSymReaderModuleName32 = "Microsoft.DiaSymReader.Native.x86.dll"; + private const string DiaSymReaderModuleName64 = "Microsoft.DiaSymReader.Native.amd64.dll"; + + private const string CreateNGenPdbWriterFactoryName = "CreateNGenPdbWriter"; + + [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.SafeDirectories)] + [DllImport(DiaSymReaderModuleName32, EntryPoint = CreateNGenPdbWriterFactoryName, PreserveSig = false)] + private extern static void CreateNGenPdbWriter32([MarshalAs(UnmanagedType.LPWStr)] string ngenImagePath, [MarshalAs(UnmanagedType.LPWStr)] string pdbPath, [MarshalAs(UnmanagedType.IUnknown)] out object ngenPdbWriter); + + [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.SafeDirectories)] + [DllImport(DiaSymReaderModuleName64, EntryPoint = CreateNGenPdbWriterFactoryName, PreserveSig = false)] + private extern static void CreateNGenPdbWriter64([MarshalAs(UnmanagedType.LPWStr)] string ngenImagePath, [MarshalAs(UnmanagedType.LPWStr)] string pdbPath, [MarshalAs(UnmanagedType.IUnknown)] out object ngenPdbWriter); + + private static ISymNGenWriter2 CreateNGenWriter(string ngenImagePath, string pdbPath) + { + object instance; + + if (IntPtr.Size == 4) + { + CreateNGenPdbWriter32(ngenImagePath, pdbPath, out instance); + } + else + { + CreateNGenPdbWriter64(ngenImagePath, pdbPath, out instance); + } + return (ISymNGenWriter2)instance; + } + + public PdbWriter(string pdbPath, PDBExtraData pdbExtraData) + { + SymDocument unknownDocument = new SymDocument(); + unknownDocument.Name = "unknown"; + unknownDocument.ChecksumType = SymChecksumType.None; + unknownDocument.Checksum = Array.Empty(); + + _symDocuments.Add(unknownDocument); + _pdbPath = pdbPath; + _pdbExtraData = pdbExtraData; + } + + public void WritePDBData(string dllPath, IEnumerable methods) + { + bool failed = true; + try + { + try + { + try + { + WritePDBDataHelper(dllPath, methods); + } + finally + { + if ((_ngenWriter != null) && (_pdbMod != UIntPtr.Zero)) + { + _ngenWriter.CloseMod(_pdbMod); + } + } + } + finally + { + if (_ngenWriter != null) + { + Marshal.FinalReleaseComObject(_ngenWriter); + } + } + + failed = false; + } + finally + { + if (_tempSourceDllName != null) + { + try + { + File.Delete(_tempSourceDllName); + } + catch {} + } + + if (failed && (_pdbFilePath != null)) + { + try + { + // If anything fails, do not create a partial pdb file + File.Delete(_pdbFilePath); + } + catch {} + } + } + } + + private void WritePDBDataHelper(string dllPath, IEnumerable methods) + { + // This will try to open the managed PDB if lines info was requested. This is a + // likely failure point, so intentionally do this before creating the NGEN PDB file + // on disk. + bool isILPDBProvided = false; + if (_pdbExtraData.HasFlag(PDBExtraData.kPDBLines)) + { + // line mapping not ported from crossgen yet. + throw new NotImplementedException(); + } + + string originalDllPath = dllPath; + + // Currently DiaSymReader does not work properly generating NGEN PDBS unless + // the DLL whose PDB is being generated ends in .ni.*. Unfortunately, readyToRun + // images do not follow this convention and end up producing bad PDBS. To fix + // this (without changing diasymreader.dll which ships indepdendently of .NET Core) + // we copy the file to somethign with this convention before generating the PDB + // and delete it when we are done. + if (!dllPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase) && !dllPath.EndsWith(".ni.exe", StringComparison.OrdinalIgnoreCase)) + { + _tempSourceDllName = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".ni" + Path.GetExtension(dllPath)); + File.Copy(dllPath, _tempSourceDllName); + dllPath = _tempSourceDllName; + } + + _ngenWriter = CreateNGenWriter(dllPath, _pdbPath + "\\"); + + { + // PDB file is now created. Get its path and initialize _pdbFilePath so the PDB file + // can be deleted if we don't make it successfully to the end + StringBuilder pdbFilePathBuilder = new StringBuilder(); + pdbFilePathBuilder.Capacity = 1024; + _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(pdbFilePathBuilder.Capacity)); + _pdbFilePath = pdbFilePathBuilder.ToString(); + } + + _ngenWriter.OpenModW(originalDllPath, Path.GetFileName(originalDllPath), out _pdbMod); + + WriteStringTable(); + WriteFileChecksums(); + + ushort? iCodeSection = null; + uint rvaOfTextSection = 0; + using (var peReader = new PEReader(new FileStream(dllPath, FileMode.Open), PEStreamOptions.Default)) + { + var sections = peReader.PEHeaders.SectionHeaders; + + for (int i = 0; i < sections.Length; i++) + { + ushort pdbSectionNumber = checked((ushort)(i+1)); + + _ngenWriter.AddSection(pdbSectionNumber, OMF.StandardText, 0, sections[i].SizeOfRawData); + if (sections[i].Name == ".text") + { + iCodeSection = pdbSectionNumber; + rvaOfTextSection = (uint)sections[i].VirtualAddress; + } + _ngenWriter.ModAddSecContribEx(_pdbMod, pdbSectionNumber, 0, sections[i].SizeOfRawData, (uint)sections[i].SectionCharacteristics, 0, 0); + } + } + + // To support lines info, we need a "dummy" section, indexed as 0, for use as a + // sentinel when MSPDB sets up its section contribution table + _ngenWriter.AddSection(0, // Dummy section 0 + OMF.SentinelType, + 0, + unchecked((int)0xFFFFFFFF)); + + foreach (var method in methods) + { + WriteMethodPDBData(iCodeSection.Value, method, Path.GetFileNameWithoutExtension(originalDllPath), rvaOfTextSection, isILPDBProvided); + } + } + + void WriteMethodPDBData(ushort iCodeSection, MethodInfo method, string assemblyName, uint textSectionOffset, bool isILPDBProvided) + { + string nameSuffix = $"{method.Name}$#{(assemblyName != method.AssemblyName ? method.AssemblyName : String.Empty)}#{method.MethodToken.ToString("X")}"; + + _ngenWriter.AddSymbol(nameSuffix, iCodeSection, method.HotRVA - textSectionOffset); + if (method.ColdRVA != 0) + { + _ngenWriter.AddSymbol($"[COLD] {nameSuffix}", iCodeSection, method.ColdRVA); + } + + if (isILPDBProvided) + { + // line mapping not ported from crossgen yet. + throw new NotImplementedException(); + } + } + + private const int CV_SIGNATURE_C13 = 4; + private enum DEBUG_S_SUBSECTION_TYPE { + DEBUG_S_IGNORE = unchecked((int)0x80000000), // if this bit is set in a subsection type then ignore the subsection contents + + DEBUG_S_SYMBOLS = 0xf1, + DEBUG_S_LINES, + DEBUG_S_STRINGTABLE, + DEBUG_S_FILECHKSMS, + DEBUG_S_FRAMEDATA, + DEBUG_S_INLINEELINES, + DEBUG_S_CROSSSCOPEIMPORTS, + DEBUG_S_CROSSSCOPEEXPORTS, + + DEBUG_S_IL_LINES, + DEBUG_S_FUNC_MDTOKEN_MAP, + DEBUG_S_TYPE_MDTOKEN_MAP, + DEBUG_S_MERGED_ASSEMBLYINPUT, + + DEBUG_S_COFF_SYMBOL_RVA, + } + + private void WriteStringTable() + { + _stringTableToOffsetMapping = new Dictionary(); + + MemoryStream stringTableStream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stringTableStream, Encoding.UTF8); + writer.Write(CV_SIGNATURE_C13); + writer.Write((uint)DEBUG_S_SUBSECTION_TYPE.DEBUG_S_STRINGTABLE); + long sizeOfStringTablePosition = writer.BaseStream.Position; + writer.Write((uint)0); // Size of actual string table. To be filled in later + long startOfStringTableOffset = writer.BaseStream.Position; + foreach (var document in _symDocuments) + { + string str = document.Name; + if (_stringTableToOffsetMapping.ContainsKey(str)) + continue; + + long offset = writer.BaseStream.Position; + _stringTableToOffsetMapping.Add(str, checked((int)(offset - startOfStringTableOffset))); + writer.Write(str.AsSpan()); + writer.Write((byte)0); // Null terminate all strings + } + + // Update string table size + long stringTableSize = writer.BaseStream.Position - startOfStringTableOffset; + writer.BaseStream.Position = sizeOfStringTablePosition; + writer.Write(checked((uint)stringTableSize)); + writer.Flush(); + + // Write string table into pdb file + byte[] stringTableArray = stringTableStream.ToArray(); + _ngenWriter.ModAddSymbols(_pdbMod, stringTableArray, stringTableArray.Length); + } + + private void WriteFileChecksums() + { + _documentToChecksumOffsetMapping = new Dictionary(); + + MemoryStream checksumStream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(checksumStream, Encoding.UTF8); + writer.Write(CV_SIGNATURE_C13); + writer.Write((uint)DEBUG_S_SUBSECTION_TYPE.DEBUG_S_FILECHKSMS); + + long sizeOfChecksumTablePosition = writer.BaseStream.Position; + writer.Write((uint)0); // Size of actual checksum table. To be filled in later + long startOfChecksumTableOffset = writer.BaseStream.Position; + foreach (var document in _symDocuments) + { + long offset = writer.BaseStream.Position; + _documentToChecksumOffsetMapping.Add(document, checked((int)(offset - startOfChecksumTableOffset))); + + SymChecksumType checksumType = document.ChecksumType; + byte[] checksum = document.Checksum; + + if (document.Checksum.Length > 255) + { + // Should never happen, but just in case checksum data is invalid, just put + // no checksum into the NGEN PDB + checksumType = SymChecksumType.None; + checksum = Array.Empty(); + } + writer.Write(_stringTableToOffsetMapping[document.Name]); + writer.Write((byte)checksum.Length); + writer.Write((byte)checksumType); + writer.Write(checksum); + + // Must align to the next 4-byte boundary + while ((writer.BaseStream.Position % 4) != 0) + { + writer.Write((byte)0); + } + } + + // Update checksum table size + long checksumTableSize = writer.BaseStream.Position - startOfChecksumTableOffset; + writer.BaseStream.Position = sizeOfChecksumTablePosition; + writer.Write(checked((uint)checksumTableSize)); + writer.Flush(); + + // Write string table into pdb file + byte[] checksumTableArray = checksumStream.ToArray(); + _ngenWriter.ModAddSymbols(_pdbMod, checksumTableArray, checksumTableArray.Length); + } + } +} diff --git a/src/coreclr/src/tools/r2rdump/R2RDump.cs b/src/coreclr/src/tools/r2rdump/R2RDump.cs index 5e4360db44228..320d41548d9aa 100644 --- a/src/coreclr/src/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/src/tools/r2rdump/R2RDump.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.CommandLine; using System.CommandLine.Invocation; using System.IO; using System.Linq; @@ -15,6 +16,7 @@ using System.Text; using System.Threading.Tasks; using ILCompiler.Reflection.ReadyToRun; +using ILCompiler.PdbWriter; using Internal.Runtime; @@ -46,6 +48,9 @@ public class DumpOptions : IAssemblyResolver public bool DiffHideSameDisasm { get; set; } public bool IgnoreSensitive { get; set; } + public bool CreatePDB { get; set; } + public string PdbPath { get; set; } + public FileInfo[] Reference { get; set; } public DirectoryInfo[] ReferencePath { get; set; } @@ -199,12 +204,14 @@ class R2RDump { private readonly DumpOptions _options; private readonly Dictionary _selectedSections = new Dictionary(); + private readonly Encoding _encoding; private readonly TextWriter _writer; private Dumper _dumper; private R2RDump(DumpOptions options) { _options = options; + _encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false); if (_options.Verbose) { @@ -216,7 +223,7 @@ private R2RDump(DumpOptions options) if (_options.Out != null) { - _writer = new StreamWriter(_options.Out.FullName, append: false, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false)); + _writer = new StreamWriter(_options.Out.FullName, append: false, _encoding); } else { @@ -337,8 +344,9 @@ private void QueryRuntimeFunction(ReadyToRunReader r2r, IEnumerable quer public void Dump(ReadyToRunReader r2r) { _dumper.Begin(); + bool standardDump = !(_options.EntryPoints || _options.CreatePDB); - if (_options.Header || !_options.EntryPoints) + if (_options.Header && standardDump) { _dumper.WriteDivider("R2R Header"); _dumper.DumpHeader(true); @@ -377,7 +385,18 @@ public void Dump(ReadyToRunReader r2r) _dumper.DumpEntryPoints(); } - if (!_options.Header && !_options.EntryPoints) + if (_options.CreatePDB) + { + string pdbPath = _options.PdbPath; + if (String.IsNullOrEmpty(pdbPath)) + { + pdbPath = Path.GetDirectoryName(r2r.Filename); + } + var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None); + pdbWriter.WritePDBData(r2r.Filename, ProducePdbWriterMethods(r2r)); + } + + if (!_options.Header && standardDump) { _dumper.DumpAllMethods(); } @@ -386,6 +405,21 @@ public void Dump(ReadyToRunReader r2r) _dumper.End(); } + IEnumerable ProducePdbWriterMethods(ReadyToRunReader r2r) + { + foreach (var method in _dumper.NormalizedMethods()) + { + MethodInfo mi = new MethodInfo(); + mi.Name = method.SignatureString; + mi.HotRVA = (uint)method.RuntimeFunctions[0].StartAddress; + mi.MethodToken = (uint)MetadataTokens.GetToken(method.MetadataReader, method.MethodHandle); + mi.AssemblyName = method.MetadataReader.GetString(method.MetadataReader.GetAssemblyDefinition().Name); + mi.ColdRVA = 0; + + yield return mi; + } + } + /// /// Returns true if the name, signature or id of method matches query /// @@ -538,7 +572,7 @@ private int Run() else { string perFileOutput = filename.FullName + ".common-methods.r2r"; - _dumper = new TextDumper(r2r, new StreamWriter(perFileOutput), disassembler, _options); + _dumper = new TextDumper(r2r, new StreamWriter(perFileOutput, append: false, _encoding), disassembler, _options); if (previousDumper != null) { new R2RDiff(previousDumper, _dumper, _writer).Run(); diff --git a/src/coreclr/src/tools/r2rdump/R2RDump.csproj b/src/coreclr/src/tools/r2rdump/R2RDump.csproj index f54756878189d..95dc287d162bc 100644 --- a/src/coreclr/src/tools/r2rdump/R2RDump.csproj +++ b/src/coreclr/src/tools/r2rdump/R2RDump.csproj @@ -15,12 +15,14 @@ AnyCPU;x64 + + 1.0.1-prerelease-00005 - - 0.2.0-alpha.19174.3 + + $(SystemCommandLineVersion) diff --git a/src/coreclr/src/tools/r2rdump/R2RFormat.png b/src/coreclr/src/tools/r2rdump/R2RFormat.png index f989086c61f7f..60b84b6cdbeea 100644 Binary files a/src/coreclr/src/tools/r2rdump/R2RFormat.png and b/src/coreclr/src/tools/r2rdump/R2RFormat.png differ diff --git a/src/coreclr/src/tools/r2rdump/TextDumper.cs b/src/coreclr/src/tools/r2rdump/TextDumper.cs index 9b67bad70af76..84ff8cc968685 100644 --- a/src/coreclr/src/tools/r2rdump/TextDumper.cs +++ b/src/coreclr/src/tools/r2rdump/TextDumper.cs @@ -134,7 +134,7 @@ internal override void DumpEntryPoints() internal override void DumpAllMethods() { WriteDivider("R2R Methods"); - _writer.WriteLine($"{_r2r.Methods.Count} methods"); + _writer.WriteLine($"{_r2r.Methods.Sum(kvp => kvp.Value.Count)} methods"); SkipLine(); foreach (ReadyToRunMethod method in NormalizedMethods()) { @@ -207,10 +207,10 @@ internal override void DumpRuntimeFunction(RuntimeFunction rtf) /// internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset) { - int indent = (_options.Naked ? _options.HideOffsets ? 4 : 11 : 32); - string indentString = new string(' ', indent); - int rtfOffset = 0; + string indentString = new string(' ', _disassembler.MnemonicIndentation); int codeOffset = rtf.CodeOffset; + int rtfOffset = 0; + while (rtfOffset < rtf.Size) { string instr; @@ -450,12 +450,12 @@ internal override void DumpSectionContents(ReadyToRunSection section) break; case ReadyToRunSectionType.OwnerCompositeExecutable: int oceOffset = _r2r.GetOffset(section.RelativeVirtualAddress); - Decoder decoder = Encoding.UTF8.GetDecoder(); - int charLength = decoder.GetCharCount(_r2r.Image, oceOffset, section.Size - 1); // exclude the zero terminator - char[] charArray = new char[charLength]; - decoder.GetChars(_r2r.Image, oceOffset, section.Size, charArray, 0, flush: true); - string ownerCompositeExecutable = new string(charArray); - _writer.WriteLine("Composite executable: {0}", ownerCompositeExecutable); + if (_r2r.Image[oceOffset + section.Size - 1] != 0) + { + R2RDump.WriteWarning("String is not zero-terminated"); + } + string ownerCompositeExecutable = Encoding.UTF8.GetString(_r2r.Image, oceOffset, section.Size - 1); // exclude the zero terminator + _writer.WriteLine("Composite executable: {0}", ownerCompositeExecutable.ToEscapedString()); break; } } diff --git a/src/coreclr/src/tools/r2rtest/BuildOptions.cs b/src/coreclr/src/tools/r2rtest/BuildOptions.cs index eec3f5bc711f3..152b6ae04352f 100644 --- a/src/coreclr/src/tools/r2rtest/BuildOptions.cs +++ b/src/coreclr/src/tools/r2rtest/BuildOptions.cs @@ -30,6 +30,7 @@ public class BuildOptions public bool Release { get; set; } public bool LargeBubble { get; set; } public bool Composite { get; set; } + public bool PartialComposite { get; set; } public int Crossgen2Parallelism { get; set; } public int CompilationTimeoutMinutes { get; set; } public int ExecutionTimeoutMinutes { get; set; } diff --git a/src/coreclr/src/tools/r2rtest/CommandLineOptions.cs b/src/coreclr/src/tools/r2rtest/CommandLineOptions.cs index 5f6d3d914d364..9575654a57934 100644 --- a/src/coreclr/src/tools/r2rtest/CommandLineOptions.cs +++ b/src/coreclr/src/tools/r2rtest/CommandLineOptions.cs @@ -24,8 +24,17 @@ public static CommandLineBuilder Build() return parser; + Command CreateCommand(string name, string description, Option[] options, Func action) + { + Command command = new Command(name, description); + foreach (var option in options) + command.AddOption(option); + command.Handler = CommandHandler.Create(action); + return command; + } + Command CompileFolder() => - new Command("compile-directory", "Compile all assemblies in directory", + CreateCommand("compile-directory", "Compile all assemblies in directory", new Option[] { InputDirectory(), @@ -56,10 +65,10 @@ public static CommandLineBuilder Build() MeasurePerf(), InputFileSearchString(), }, - handler: CommandHandler.Create(CompileDirectoryCommand.CompileDirectory)); + CompileDirectoryCommand.CompileDirectory); Command CompileSubtree() => - new Command("compile-subtree", "Build each directory in a given subtree containing any managed assemblies as a separate app", + CreateCommand("compile-subtree", "Build each directory in a given subtree containing any managed assemblies as a separate app", new Option[] { InputDirectory(), @@ -89,10 +98,10 @@ public static CommandLineBuilder Build() R2RDumpPath(), GCStress(), }, - handler: CommandHandler.Create(CompileSubtreeCommand.CompileSubtree)); + CompileSubtreeCommand.CompileSubtree); Command CompileFramework() => - new Command("compile-framework", "Compile managed framework assemblies in Core_Root", + CreateCommand("compile-framework", "Compile managed framework assemblies in Core_Root", new Option[] { CoreRootDirectory(), @@ -112,10 +121,10 @@ public static CommandLineBuilder Build() MeasurePerf(), InputFileSearchString(), }, - handler: CommandHandler.Create(CompileFrameworkCommand.CompileFramework)); + CompileFrameworkCommand.CompileFramework); Command CompileNugetPackages() => - new Command("compile-nuget", "Restore a list of Nuget packages into an empty console app, publish, and optimize with Crossgen / CPAOT", + CreateCommand("compile-nuget", "Restore a list of Nuget packages into an empty console app, publish, and optimize with Crossgen / CPAOT", new Option[] { R2RDumpPath(), @@ -129,10 +138,10 @@ public static CommandLineBuilder Build() CompilationTimeoutMinutes(), ExecutionTimeoutMinutes(), }, - handler: CommandHandler.Create(CompileNugetCommand.CompileNuget)); + CompileNugetCommand.CompileNuget); Command CompileCrossgenRsp() => - new Command("compile-crossgen-rsp", "Use existing Crossgen .rsp file(s) to build assemblies, optionally rewriting base paths", + CreateCommand("compile-crossgen-rsp", "Use existing Crossgen .rsp file(s) to build assemblies, optionally rewriting base paths", new Option[] { InputDirectory(), @@ -146,11 +155,11 @@ public static CommandLineBuilder Build() RewriteOldPath(), RewriteNewPath(), }, - handler: CommandHandler.Create(CompileFromCrossgenRspCommand.CompileFromCrossgenRsp)); + CompileFromCrossgenRspCommand.CompileFromCrossgenRsp); Command CompileSerp() => - new Command("compile-serp", "Compile existing application", - new Symbol[] + CreateCommand("compile-serp", "Compile existing application", + new Option[] { InputDirectory(), OutputDirectory(), @@ -158,115 +167,123 @@ public static CommandLineBuilder Build() CoreRootDirectory(), AspNetPath(), Composite(), + PartialComposite(), }, - handler: CommandHandler.Create(CompileSerpCommand.CompileSerpAssemblies)); + CompileSerpCommand.CompileSerpAssemblies); // Todo: Input / Output directories should be required arguments to the command when they're made available to handlers // https://github.com/dotnet/command-line-api/issues/297 Option InputDirectory() => - new Option(new[] { "--input-directory", "-in" }, "Folder containing assemblies to optimize", new Argument().ExistingOnly()); + new Option(new[] { "--input-directory", "-in" }, "Folder containing assemblies to optimize").ExistingOnly(); Option OutputDirectory() => - new Option(new[] { "--output-directory", "-out" }, "Folder to emit compiled assemblies", new Argument().LegalFilePathsOnly()); + new Option(new[] { "--output-directory", "-out" }, "Folder to emit compiled assemblies").LegalFilePathsOnly(); Option CoreRootDirectory() => - new Option(new[] { "--core-root-directory", "-cr" }, "Location of the CoreCLR CORE_ROOT folder", new Argument().ExistingOnly()); + new Option(new[] { "--core-root-directory", "-cr" }, "Location of the CoreCLR CORE_ROOT folder").ExistingOnly(); Option ReferencePath() => - new Option(new[] { "--reference-path", "-r" }, "Folder containing assemblies to reference during compilation", new Argument() { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly()); + new Option(new[] { "--reference-path", "-r" }, "Folder containing assemblies to reference during compilation") + { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly() }; Option Crossgen() => - new Option(new[] { "--crossgen" }, "Compile the apps using Crossgen in the CORE_ROOT folder", new Argument()); + new Option(new[] { "--crossgen" }, "Compile the apps using Crossgen in the CORE_ROOT folder"); Option CrossgenPath() => - new Option(new[] { "--crossgen-path", "-cp" }, "Explicit Crossgen path (useful for cross-targeting)", new Argument().ExistingOnly()); + new Option(new[] { "--crossgen-path", "-cp" }, "Explicit Crossgen path (useful for cross-targeting)").ExistingOnly(); Option NoJit() => - new Option(new[] { "--nojit" }, "Don't run tests in JITted mode", new Argument()); + new Option(new[] { "--nojit" }, "Don't run tests in JITted mode"); Option NoCrossgen2() => - new Option(new[] { "--nocrossgen2" }, "Don't run tests in Crossgen2 mode", new Argument()); + new Option(new[] { "--nocrossgen2" }, "Don't run tests in Crossgen2 mode"); Option Exe() => - new Option(new[] { "--exe" }, "Don't compile tests, just execute them", new Argument()); + new Option(new[] { "--exe" }, "Don't compile tests, just execute them"); Option NoExe() => - new Option(new[] { "--noexe" }, "Compilation-only mode (don't execute the built apps)", new Argument()); + new Option(new[] { "--noexe" }, "Compilation-only mode (don't execute the built apps)"); Option NoEtw() => - new Option(new[] { "--noetw" }, "Don't capture jitted methods using ETW", new Argument()); + new Option(new[] { "--noetw" }, "Don't capture jitted methods using ETW"); Option NoCleanup() => - new Option(new[] { "--nocleanup" }, "Don't clean up compilation artifacts after test runs", new Argument()); + new Option(new[] { "--nocleanup" }, "Don't clean up compilation artifacts after test runs"); Option Map() => - new Option(new[] { "--map" }, "Generate a map file (Crossgen2)", new Argument()); + new Option(new[] { "--map" }, "Generate a map file (Crossgen2)"); Option DegreeOfParallelism() => - new Option(new[] { "--degree-of-parallelism", "-dop" }, "Override default compilation / execution DOP (default = logical processor count)", new Argument()); + new Option(new[] { "--degree-of-parallelism", "-dop" }, "Override default compilation / execution DOP (default = logical processor count)"); Option Sequential() => - new Option(new[] { "--sequential" }, "Run tests sequentially", new Argument()); + new Option(new[] { "--sequential" }, "Run tests sequentially"); Option Framework() => - new Option(new[] { "--framework" }, "Precompile and use native framework", new Argument()); + new Option(new[] { "--framework" }, "Precompile and use native framework"); Option UseFramework() => - new Option(new[] { "--use-framework" }, "Use native framework (don't precompile, assume previously compiled)", new Argument()); + new Option(new[] { "--use-framework" }, "Use native framework (don't precompile, assume previously compiled)"); Option Release() => - new Option(new[] { "--release" }, "Build the tests in release mode", new Argument()); + new Option(new[] { "--release" }, "Build the tests in release mode"); Option LargeBubble() => - new Option(new[] { "--large-bubble" }, "Assume all input files as part of one version bubble", new Argument()); + new Option(new[] { "--large-bubble" }, "Assume all input files as part of one version bubble"); Option Composite() => - new Option(new[] { "--composite" }, "Compile tests in composite R2R mode", new Argument()); + new Option(new[] { "--composite" }, "Compile tests in composite R2R mode"); Option Crossgen2Parallelism() => - new Option(new[] { "--crossgen2-parallelism" }, "Max number of threads to use in Crossgen2 (default = logical processor count)", new Argument()); + new Option(new[] { "--crossgen2-parallelism" }, "Max number of threads to use in Crossgen2 (default = logical processor count)"); Option IssuesPath() => - new Option(new[] { "--issues-path", "-ip" }, "Path to issues.targets", new Argument() { Arity = ArgumentArity.ZeroOrMore }); + new Option(new[] { "--issues-path", "-ip" }, "Path to issues.targets") + { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore } }; Option CompilationTimeoutMinutes() => - new Option(new[] { "--compilation-timeout-minutes", "-ct" }, "Compilation timeout (minutes)", new Argument()); + new Option(new[] { "--compilation-timeout-minutes", "-ct" }, "Compilation timeout (minutes)"); Option ExecutionTimeoutMinutes() => - new Option(new[] { "--execution-timeout-minutes", "-et" }, "Execution timeout (minutes)", new Argument()); + new Option(new[] { "--execution-timeout-minutes", "-et" }, "Execution timeout (minutes)"); Option R2RDumpPath() => - new Option(new[] { "--r2r-dump-path", "-r2r" }, "Path to R2RDump.exe/dll", new Argument().ExistingOnly()); + new Option(new[] { "--r2r-dump-path", "-r2r" }, "Path to R2RDump.exe/dll").ExistingOnly();; Option CrossgenResponseFile() => - new Option(new [] { "--crossgen-response-file", "-rsp" }, "Response file to transpose", new Argument().ExistingOnly()); + new Option(new [] { "--crossgen-response-file", "-rsp" }, "Response file to transpose").ExistingOnly();; Option RewriteOldPath() => - new Option(new [] { "--rewrite-old-path" }, "Path substring to replace", new Argument(){ Arity = ArgumentArity.ZeroOrMore }); + new Option(new[] { "--rewrite-old-path" }, "Path substring to replace") + { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore } }; Option RewriteNewPath() => - new Option(new [] { "--rewrite-new-path" }, "Path substring to use instead", new Argument(){ Arity = ArgumentArity.ZeroOrMore }); + new Option(new[] { "--rewrite-new-path" }, "Path substring to use instead") + { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore } }; Option MeasurePerf() => - new Option(new[] { "--measure-perf" }, "Print out compilation time", new Argument()); + new Option(new[] { "--measure-perf" }, "Print out compilation time"); Option InputFileSearchString() => - new Option(new[] { "--input-file-search-string", "-input-file" }, "Search string for input files in the input directory", new Argument()); + new Option(new[] { "--input-file-search-string", "-input-file" }, "Search string for input files in the input directory"); Option GCStress() => - new Option(new[] { "--gcstress" }, "Run tests with the specified GC stress level enabled (the argument value is in hex)", new Argument()); + new Option(new[] { "--gcstress" }, "Run tests with the specified GC stress level enabled (the argument value is in hex)"); // // compile-nuget specific options // Option PackageList() => - new Option(new[] { "--package-list", "-pl" }, "Text file containing a package name on each line", new Argument().ExistingOnly()); + new Option(new[] { "--package-list", "-pl" }, "Text file containing a package name on each line").ExistingOnly();; // // compile-serp specific options // Option AspNetPath() => - new Option(new[] { "--asp-net-path", "-asp" }, "Path to SERP's ASP.NET Core folder", new Argument().ExistingOnly()); + new Option(new[] { "--asp-net-path", "-asp" }, "Path to SERP's ASP.NET Core folder").ExistingOnly(); + + Option PartialComposite() => + new Option(new[] { "--partial-composite", "-pc" }, "Add references to framework and asp.net instead of unrooted inputs"); } } } diff --git a/src/coreclr/src/tools/r2rtest/Commands/CompileSerpCommand.cs b/src/coreclr/src/tools/r2rtest/Commands/CompileSerpCommand.cs index af6b7ba8c918e..15893256577bc 100644 --- a/src/coreclr/src/tools/r2rtest/Commands/CompileSerpCommand.cs +++ b/src/coreclr/src/tools/r2rtest/Commands/CompileSerpCommand.cs @@ -110,12 +110,26 @@ public static int CompileSerpAssemblies(BuildOptions options) referenceAssemblies.Add(Path.Combine(options.CoreRootDirectory.FullName, "mscorlib.dll")); referenceAssemblies.Add(Path.Combine(options.CoreRootDirectory.FullName, "netstandard.dll")); + // + // binFiles is now all the assemblies that we want to compile (either individually or as composite) + // referenceAssemblies is all managed assemblies that are referenceable + // + + // Remove all bin files except serp.dll so they're just referenced (eventually we'll be able to compile all these in a single composite) + foreach (string item in new HashSet(File.ReadAllLines(whiteListFilePath))) + { + if (item == "Serp.dll") + continue; + + binFiles.Remove(Path.Combine(binDir, item)); + } + List fileCompilations = new List(); if (options.Composite) { string serpDll = Path.Combine(binDir, "Serp.dll"); var runner = new CpaotRunner(options, referenceAssemblies); - var compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, Path.ChangeExtension(serpDll, ".ni.dll"), referenceAssemblies)); + var compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, Path.ChangeExtension(serpDll, ".ni.dll"), binFiles)); fileCompilations.Add(compilationProcess); } else diff --git a/src/coreclr/src/tools/r2rtest/CpaotRunner.cs b/src/coreclr/src/tools/r2rtest/CpaotRunner.cs index f1f9090eec82e..128b0e20ed6ce 100644 --- a/src/coreclr/src/tools/r2rtest/CpaotRunner.cs +++ b/src/coreclr/src/tools/r2rtest/CpaotRunner.cs @@ -137,7 +137,7 @@ protected override IEnumerable BuildCommandLineArguments(IEnumerable16.0.461 - 2.0.38 + 2.0.55 - - 0.2.0-alpha.19174.3 + + $(SystemCommandLineVersion) - 1.6.0 + 1.8.1 diff --git a/src/coreclr/src/tools/r2rtest/TestExclusion.cs b/src/coreclr/src/tools/r2rtest/TestExclusion.cs index 133df0677c5de..5fefaee6d90fc 100644 --- a/src/coreclr/src/tools/r2rtest/TestExclusion.cs +++ b/src/coreclr/src/tools/r2rtest/TestExclusion.cs @@ -163,7 +163,8 @@ public static TestExclusionMap Create(BuildOptions options) Project project = new Project(); project.SetGlobalProperty("XunitTestBinBase", "*"); - project.SetGlobalProperty("BuildArch", "x64"); + project.SetGlobalProperty("TargetArchitecture", "x64"); + project.SetGlobalProperty("RuntimeFlavor", "coreclr"); // TODO: cross-OS CPAOT project.SetGlobalProperty("TargetsWindows", (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "true" : "false")); project.SetGlobalProperty("AltJitArch", "x64"); diff --git a/src/coreclr/src/utilcode/util.cpp b/src/coreclr/src/utilcode/util.cpp index f1f004d3897d5..8c980df45dea1 100644 --- a/src/coreclr/src/utilcode/util.cpp +++ b/src/coreclr/src/utilcode/util.cpp @@ -3031,58 +3031,6 @@ lDone: ; return param.fRet; } -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - -// To include definition of EXCEPTION_SOFTSO -#include "corexcep.h" - -// These functions provide limited support for corrupting exceptions -// outside the VM folder. Its limited since we don't have access to the -// throwable. -// -// These functions are also wrapped by the corresponding CEHelper -// methods in excep.cpp. - -// Given an exception code, this method returns a BOOL to indicate if the -// code belongs to a corrupting exception or not. -BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO /*=TRUE*/) -{ - LIMITED_METHOD_CONTRACT; - - // By default, assume its not corrupting - BOOL fIsCorruptedStateException = FALSE; - - if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy) == 1) - { - return fIsCorruptedStateException; - } - - // If we have been asked not to include SO in the CSE check - // and the code represent SO, then exit now. - if ((fCheckForSO == FALSE) && (dwExceptionCode == STATUS_STACK_OVERFLOW)) - { - return fIsCorruptedStateException; - } - - switch(dwExceptionCode) - { - case STATUS_ACCESS_VIOLATION: - case STATUS_STACK_OVERFLOW: - case EXCEPTION_ILLEGAL_INSTRUCTION: - case EXCEPTION_IN_PAGE_ERROR: - case EXCEPTION_INVALID_DISPOSITION: - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - case EXCEPTION_PRIV_INSTRUCTION: - case STATUS_UNWIND_CONSOLIDATE: - fIsCorruptedStateException = TRUE; - break; - } - - return fIsCorruptedStateException; -} - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - namespace Clr { namespace Util diff --git a/src/coreclr/src/vm/.vscode/c_cpp_properties.json b/src/coreclr/src/vm/.vscode/c_cpp_properties.json index a4c0ec931c99a..2a68e99359295 100644 --- a/src/coreclr/src/vm/.vscode/c_cpp_properties.json +++ b/src/coreclr/src/vm/.vscode/c_cpp_properties.json @@ -53,7 +53,6 @@ "FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION", "FEATURE_CORECLR", "FEATURE_CORESYSTEM", - "FEATURE_CORRUPTING_EXCEPTIONS", "FEATURE_DATABREAKPOINT", "FEATURE_DEFAULT_INTERFACES", "FEATURE_EVENT_TRACE=1", diff --git a/src/coreclr/src/vm/CMakeLists.txt b/src/coreclr/src/vm/CMakeLists.txt index 67a168993b28c..dedb57d041475 100644 --- a/src/coreclr/src/vm/CMakeLists.txt +++ b/src/coreclr/src/vm/CMakeLists.txt @@ -42,6 +42,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON assemblyloadcontext.cpp baseassemblyspec.cpp binder.cpp + bundle.cpp castcache.cpp callcounting.cpp ceeload.cpp @@ -106,6 +107,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON peimagelayout.cpp perfmap.cpp perfinfo.cpp + pgo.cpp precode.cpp prestub.cpp profilerdiagnosticprotocolhelper.cpp @@ -217,6 +219,7 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON peimagelayout.inl perfmap.h perfinfo.h + pgo.h precode.h rejit.h rejit.inl @@ -364,6 +367,7 @@ set(VM_SOURCES_WKS interoputil.cpp interpreter.cpp invokeutil.cpp + ipcstreamfactory.cpp jithelpers.cpp managedmdimport.cpp marshalnative.cpp @@ -483,6 +487,7 @@ set(VM_HEADERS_WKS interpreter.h interpreter.hpp invokeutil.h + ipcstreamfactory.h managedmdimport.hpp marshalnative.h methodtablebuilder.h diff --git a/src/coreclr/src/vm/appdomain.cpp b/src/coreclr/src/vm/appdomain.cpp index 95cd9174b9db2..2e39d011b49d8 100644 --- a/src/coreclr/src/vm/appdomain.cpp +++ b/src/coreclr/src/vm/appdomain.cpp @@ -1761,7 +1761,7 @@ void SystemDomain::Init() sizeof(MethodDesc), sizeof(FieldDesc), sizeof(Module) - )); + )); #endif // _DEBUG // The base domain is initialized in SystemDomain::Attach() @@ -1776,21 +1776,18 @@ void SystemDomain::Init() DWORD size = 0; - // Get the install directory so we can find mscorlib hr = GetInternalSystemDirectory(NULL, &size); if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) ThrowHR(hr); // GetInternalSystemDirectory returns a size, including the null! - WCHAR *buffer = m_SystemDirectory.OpenUnicodeBuffer(size-1); + WCHAR* buffer = m_SystemDirectory.OpenUnicodeBuffer(size - 1); IfFailThrow(GetInternalSystemDirectory(buffer, &size)); m_SystemDirectory.CloseBuffer(); m_SystemDirectory.Normalize(); // At this point m_SystemDirectory should already be canonicalized - - m_BaseLibrary.Append(m_SystemDirectory); if (!m_BaseLibrary.EndsWith(DIRECTORY_SEPARATOR_CHAR_W)) { @@ -1825,7 +1822,7 @@ void SystemDomain::Init() #ifdef _DEBUG BOOL fPause = EEConfig::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_PauseOnLoad, FALSE); - while(fPause) + while (fPause) { ClrSleepEx(20, TRUE); } diff --git a/src/coreclr/src/vm/appdomain.hpp b/src/coreclr/src/vm/appdomain.hpp index 0ca41f064ee5c..f017b42c73a2a 100644 --- a/src/coreclr/src/vm/appdomain.hpp +++ b/src/coreclr/src/vm/appdomain.hpp @@ -1110,10 +1110,10 @@ class BaseDomain return ::CreateRefcountedHandle(m_handleStore, object); } - OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference) + OBJECTHANDLE CreateNativeComWeakHandle(OBJECTREF object, IWeakReference* pComWeakReference) { WRAPPER_NO_CONTRACT; - return ::CreateWinRTWeakHandle(m_handleStore, object, pWinRTWeakReference); + return ::CreateNativeComWeakHandle(m_handleStore, object, pComWeakReference); } #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/src/vm/assemblynative.cpp b/src/coreclr/src/vm/assemblynative.cpp index b9cec28e3c5a2..0cb1dba31c3c4 100644 --- a/src/coreclr/src/vm/assemblynative.cpp +++ b/src/coreclr/src/vm/assemblynative.cpp @@ -239,7 +239,9 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext if (pwzILPath != NULL) { - pILImage = PEImage::OpenImage(pwzILPath); + pILImage = PEImage::OpenImage(pwzILPath, + MDInternalImport_Default, + Bundle::ProbeAppBundle(pwzILPath)); // Need to verify that this is a valid CLR assembly. if (!pILImage->CheckILFormat()) @@ -257,7 +259,9 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext // Form the PEImage for the NI assembly, if specified if (pwzNIPath != NULL) { - pNIImage = PEImage::OpenImage(pwzNIPath, MDInternalImport_TrustedNativeImage); + pNIImage = PEImage::OpenImage(pwzNIPath, + MDInternalImport_TrustedNativeImage, + Bundle::ProbeAppBundle(pwzNIPath)); if (pNIImage->HasReadyToRunHeader()) { diff --git a/src/coreclr/src/vm/bundle.cpp b/src/coreclr/src/vm/bundle.cpp new file mode 100644 index 0000000000000..e0d03155a56a1 --- /dev/null +++ b/src/coreclr/src/vm/bundle.cpp @@ -0,0 +1,93 @@ +// 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. +//***************************************************************************** +// Bundle.cpp +// +// Helpers to access meta-data stored in single-file bundles +// +//***************************************************************************** + +#include "common.h" +#include "bundle.h" +#include +#include +#include + +Bundle *Bundle::AppBundle = nullptr; + +const SString &BundleFileLocation::Path() const +{ + LIMITED_METHOD_CONTRACT; + + // Currently, there is only one bundle -- the bundle for the main App. + // Therefore, obtain the path from the global AppBundle. + // If there is more than one bundle in one application (ex: single file plugins) + // the BundlePath may be stored in the BundleFileLocation structure. + + _ASSERTE(IsValid()); + _ASSERTE(Bundle::AppBundle != nullptr); + + return Bundle::AppBundle->Path(); +} + +Bundle::Bundle(LPCWSTR bundlePath, BundleProbe *probe) +{ + STANDARD_VM_CONTRACT; + + _ASSERTE(probe != nullptr); + + m_path.Set(bundlePath); + m_probe = probe; + + // The bundle-base path is the directory containing the single-file bundle. + // When the Probe() function searches within the bundle, it masks out the basePath from the assembly-path (if found). + + LPCWSTR pos = wcsrchr(bundlePath, DIRECTORY_SEPARATOR_CHAR_W); + _ASSERTE(pos != nullptr); + size_t baseLen = pos - bundlePath + 1; // Include DIRECTORY_SEPARATOR_CHAR_W in m_basePath + m_basePath.Set(bundlePath, (COUNT_T)baseLen); +} + +BundleFileLocation Bundle::Probe(LPCWSTR path, bool pathIsBundleRelative) const +{ + STANDARD_VM_CONTRACT; + + BundleFileLocation loc; + + // Skip over m_base_path, if any. For example: + // Bundle.Probe("lib.dll") => m_probe("lib.dll") + // Bundle.Probe("path/to/exe/lib.dll") => m_probe("lib.dll") + // Bundle.Probe("path/to/exe/and/some/more/lib.dll") => m_probe("and/some/more/lib.dll") + + if (!pathIsBundleRelative) + { + size_t baseLen = m_basePath.GetCount(); + +#ifdef TARGET_UNIX + if (wcsncmp(m_basePath, path, baseLen) == 0) +#else + if (_wcsnicmp(m_basePath, path, baseLen) == 0) +#endif // TARGET_UNIX + { + path += baseLen; // m_basePath includes count for DIRECTORY_SEPARATOR_CHAR_W + } + else + { + // This is not a file within the bundle + return loc; + } + } + + m_probe(path, &loc.Offset, &loc.Size); + + return loc; +} + +BundleFileLocation Bundle::ProbeAppBundle(LPCWSTR path, bool pathIsBundleRelative) +{ + STANDARD_VM_CONTRACT; + + return AppIsBundle() ? AppBundle->Probe(path, pathIsBundleRelative) : BundleFileLocation::Invalid(); +} + diff --git a/src/coreclr/src/vm/castcache.cpp b/src/coreclr/src/vm/castcache.cpp index 9fb5f7a61c7e7..829d8b331e012 100644 --- a/src/coreclr/src/vm/castcache.cpp +++ b/src/coreclr/src/vm/castcache.cpp @@ -40,7 +40,7 @@ BASEARRAYREF CastCache::CreateCastCache(DWORD size) EX_CATCH { } - EX_END_CATCH(RethrowCorruptingExceptions) + EX_END_CATCH(RethrowTerminalExceptions) if (!table) { @@ -54,7 +54,7 @@ BASEARRAYREF CastCache::CreateCastCache(DWORD size) EX_CATCH { } - EX_END_CATCH(RethrowCorruptingExceptions) + EX_END_CATCH(RethrowTerminalExceptions) if (!table) { diff --git a/src/coreclr/src/vm/ceeload.cpp b/src/coreclr/src/vm/ceeload.cpp index 9b9c59449c954..acd979f6cb3cd 100644 --- a/src/coreclr/src/vm/ceeload.cpp +++ b/src/coreclr/src/vm/ceeload.cpp @@ -99,10 +99,10 @@ BOOL Module::HasNativeOrReadyToRunInlineTrackingMap() { LIMITED_METHOD_DAC_CONTRACT; #ifdef FEATURE_READYTORUN - if (IsReadyToRun() && GetReadyToRunInfo()->GetInlineTrackingMap() != NULL) - { - return TRUE; - } + if (IsReadyToRun() && GetReadyToRunInfo()->GetInlineTrackingMap() != NULL) + { + return TRUE; + } #endif return (m_pPersistentInlineTrackingMapNGen != NULL); } @@ -500,10 +500,9 @@ BOOL Module::IsPersistedObject(void *address) uint32_t Module::GetNativeMetadataAssemblyCount() { - NativeImage *compositeImage = GetCompositeNativeImage(); - if (compositeImage != NULL) + if (m_pNativeImage != NULL) { - return compositeImage->GetComponentAssemblyCount(); + return m_pNativeImage->GetManifestAssemblyCount(); } else { @@ -593,15 +592,25 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) #endif // FEATURE_COLLECTIBLE_TYPES #ifdef FEATURE_READYTORUN + m_pNativeImage = NULL; if (!HasNativeImage() && !IsResource()) { if ((m_pReadyToRunInfo = ReadyToRunInfo::Initialize(this, pamTracker)) != NULL) { - COUNT_T cMeta = 0; - if (GetFile()->GetOpenedILimage()->GetNativeManifestMetadata(&cMeta) != NULL) + m_pNativeImage = m_pReadyToRunInfo->GetNativeImage(); + if (m_pNativeImage != NULL) + { + m_NativeMetadataAssemblyRefMap = m_pNativeImage->GetManifestMetadataAssemblyRefMap(); + } + else { - // Load the native assembly import - GetNativeAssemblyImport(TRUE /* loadAllowed */); + // For composite images, manifest metadata gets loaded as part of the native image + COUNT_T cMeta = 0; + if (GetFile()->GetOpenedILimage()->GetNativeManifestMetadata(&cMeta) != NULL) + { + // Load the native assembly import + GetNativeAssemblyImport(TRUE /* loadAllowed */); + } } } } @@ -9619,7 +9628,14 @@ void Module::Fixup(DataImage *image) image->ZeroField(this, offsetof(Module, m_AssemblyRefByNameCount), sizeof(m_AssemblyRefByNameCount)); image->ZeroPointerField(this, offsetof(Module, m_AssemblyRefByNameTable)); - image->ZeroPointerField(this,offsetof(Module, m_NativeMetadataAssemblyRefMap)); +#ifdef FEATURE_READYTORUN + // For composite ready-to-run images, the manifest assembly ref map is stored in the native image + // and shared by all its component images. + if (m_pNativeImage == NULL) +#endif + { + image->ZeroPointerField(this,offsetof(Module, m_NativeMetadataAssemblyRefMap)); + } // // Fixup statics diff --git a/src/coreclr/src/vm/ceeload.h b/src/coreclr/src/vm/ceeload.h index 9c11aa4bb5c05..361937847fd8f 100644 --- a/src/coreclr/src/vm/ceeload.h +++ b/src/coreclr/src/vm/ceeload.h @@ -1615,6 +1615,7 @@ class Module #ifdef FEATURE_READYTORUN private: PTR_ReadyToRunInfo m_pReadyToRunInfo; + PTR_NativeImage m_pNativeImage; #endif private: @@ -2924,17 +2925,17 @@ class Module #endif } - NativeImage *GetCompositeNativeImage() const +#ifdef FEATURE_READYTORUN + PTR_ReadyToRunInfo GetReadyToRunInfo() const { LIMITED_METHOD_DAC_CONTRACT; - return (m_pReadyToRunInfo != NULL ? m_pReadyToRunInfo->GetNativeImage() : NULL); + return m_pReadyToRunInfo; } -#ifdef FEATURE_READYTORUN - PTR_ReadyToRunInfo GetReadyToRunInfo() const + PTR_NativeImage GetCompositeNativeImage() const { LIMITED_METHOD_DAC_CONTRACT; - return m_pReadyToRunInfo; + return m_pNativeImage; } #endif diff --git a/src/coreclr/src/vm/ceemain.cpp b/src/coreclr/src/vm/ceemain.cpp index ee67d1e20a708..f80dc4601043b 100644 --- a/src/coreclr/src/vm/ceemain.cpp +++ b/src/coreclr/src/vm/ceemain.cpp @@ -93,14 +93,14 @@ // file:threads.h#SuspendingTheRuntime and file:../../Documentation/botr/threading.md // * Garbage collection - file:gc.cpp#Overview and file:../../Documentation/botr/garbage-collection.md // * code:AppDomain - The managed version of a process. -// * Calling Into the runtime (FCALLs QCalls) file:../../Documentation/botr/mscorlib.md +// * Calling Into the runtime (FCALLs QCalls) file:../../Documentation/botr/corelib.md // * Exceptions - file:../../Documentation/botr/exceptions.md. The most important routine to start // with is code:COMPlusFrameHandler which is the routine that we hook up to get called when an unmanaged // exception happens. // * Assembly Loading file:../../Documentation/botr/type-loader.md // * Profiling file:../../Documentation/botr/profiling.md and file:../../Documentation/botr/profilability.md // * FCALLS QCALLS (calling into the runtime from managed code) -// file:../../Documentation/botr/mscorlib.md +// file:../../Documentation/botr/corelib.md // * Event Tracing for Windows // * file:../inc/eventtrace.h#EventTracing - // * This is the main file dealing with event tracing in CLR @@ -164,6 +164,7 @@ #include "threadsuspend.h" #include "disassembler.h" #include "jithost.h" +#include "pgo.h" #ifndef TARGET_UNIX #include "dwreport.h" @@ -719,6 +720,10 @@ void EEStartupHelper() PerfMap::Initialize(); #endif +#ifdef FEATURE_PGO + PgoManager::Initialize(); +#endif + STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Starting==================="); #ifndef CROSSGEN_COMPILE @@ -836,8 +841,6 @@ void EEStartupHelper() VirtualCallStubManager::InitStatic(); - GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure); - #endif // CROSSGEN_COMPILE // Setup the domains. Threads are started in a default domain. @@ -1315,6 +1318,10 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) PerfMap::Destroy(); #endif +#ifdef FEATURE_PGO + PgoManager::Shutdown(); +#endif + { // If we're doing basic block profiling, we need to write the log files to disk. static BOOL fIBCLoggingDone = FALSE; diff --git a/src/coreclr/src/vm/class.cpp b/src/coreclr/src/vm/class.cpp index b0976b4ef7b75..d9357e85b06a9 100644 --- a/src/coreclr/src/vm/class.cpp +++ b/src/coreclr/src/vm/class.cpp @@ -1195,10 +1195,6 @@ int MethodTable::GetVectorSize() { vectorSize = 16; } - else if (strcmp(className, "Vector256`1") == 0) - { - vectorSize = 32; - } else if (strcmp(className, "Vector64`1") == 0) { vectorSize = 8; diff --git a/src/coreclr/src/vm/clrex.h b/src/coreclr/src/vm/clrex.h index 16b32574f5a39..3a570a5480f26 100644 --- a/src/coreclr/src/vm/clrex.h +++ b/src/coreclr/src/vm/clrex.h @@ -735,7 +735,7 @@ class EEFileLoadException : public EEException // { // EX_RETHROW() // } -// EX_END_CATCH(RethrowTerminalExceptions or RethrowCorruptingExceptions) +// EX_END_CATCH(RethrowTerminalExceptions) // -------------------------------------------------------------------------------------------------------- // In DAC builds, we don't want to override the normal utilcode exception handling. @@ -746,62 +746,6 @@ class EEFileLoadException : public EEException #define GET_THROWABLE() CLRException::GetThrowableFromException(GET_EXCEPTION()) -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - -// For the VM folder, we redefine SET_CE_RETHROW_FLAG_FOR_EX_CATCH to also check the -// corruption severity when deciding whether to rethrow them or not. -// -// We also check the global override flag incase it has been set to force pre-V4 behaviour. -// -// Doing the checks for "__fCaughtSO" and "__fCaughtNonCxx" will ensure that we check for -// corruption severity only if the last exception was a managed exception that could have been rethrown in the VM. -// When "(__fCaughtSO == FALSE) && (__fCaughtNonCxx == true)" is true, it implies we are dealing with a managed exception -// inside the VM that is represented by the CLRLastThrownObjectException instance (see EX_TRY/EX_CATCH implementation in VM -// folder to see how CLRLastThrownObjectException is used). -// -// This macro also supports the following scenarios: -// -// Scenario 1 -// ---------- -// -// [VM1] -> [VM2] -> -// -// If a managed exception is swallowed by an EX_CATCH in native function VM2, which then returns back -// to native function VM1 that throws, for example, a VM C++ exception, an EX_CATCH(RethrowCorruptingExceptions) -// in VM1 that catches the C++ exception will not rethrow since the last exception was not a managed CSE but -// a C++ exception. -// -// A variation of this is for VM2 to return back in VM1, which calls VM3 that throws a VM C++ exception that -// reaches VM1's EX_CATCH(RethrowCorruptingExceptions). VM1 shouldn't be rethrowing the exception in such a case. -// -// Scenario 2 -// ---------- -// -// [VM1 - RethrowCSE] -> [VM2 - RethrowCSE] -> [VM3 - RethrowCSE] -> -// -// When managed code throws a CSE (e.g. TargetInvocationException flagged as CSE), [VM3] will rethrow it and we will -// enter EX_CATCH in VM2 which is supposed to rethrow it as well. But if the implementation of EX_CATCH in VM2 throws -// another VM C++ exception (e.g. EEFileLoadException) *before* rethrow policy is applied, control will reach EX_CATCH -// in VM1 that *shouldn't* rethrow (even though it has RethrowCSE as the policy) since the last exception was a VM C++ -// exception. -// -// Scenario 3 -// ---------- -// -// This is about VM throwing a managed exception that gets handled either within the VM, with or without CLR's managed code -// exception handler coming into the picture. -// -// This is explained in detail (alongwith relevant changes) in the implementation of RaiseTheException (in excep.cpp). - -#undef SET_CE_RETHROW_FLAG_FOR_EX_CATCH -#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) (((expr) == TRUE) && \ - (g_pConfig->LegacyCorruptedStateExceptionsPolicy() == false) && \ - (CEHelper::IsProcessCorruptedStateException(GetCurrentExceptionCode(), FALSE) || \ - (!__state.DidCatchCxx() && \ - CEHelper::IsLastActiveExceptionCorrupting(TRUE)))) - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - #undef EX_TRY #define EX_TRY \ EX_TRY_CUSTOM(CLRException::HandlerState, (::GetThreadNULLOk()), CLRLastThrownObjectException) @@ -1002,25 +946,6 @@ LONG CLRNoCatchHandler(EXCEPTION_POINTERS* pExceptionInfo, PVOID pv); } \ } \ -// This macro should be used at the entry points (e.g. COM interop boundaries) -// where CE's are not expected to get swallowed. -#define END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS_EX(fCond) \ - } \ - EX_CATCH \ - { \ - *__phr = GET_EXCEPTION()->GetHR(); \ - } \ - EX_END_CATCH(RethrowCorruptingExceptionsEx(fCond)); \ - } \ - } \ - -// This macro should be used at the entry points (e.g. COM interop boundaries) -// where CE's are not expected to get swallowed. -#define END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS \ - END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS_EX(TRUE) - - - //============================================================================== // --------------------------------------------------------------------------- diff --git a/src/coreclr/src/vm/comcallablewrapper.cpp b/src/coreclr/src/vm/comcallablewrapper.cpp index c621eeb74304d..583d52d1cf38d 100644 --- a/src/coreclr/src/vm/comcallablewrapper.cpp +++ b/src/coreclr/src/vm/comcallablewrapper.cpp @@ -3678,8 +3678,7 @@ IDispatch* ComCallWrapper::GetIDispatchIP() CorIfaceAttr ifaceType = hndDefItfClass.GetMethodTable()->GetComInterfaceType(); if (IsDispatchBasedItf(ifaceType)) { - RETURN (IDispatch*)GetComIPFromCCW(this, GUID_NULL, hndDefItfClass.GetMethodTable(), - GetComIPFromCCW::SuppressSecurityCheck); + RETURN (IDispatch*)GetComIPFromCCW(this, GUID_NULL, hndDefItfClass.GetMethodTable()); } else { diff --git a/src/coreclr/src/vm/comcallablewrapper.h b/src/coreclr/src/vm/comcallablewrapper.h index 51b6f88d87b86..9ef02ec63e384 100644 --- a/src/coreclr/src/vm/comcallablewrapper.h +++ b/src/coreclr/src/vm/comcallablewrapper.h @@ -957,8 +957,7 @@ struct GetComIPFromCCW { None = 0, CheckVisibility = 1, - SuppressSecurityCheck = 2, - SuppressCustomizedQueryInterface = 4 + SuppressCustomizedQueryInterface = 2 }; }; diff --git a/src/coreclr/src/vm/comdelegate.cpp b/src/coreclr/src/vm/comdelegate.cpp index 20a724bf0a908..e2b45fb108d1d 100644 --- a/src/coreclr/src/vm/comdelegate.cpp +++ b/src/coreclr/src/vm/comdelegate.cpp @@ -3282,44 +3282,7 @@ static void InvokeUnhandledSwallowing(OBJECTREF *pDelegate, EX_TRY { -#if defined(FEATURE_CORRUPTING_EXCEPTIONS) - BOOL fCanMethodHandleException = g_pConfig->LegacyCorruptedStateExceptionsPolicy(); - if (!fCanMethodHandleException) - { - // CSE policy has not been overridden - proceed with our checks. - // - // Notifications for CSE are only delivered if the delegate target follows CSE rules. - // So, get the corruption severity of the active exception that has gone unhandled. - // - // By Default, assume that the active exception is not corrupting. - CorruptionSeverity severity = NotCorrupting; - Thread *pCurThread = GetThread(); - _ASSERTE(pCurThread != NULL); - ThreadExceptionState *pExState = pCurThread->GetExceptionState(); - if (pExState->IsExceptionInProgress()) - { - // If an exception is active, it implies we have a tracker for it. - // Hence, get the corruption severity from the active exception tracker. - severity = pExState->GetCurrentExceptionTracker()->GetCorruptionSeverity(); - _ASSERTE(severity > NotSet); - } - - // Notifications are delivered based upon corruption severity of the exception - fCanMethodHandleException = ExceptionNotifications::CanDelegateBeInvokedForException(pDelegate, severity); - if (!fCanMethodHandleException) - { - LOG((LF_EH, LL_INFO100, "InvokeUnhandledSwallowing: ADUEN Delegate cannot be invoked for corruption severity %d\n", - severity)); - } - } - - if (fCanMethodHandleException) -#endif // defined(FEATURE_CORRUPTING_EXCEPTIONS) - { - // We've already exercised the prestub on this delegate's COMDelegate::GetMethodDesc, - // as part of wiring up a reliable event sink. Deliver the notification. - ExceptionNotifications::DeliverExceptionNotification(UnhandledExceptionHandler, pDelegate, pDomain, pEventArgs); - } + ExceptionNotifications::DeliverExceptionNotification(UnhandledExceptionHandler, pDelegate, pDomain, pEventArgs); } EX_CATCH { diff --git a/src/coreclr/src/vm/commodule.cpp b/src/coreclr/src/vm/commodule.cpp index 3a54696306675..51160cf2b896c 100644 --- a/src/coreclr/src/vm/commodule.cpp +++ b/src/coreclr/src/vm/commodule.cpp @@ -888,7 +888,7 @@ HINSTANCE QCALLTYPE COMModule::GetHINSTANCE(QCall::ModuleHandle pModule) BEGIN_QCALL; - // This returns the base address - this will work for either HMODULE or HCORMODULES + // This returns the base address // Other modules should have zero base PEFile *pPEFile = pModule->GetFile(); if (!pPEFile->IsDynamic() && !pPEFile->IsResource()) @@ -1093,4 +1093,3 @@ FCIMPL0(void*, COMPunkSafeHandle::nGetDReleaseTarget) } FCIMPLEND - diff --git a/src/coreclr/src/vm/comutilnative.cpp b/src/coreclr/src/vm/comutilnative.cpp index 0205d70691396..f66009b7bcb40 100644 --- a/src/coreclr/src/vm/comutilnative.cpp +++ b/src/coreclr/src/vm/comutilnative.cpp @@ -671,17 +671,12 @@ void QCALLTYPE Buffer::MemMove(void *dst, void *src, size_t length) // // GCInterface // - -UINT64 GCInterface::m_ulMemPressure = 0; -UINT64 GCInterface::m_ulThreshold = MIN_GC_MEMORYPRESSURE_THRESHOLD; INT32 GCInterface::m_gc_counts[3] = {0,0,0}; -CrstStatic GCInterface::m_MemoryPressureLock; - -UINT64 GCInterface::m_addPressure[NEW_PRESSURE_COUNT] = {0, 0, 0, 0}; // history of memory pressure additions -UINT64 GCInterface::m_remPressure[NEW_PRESSURE_COUNT] = {0, 0, 0, 0}; // history of memory pressure removals +UINT64 GCInterface::m_addPressure[MEM_PRESSURE_COUNT] = {0, 0, 0, 0}; // history of memory pressure additions +UINT64 GCInterface::m_remPressure[MEM_PRESSURE_COUNT] = {0, 0, 0, 0}; // history of memory pressure removals // incremented after a gen2 GC has been detected, -// (m_iteration % NEW_PRESSURE_COUNT) is used as an index into m_addPressure and m_remPressure +// (m_iteration % MEM_PRESSURE_COUNT) is used as an index into m_addPressure and m_remPressure UINT GCInterface::m_iteration = 0; FCIMPL6(void, GCInterface::GetMemoryInfo, UINT64* highMemLoadThreshold, UINT64* totalAvailableMemoryBytes, UINT64* lastRecordedMemLoadBytes, UINT32* lastRecordedMemLoadPct, size_t* lastRecordedHeapSizeBytes, size_t* lastRecordedFragmentationBytes) @@ -917,7 +912,7 @@ FCIMPL1(int, GCInterface::GetGenerationWR, LPVOID handle) OBJECTREF temp; temp = ObjectFromHandle((OBJECTHANDLE) handle); if (temp == NULL) - COMPlusThrowArgumentNull(W("weak handle")); + COMPlusThrowArgumentNull(W("wo")); iRetVal = (INT32)GCHeapUtilities::GetGCHeap()->WhichGeneration(OBJECTREFToObject(temp)); @@ -1273,79 +1268,11 @@ void QCALLTYPE GCInterface::_AddMemoryPressure(UINT64 bytesAllocated) { QCALL_CONTRACT; - // AddMemoryPressure could cause a GC, so we need a frame BEGIN_QCALL; AddMemoryPressure(bytesAllocated); END_QCALL; } -void GCInterface::AddMemoryPressure(UINT64 bytesAllocated) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - SendEtwAddMemoryPressureEvent(bytesAllocated); - - UINT64 newMemValue = InterlockedAdd(&m_ulMemPressure, bytesAllocated); - - if (newMemValue > m_ulThreshold) - { - INT32 gen_collect = 0; - { - GCX_PREEMP(); - CrstHolder holder(&m_MemoryPressureLock); - - // to avoid collecting too often, take the max threshold of the linear and geometric growth - // heuristics. - UINT64 addMethod; - UINT64 multMethod; - UINT64 bytesAllocatedMax = (UINT64_MAX - m_ulThreshold) / 8; - - if (bytesAllocated >= bytesAllocatedMax) // overflow check - { - addMethod = UINT64_MAX; - } - else - { - addMethod = m_ulThreshold + bytesAllocated * 8; - } - - multMethod = newMemValue + newMemValue / 10; - if (multMethod < newMemValue) // overflow check - { - multMethod = UINT64_MAX; - } - - m_ulThreshold = (addMethod > multMethod) ? addMethod : multMethod; - for (int i = 0; i <= 1; i++) - { - if ((GCHeapUtilities::GetGCHeap()->CollectionCount(i) / RELATIVE_GC_RATIO) > GCHeapUtilities::GetGCHeap()->CollectionCount(i + 1)) - { - gen_collect = i + 1; - break; - } - } - } - - PREFIX_ASSUME(gen_collect <= 2); - - if ((gen_collect == 0) || (m_gc_counts[gen_collect] == GCHeapUtilities::GetGCHeap()->CollectionCount(gen_collect))) - { - GarbageCollectModeAny(gen_collect); - } - - for (int i = 0; i < 3; i++) - { - m_gc_counts [i] = GCHeapUtilities::GetGCHeap()->CollectionCount(i); - } - } -} - #ifdef HOST_64BIT const unsigned MIN_MEMORYPRESSURE_BUDGET = 4 * 1024 * 1024; // 4 MB #else // HOST_64BIT @@ -1371,17 +1298,16 @@ void GCInterface::CheckCollectionCount() m_iteration++; - UINT p = m_iteration % NEW_PRESSURE_COUNT; + UINT p = m_iteration % MEM_PRESSURE_COUNT; m_addPressure[p] = 0; // new pressure will be accumulated here m_remPressure[p] = 0; } } - -// New AddMemoryPressure implementation (used by RCW and the CLRServicesImpl class) +// AddMemoryPressure implementation // -// 1. Less sensitive than the original implementation (start budget 3 MB) +// 1. Start budget - MIN_MEMORYPRESSURE_BUDGET // 2. Focuses more on newly added memory pressure // 3. Budget adjusted by effectiveness of last 3 triggered GC (add / remove ratio, max 10x) // 4. Budget maxed with 30% of current managed GC size @@ -1395,7 +1321,7 @@ void GCInterface::CheckCollectionCount() // and would be calculated based on historic data using standard exponential approximation: // Xnew = UMDeath/UMTotal * 0.5 + Xprev // -void GCInterface::NewAddMemoryPressure(UINT64 bytesAllocated) +void GCInterface::AddMemoryPressure(UINT64 bytesAllocated) { CONTRACTL { @@ -1407,11 +1333,11 @@ void GCInterface::NewAddMemoryPressure(UINT64 bytesAllocated) CheckCollectionCount(); - UINT p = m_iteration % NEW_PRESSURE_COUNT; + UINT p = m_iteration % MEM_PRESSURE_COUNT; UINT64 newMemValue = InterlockedAdd(&m_addPressure[p], bytesAllocated); - static_assert(NEW_PRESSURE_COUNT == 4, "NewAddMemoryPressure contains unrolled loops which depend on NEW_PRESSURE_COUNT"); + static_assert(MEM_PRESSURE_COUNT == 4, "AddMemoryPressure contains unrolled loops which depend on MEM_PRESSURE_COUNT"); UINT64 add = m_addPressure[0] + m_addPressure[1] + m_addPressure[2] + m_addPressure[3] - m_addPressure[p]; UINT64 rem = m_remPressure[0] + m_remPressure[1] + m_remPressure[2] + m_remPressure[3] - m_remPressure[p]; @@ -1425,7 +1351,7 @@ void GCInterface::NewAddMemoryPressure(UINT64 bytesAllocated) { UINT64 budget = MIN_MEMORYPRESSURE_BUDGET; - if (m_iteration >= NEW_PRESSURE_COUNT) // wait until we have enough data points + if (m_iteration >= MEM_PRESSURE_COUNT) // wait until we have enough data points { // Adjust according to effectiveness of GC // Scale budget according to past m_addPressure / m_remPressure ratio @@ -1489,54 +1415,9 @@ void GCInterface::RemoveMemoryPressure(UINT64 bytesAllocated) } CONTRACTL_END; - SendEtwRemoveMemoryPressureEvent(bytesAllocated); - - UINT64 newMemValue = InterlockedSub(&m_ulMemPressure, bytesAllocated); - UINT64 new_th; - UINT64 bytesAllocatedMax = (m_ulThreshold / 4); - UINT64 addMethod; - UINT64 multMethod = (m_ulThreshold - m_ulThreshold / 20); // can never underflow - if (bytesAllocated >= bytesAllocatedMax) // protect against underflow - { - m_ulThreshold = MIN_GC_MEMORYPRESSURE_THRESHOLD; - return; - } - else - { - addMethod = m_ulThreshold - bytesAllocated * 4; - } - - new_th = (addMethod < multMethod) ? addMethod : multMethod; - - if (newMemValue <= new_th) - { - GCX_PREEMP(); - CrstHolder holder(&m_MemoryPressureLock); - if (new_th > MIN_GC_MEMORYPRESSURE_THRESHOLD) - m_ulThreshold = new_th; - else - m_ulThreshold = MIN_GC_MEMORYPRESSURE_THRESHOLD; - - for (int i = 0; i < 3; i++) - { - m_gc_counts [i] = GCHeapUtilities::GetGCHeap()->CollectionCount(i); - } - } -} - -void GCInterface::NewRemoveMemoryPressure(UINT64 bytesAllocated) -{ - CONTRACTL - { - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - CheckCollectionCount(); - UINT p = m_iteration % NEW_PRESSURE_COUNT; + UINT p = m_iteration % MEM_PRESSURE_COUNT; SendEtwRemoveMemoryPressureEvent(bytesAllocated); diff --git a/src/coreclr/src/vm/comutilnative.h b/src/coreclr/src/vm/comutilnative.h index fa3f0fdcb2ada..a1a18c45afc5a 100644 --- a/src/coreclr/src/vm/comutilnative.h +++ b/src/coreclr/src/vm/comutilnative.h @@ -74,25 +74,17 @@ class Buffer static void QCALLTYPE Clear(void *dst, size_t length); }; -#define MIN_GC_MEMORYPRESSURE_THRESHOLD 100000 -#define RELATIVE_GC_RATIO 8 - -const UINT NEW_PRESSURE_COUNT = 4; +const UINT MEM_PRESSURE_COUNT = 4; class GCInterface { private: - - static UINT64 m_ulMemPressure; - static UINT64 m_ulThreshold; static INT32 m_gc_counts[3]; - static UINT64 m_addPressure[NEW_PRESSURE_COUNT]; - static UINT64 m_remPressure[NEW_PRESSURE_COUNT]; + static UINT64 m_addPressure[MEM_PRESSURE_COUNT]; + static UINT64 m_remPressure[MEM_PRESSURE_COUNT]; static UINT m_iteration; public: - static CrstStatic m_MemoryPressureLock; - static FORCEINLINE UINT64 InterlockedAdd(UINT64 *pAugend, UINT64 addend); static FORCEINLINE UINT64 InterlockedSub(UINT64 *pMinuend, UINT64 subtrahend); @@ -150,15 +142,12 @@ class GCInterface { static void QCALLTYPE _RemoveMemoryPressure(UINT64 bytesAllocated); - static void RemoveMemoryPressure(UINT64 bytesAllocated); - static void AddMemoryPressure(UINT64 bytesAllocated); NOINLINE static void SendEtwRemoveMemoryPressureEvent(UINT64 bytesAllocated); static void SendEtwAddMemoryPressureEvent(UINT64 bytesAllocated); - // New less sensitive implementation of Add/RemoveMemoryPressure: static void CheckCollectionCount(); - static void NewRemoveMemoryPressure(UINT64 bytesAllocated); - static void NewAddMemoryPressure(UINT64 bytesAllocated); + static void RemoveMemoryPressure(UINT64 bytesAllocated); + static void AddMemoryPressure(UINT64 bytesAllocated); private: // Out-of-line helper to avoid EH prolog/epilog in functions that otherwise don't throw. diff --git a/src/coreclr/src/vm/coreassemblyspec.cpp b/src/coreclr/src/vm/coreassemblyspec.cpp index 99ae244064758..d2fc56ad064d9 100644 --- a/src/coreclr/src/vm/coreassemblyspec.cpp +++ b/src/coreclr/src/vm/coreassemblyspec.cpp @@ -19,7 +19,7 @@ #include "domainfile.h" #include "holder.h" #include "../binder/inc/assemblybinder.hpp" - +#include "bundle.h" #include "strongnameinternal.h" #include "strongnameholders.h" @@ -174,10 +174,11 @@ VOID AssemblySpec::Bind(AppDomain *pAppDomain, } -STDAPI BinderAcquirePEImage(LPCWSTR wszAssemblyPath, - PEImage **ppPEImage, - PEImage **ppNativeImage, - BOOL fExplicitBindToNativeImage) +STDAPI BinderAcquirePEImage(LPCWSTR wszAssemblyPath, + PEImage **ppPEImage, + PEImage **ppNativeImage, + BOOL fExplicitBindToNativeImage, + BundleFileLocation bundleFileLocation) { HRESULT hr = S_OK; @@ -187,12 +188,13 @@ STDAPI BinderAcquirePEImage(LPCWSTR wszAssemblyPath, { PEImageHolder pImage = NULL; PEImageHolder pNativeImage = NULL; + AppDomain* pDomain = ::GetAppDomain(); // DEAD ? ? #ifdef FEATURE_PREJIT // fExplicitBindToNativeImage is set on Phone when we bind to a list of native images and have no IL on device for an assembly if (fExplicitBindToNativeImage) { - pNativeImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_TrustedNativeImage); + pNativeImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_TrustedNativeImage, bundleFileLocation); // Make sure that the IL image can be opened if the native image is not available. hr=pNativeImage->TryOpenFile(); @@ -204,7 +206,7 @@ STDAPI BinderAcquirePEImage(LPCWSTR wszAssemblyPath, else #endif { - pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default); + pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default, bundleFileLocation); // Make sure that the IL image can be opened if the native image is not available. hr=pImage->TryOpenFile(); diff --git a/src/coreclr/src/vm/crossgen/CMakeLists.txt b/src/coreclr/src/vm/crossgen/CMakeLists.txt index 77f46314b9bed..b532a9ecdc3cb 100644 --- a/src/coreclr/src/vm/crossgen/CMakeLists.txt +++ b/src/coreclr/src/vm/crossgen/CMakeLists.txt @@ -6,6 +6,7 @@ set(VM_CROSSGEN_SOURCES ../assemblyspec.cpp ../baseassemblyspec.cpp ../binder.cpp + ../bundle.cpp ../castcache.cpp ../ceeload.cpp ../ceemain.cpp diff --git a/src/coreclr/src/vm/diagnosticserver.cpp b/src/coreclr/src/vm/diagnosticserver.cpp index 9fbde4a797da9..9879c7b1e35dc 100644 --- a/src/coreclr/src/vm/diagnosticserver.cpp +++ b/src/coreclr/src/vm/diagnosticserver.cpp @@ -4,6 +4,7 @@ #include "common.h" #include "diagnosticserver.h" +#include "ipcstreamfactory.h" #include "eventpipeprotocolhelper.h" #include "dumpdiagnosticprotocolhelper.h" #include "profilerdiagnosticprotocolhelper.h" @@ -19,7 +20,6 @@ #ifdef FEATURE_PERFTRACING -IpcStream::DiagnosticsIpc *DiagnosticServer::s_pIpc = nullptr; Volatile DiagnosticServer::s_shuttingDown(false); DWORD WINAPI DiagnosticServer::DiagnosticsServerThread(LPVOID) @@ -29,11 +29,11 @@ DWORD WINAPI DiagnosticServer::DiagnosticsServerThread(LPVOID) NOTHROW; GC_TRIGGERS; MODE_PREEMPTIVE; - PRECONDITION(s_pIpc != nullptr); + PRECONDITION(IpcStreamFactory::HasActiveConnections()); } CONTRACTL_END; - if (s_pIpc == nullptr) + if (!IpcStreamFactory::HasActiveConnections()) { STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_ERROR, "Diagnostics IPC listener was undefined\n"); return 1; @@ -47,8 +47,7 @@ DWORD WINAPI DiagnosticServer::DiagnosticsServerThread(LPVOID) { while (!s_shuttingDown) { - // FIXME: Ideally this would be something like a std::shared_ptr - IpcStream *pStream = s_pIpc->Accept(LoggingCallback); + IpcStream *pStream = IpcStreamFactory::GetNextAvailableStream(LoggingCallback); if (pStream == nullptr) continue; @@ -134,7 +133,7 @@ bool DiagnosticServer::Initialize() }; NewArrayHolder address = nullptr; - CLRConfigStringHolder wAddress = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DOTNET_DiagnosticsServerAddress); + CLRConfigStringHolder wAddress = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DOTNET_DiagnosticsMonitorAddress); int nCharactersWritten = 0; if (wAddress != nullptr) { @@ -145,12 +144,14 @@ bool DiagnosticServer::Initialize() nCharactersWritten = WideCharToMultiByte(CP_UTF8, 0, wAddress, -1, address, nCharactersWritten, NULL, NULL); assert(nCharactersWritten != 0); } + + // Create the client mode connection + fSuccess &= IpcStreamFactory::CreateClient(address, ErrorCallback); } - // TODO: Should we handle/assert that (s_pIpc == nullptr)? - s_pIpc = IpcStream::DiagnosticsIpc::Create(address, ErrorCallback); + fSuccess &= IpcStreamFactory::CreateServer(nullptr, ErrorCallback); - if (s_pIpc != nullptr) + if (IpcStreamFactory::HasActiveConnections()) { #ifdef FEATURE_AUTO_TRACE auto_trace_init(); @@ -161,14 +162,13 @@ bool DiagnosticServer::Initialize() nullptr, // no security attribute 0, // default stack size DiagnosticsServerThread, // thread proc - (LPVOID)s_pIpc, // thread parameter + nullptr, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if (hServerThread == NULL) { - delete s_pIpc; - s_pIpc = nullptr; + IpcStreamFactory::CloseConnections(); // Failed to create IPC thread. STRESS_LOG1( @@ -213,7 +213,7 @@ bool DiagnosticServer::Shutdown() EX_TRY { - if (s_pIpc != nullptr) + if (IpcStreamFactory::HasActiveConnections()) { auto ErrorCallback = [](const char *szMessage, uint32_t code) { STRESS_LOG2( @@ -223,7 +223,8 @@ bool DiagnosticServer::Shutdown() code, // data1 szMessage); // data2 }; - s_pIpc->Close(ErrorCallback); // This will break the accept waiting for client connection. + + IpcStreamFactory::Shutdown(ErrorCallback); } fSuccess = true; } diff --git a/src/coreclr/src/vm/diagnosticserver.h b/src/coreclr/src/vm/diagnosticserver.h index 393fbda0bd9ae..a5b8f07f7847b 100644 --- a/src/coreclr/src/vm/diagnosticserver.h +++ b/src/coreclr/src/vm/diagnosticserver.h @@ -46,7 +46,6 @@ class DiagnosticServer final static DWORD WINAPI DiagnosticsServerThread(LPVOID lpThreadParameter); private: - static IpcStream::DiagnosticsIpc *s_pIpc; static Volatile s_shuttingDown; }; diff --git a/src/coreclr/src/vm/diagnosticsprotocol.h b/src/coreclr/src/vm/diagnosticsprotocol.h index bbc622a6411a3..e6bd3d4e89a8d 100644 --- a/src/coreclr/src/vm/diagnosticsprotocol.h +++ b/src/coreclr/src/vm/diagnosticsprotocol.h @@ -103,6 +103,60 @@ namespace DiagnosticsIpc const MagicVersion DotnetIpcMagic_V1 = { "DOTNET_IPC_V1" }; + /** + * ==ADVERTISE PROTOCOL== + * Before standard IPC Protocol communication can occur on a client-mode connection + * the runtime must advertise itself over the connection. ALL SUBSEQUENT COMMUNICATION + * IS STANDARD DIAGNOSTICS IPC PROTOCOL COMMUNICATION. + * + * See spec in: dotnet/diagnostics@documentation/design-docs/ipc-spec.md + * + * The flow for Advertise is a one-way burst of 24 bytes consisting of + * 8 bytes - "ADVR_V1\0" (ASCII chars + null byte) + * 16 bytes - random 128 bit number cookie (little-endian) + * 8 bytes - PID (little-endian) + * 2 bytes - unused 2 byte field for futureproofing + */ + + const uint8_t AdvertiseMagic_V1[8] = "ADVR_V1"; + + const uint32_t AdvertiseSize = 34; + + static GUID AdvertiseCookie_V1 = GUID_NULL; + + inline GUID GetAdvertiseCookie_V1() + { + if (AdvertiseCookie_V1 == GUID_NULL) + { + CoCreateGuid(&AdvertiseCookie_V1); + } + + return AdvertiseCookie_V1; + } + + inline bool SendIpcAdvertise_V1(IpcStream *pStream) + { + uint8_t advertiseBuffer[DiagnosticsIpc::AdvertiseSize]; + GUID cookie = GetAdvertiseCookie_V1(); + uint64_t pid = GetCurrentProcessId(); + + uint64_t *buffer = (uint64_t*)advertiseBuffer; + buffer[0] = *(uint64_t*)AdvertiseMagic_V1; + buffer[1] = (((uint64_t)VAL32(cookie.Data1) << 32) | ((uint64_t)VAL16(cookie.Data2) << 16) | VAL16((uint64_t)cookie.Data3)); + buffer[2] = *(uint64_t*)cookie.Data4; + buffer[3] = VAL64(pid); + + // zero out unused field + ((uint16_t*)advertiseBuffer)[16] = VAL16(0); + + uint32_t nBytesWritten = 0; + if (!pStream->Write(advertiseBuffer, sizeof(advertiseBuffer), nBytesWritten, 100 /* ms */)) + return false; + + _ASSERTE(nBytesWritten == sizeof(advertiseBuffer)); + return nBytesWritten == sizeof(advertiseBuffer); + } + const IpcHeader GenericSuccessHeader = { { DotnetIpcMagic_V1 }, diff --git a/src/coreclr/src/vm/dispatchinfo.cpp b/src/coreclr/src/vm/dispatchinfo.cpp index 8da1151b93c05..dca9108f1d853 100644 --- a/src/coreclr/src/vm/dispatchinfo.cpp +++ b/src/coreclr/src/vm/dispatchinfo.cpp @@ -2193,10 +2193,8 @@ HRESULT DispatchInfo::InvokeMember(SimpleComCallWrapper *pSimpleWrap, DISPID id, EX_CATCH { pThrowable = GET_THROWABLE(); - - // RethrowCorruptingExceptionsEx, in EX_END_CATCH below, will ensure that CEs are rethrown. } - EX_END_CATCH(RethrowCorruptingExceptionsEx(!CEHelper::CanIDispatchTargetHandleException())) + EX_END_CATCH(RethrowTerminalExceptions) catchFrame.Pop(); if (pThrowable != NULL) diff --git a/src/coreclr/src/vm/dllimport.cpp b/src/coreclr/src/vm/dllimport.cpp index b2f1ee1f94e8d..99a63ac3f5b11 100644 --- a/src/coreclr/src/vm/dllimport.cpp +++ b/src/coreclr/src/vm/dllimport.cpp @@ -4797,7 +4797,7 @@ void NDirect::PopulateNDirectMethodDesc(NDirectMethodDesc* pNMD, PInvokeStaticSi if (callConv == pmCallConvThiscall) ndirectflags |= NDirectMethodDesc::kThisCall; - if (pNMD->GetLoaderModule()->IsSystem() && (strcmp(szLibName, "QCall") == 0 || strcmp(szLibName, "libSystem.Globalization.Native") == 0)) + if (pNMD->GetLoaderModule()->IsSystem() && strcmp(szLibName, "QCall") == 0) { ndirectflags |= NDirectMethodDesc::kIsQCall; } diff --git a/src/coreclr/src/vm/dwbucketmanager.hpp b/src/coreclr/src/vm/dwbucketmanager.hpp index 535adb3eb5d75..eb7beac884d2f 100644 --- a/src/coreclr/src/vm/dwbucketmanager.hpp +++ b/src/coreclr/src/vm/dwbucketmanager.hpp @@ -431,7 +431,7 @@ void BaseBucketParamsManager::PopulateBucketParameter(BucketParameterIndex param CONTRACTL { NOTHROW; - GC_NOTRIGGER; + GC_TRIGGERS; MODE_ANY; } CONTRACTL_END; @@ -452,7 +452,7 @@ void BaseBucketParamsManager::GetAppName(__out_ecount(maxLength) WCHAR* targetPa { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -475,8 +475,8 @@ void BaseBucketParamsManager::GetAppVersion(__out_ecount(maxLength) WCHAR* targe CONTRACTL { NOTHROW; - GC_NOTRIGGER; - MODE_ANY; + GC_TRIGGERS; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -511,7 +511,7 @@ void BaseBucketParamsManager::GetAppTimeStamp(__out_ecount(maxLength) WCHAR* tar { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -543,7 +543,7 @@ void BaseBucketParamsManager::GetModuleName(__out_ecount(maxLength) WCHAR* targe { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -632,8 +632,8 @@ void BaseBucketParamsManager::GetModuleVersion(__out_ecount(maxLength) WCHAR* ta CONTRACTL { NOTHROW; - GC_NOTRIGGER; - MODE_ANY; + GC_TRIGGERS; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -689,7 +689,7 @@ void BaseBucketParamsManager::GetModuleTimeStamp(__out_ecount(maxLength) WCHAR* { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -742,7 +742,7 @@ void BaseBucketParamsManager::GetMethodDef(__out_ecount(maxLength) WCHAR* target { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -767,7 +767,7 @@ void BaseBucketParamsManager::GetIlOffset(__out_ecount(maxLength) WCHAR* targetP { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -786,7 +786,7 @@ void BaseBucketParamsManager::GetExceptionName(__out_ecount(maxLength) WCHAR* ta { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -954,8 +954,8 @@ bool BaseBucketParamsManager::GetFileVersionInfoForModule(Module* pModule, USHOR CONTRACTL { NOTHROW; - GC_NOTRIGGER; - MODE_ANY; + GC_TRIGGERS; + MODE_PREEMPTIVE; PRECONDITION(pModule != NULL); } CONTRACTL_END; @@ -1215,11 +1215,14 @@ void CLR20r3BucketParamsManager::PopulateBucketParameters() CONTRACTL { NOTHROW; - GC_NOTRIGGER; + GC_TRIGGERS; MODE_ANY; } CONTRACTL_END; + // Preempt to let GC suspend + GCX_PREEMP(); + PopulateEventName(g_WerEventTraits[CLR20r3].EventName); // the "+ 1" is to explicitly indicate which fields need to specify space for NULL diff --git a/src/coreclr/src/vm/dwreport.cpp b/src/coreclr/src/vm/dwreport.cpp index 4cc5950f7fc9a..0b9a2c9438293 100644 --- a/src/coreclr/src/vm/dwreport.cpp +++ b/src/coreclr/src/vm/dwreport.cpp @@ -189,8 +189,8 @@ HRESULT DwGetFileVersionInfo( CONTRACTL { NOTHROW; - GC_NOTRIGGER; - MODE_ANY; + GC_TRIGGERS; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -602,7 +602,7 @@ HRESULT GetManagedBucketParametersForIp( CONTRACTL { NOTHROW; - GC_NOTRIGGER; + GC_TRIGGERS; MODE_ANY; } CONTRACTL_END; @@ -677,7 +677,7 @@ void* GetBucketParametersForManagedException(UINT_PTR ip, TypeOfReportedError to CONTRACTL { NOTHROW; - GC_NOTRIGGER; + GC_TRIGGERS; MODE_ANY; } CONTRACTL_END; diff --git a/src/coreclr/src/vm/ecalllist.h b/src/coreclr/src/vm/ecalllist.h index 87aa7b62be5b2..243a735c2b2e4 100644 --- a/src/coreclr/src/vm/ecalllist.h +++ b/src/coreclr/src/vm/ecalllist.h @@ -909,6 +909,8 @@ FCFuncStart(gRuntimeHelpers) FCFuncElement("AllocTailCallArgBuffer", TailCallHelp::AllocTailCallArgBuffer) FCFuncElement("FreeTailCallArgBuffer", TailCallHelp::FreeTailCallArgBuffer) FCFuncElement("GetTailCallInfo", TailCallHelp::GetTailCallInfo) + FCFuncElement("GetILBytesJitted", GetJittedBytes) + FCFuncElement("GetMethodsJittedCount", GetJittedMethodsCount) FCFuncEnd() FCFuncStart(gContextSynchronizationFuncs) @@ -986,6 +988,7 @@ FCFuncStart(gComWrappersFuncs) QCFuncElement("TryGetOrCreateComInterfaceForObjectInternal", ComWrappersNative::TryGetOrCreateComInterfaceForObject) QCFuncElement("TryGetOrCreateObjectForComInstanceInternal", ComWrappersNative::TryGetOrCreateObjectForComInstance) QCFuncElement("SetGlobalInstanceRegisteredForMarshalling", GlobalComWrappersForMarshalling::SetGlobalInstanceRegisteredForMarshalling) + QCFuncElement("SetGlobalInstanceRegisteredForTrackerSupport", GlobalComWrappersForTrackerSupport::SetGlobalInstanceRegisteredForTrackerSupport) FCFuncEnd() #endif // FEATURE_COMWRAPPERS diff --git a/src/coreclr/src/vm/eeconfig.cpp b/src/coreclr/src/vm/eeconfig.cpp index bf0c602aa19c6..bb4266f86fb7f 100644 --- a/src/coreclr/src/vm/eeconfig.cpp +++ b/src/coreclr/src/vm/eeconfig.cpp @@ -126,11 +126,6 @@ HRESULT EEConfig::Init() fJitMinOpts = false; fPInvokeRestoreEsp = (DWORD)-1; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // By default, there is not pre-V4 CSE policy - fLegacyCorruptedStateExceptionsPolicy = false; -#endif // FEATURE_CORRUPTING_EXCEPTIONS - fNgenBindOptimizeNonGac = false; fStressLog = false; fProbeForStackOverflow = true; diff --git a/src/coreclr/src/vm/eeconfig.h b/src/coreclr/src/vm/eeconfig.h index c6579786aa821..7ed91a49fc9d4 100644 --- a/src/coreclr/src/vm/eeconfig.h +++ b/src/coreclr/src/vm/eeconfig.h @@ -133,11 +133,6 @@ class EEConfig } } -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Returns a bool to indicate if the legacy CSE (pre-v4) behaviour is enabled or not - bool LegacyCorruptedStateExceptionsPolicy(void) const {LIMITED_METHOD_CONTRACT; return fLegacyCorruptedStateExceptionsPolicy; } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - bool InteropValidatePinnedObjects() const { LIMITED_METHOD_CONTRACT; return m_fInteropValidatePinnedObjects; } bool InteropLogArguments() const { LIMITED_METHOD_CONTRACT; return m_fInteropLogArguments; } @@ -559,10 +554,6 @@ class EEConfig unsigned fPInvokeRestoreEsp; // -1=Default, 0=Never, Else=Always -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - bool fLegacyCorruptedStateExceptionsPolicy; -#endif // FEATURE_CORRUPTING_EXCEPTIONS - LPUTF8 pszBreakOnClassLoad; // Halt just before loading this class #ifdef TEST_DATA_CONSISTENCY diff --git a/src/coreclr/src/vm/eventpipe.cpp b/src/coreclr/src/vm/eventpipe.cpp index a7b64acc216fb..3ec4c54d5b5c4 100644 --- a/src/coreclr/src/vm/eventpipe.cpp +++ b/src/coreclr/src/vm/eventpipe.cpp @@ -434,6 +434,15 @@ void EventPipe::Disable(EventPipeSessionID id) if (s_numberOfSessions > 0) DisableInternal(id, pEventPipeProviderCallbackDataQueue); }); + +#ifdef DEBUG + if ((int)s_numberOfSessions == 0) + { + _ASSERTE(!MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled); + _ASSERTE(!MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled); + _ASSERTE(!MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled); + } +#endif } static void LogProcessInformationEvent(EventPipeEventSource &eventSource) diff --git a/src/coreclr/src/vm/eventpipeblock.cpp b/src/coreclr/src/vm/eventpipeblock.cpp index d72715956df7e..dd8807d3364c2 100644 --- a/src/coreclr/src/vm/eventpipeblock.cpp +++ b/src/coreclr/src/vm/eventpipeblock.cpp @@ -462,6 +462,4 @@ bool EventPipeStackBlock::WriteStack(DWORD stackId, StackContents* pStack) return true; } - - #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/src/vm/eventpipeevent.cpp b/src/coreclr/src/vm/eventpipeevent.cpp index e352afb456c3e..a56ed9429847c 100644 --- a/src/coreclr/src/vm/eventpipeevent.cpp +++ b/src/coreclr/src/vm/eventpipeevent.cpp @@ -23,7 +23,8 @@ EventPipeEvent::EventPipeEvent( m_level(level), m_needStack(needStack), m_enabledMask(0), - m_pMetadata(nullptr) + m_pMetadata(nullptr), + m_metadataLength(0) { CONTRACTL { diff --git a/src/coreclr/src/vm/eventpipeevent.h b/src/coreclr/src/vm/eventpipeevent.h index f2dfe4ec232ef..06da70f90f6c3 100644 --- a/src/coreclr/src/vm/eventpipeevent.h +++ b/src/coreclr/src/vm/eventpipeevent.h @@ -49,7 +49,8 @@ class EventPipeEvent // Only EventPipeProvider can create events. // The provider is responsible for allocating and freeing events. - EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0); + EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, + BYTE *pMetadata = NULL, unsigned int metadataLength = 0); public: ~EventPipeEvent(); diff --git a/src/coreclr/src/vm/eventpipefile.cpp b/src/coreclr/src/vm/eventpipefile.cpp index 6baeaeefa9cf5..5a69f502e724b 100644 --- a/src/coreclr/src/vm/eventpipefile.cpp +++ b/src/coreclr/src/vm/eventpipefile.cpp @@ -201,10 +201,11 @@ void EventPipeFile::WriteEvent(EventPipeEventInstance &instance, ULONGLONG captu THROWS; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(m_pSerializer != nullptr); } CONTRACTL_END; + if (HasErrors()) return; + #ifdef DEBUG _ASSERTE(instance.GetTimeStamp()->QuadPart >= m_lastSortedTimestamp.QuadPart); if (isSortedEvent) @@ -221,14 +222,15 @@ void EventPipeFile::WriteEvent(EventPipeEventInstance &instance, ULONGLONG captu // Check to see if we've seen this event type before. // If not, then write the event metadata to the event stream first. - unsigned int metadataId = GetMetadataId(*instance.GetEvent()); + EventPipeEvent* pEvent = instance.GetEvent(); + unsigned int metadataId = GetMetadataId(*pEvent); if(metadataId == 0) { metadataId = GenerateMetadataId(); EventPipeEventInstance* pMetadataInstance = EventPipe::BuildEventMetadataEvent(instance, metadataId); - WriteEventToBlock(*pMetadataInstance, 0); // metadataId=0 breaks recursion and represents the metadata event. + WriteEventToBlock(*pMetadataInstance, 0); // metadataId=0 breaks recursion and represents the metadata event. SaveMetadataId(*instance.GetEvent(), metadataId); @@ -247,7 +249,6 @@ void EventPipeFile::WriteSequencePoint(EventPipeSequencePoint* pSequencePoint) GC_NOTRIGGER; MODE_ANY; PRECONDITION(pSequencePoint != nullptr); - PRECONDITION(m_pSerializer != nullptr); } CONTRACTL_END; @@ -259,6 +260,9 @@ void EventPipeFile::WriteSequencePoint(EventPipeSequencePoint* pSequencePoint) Flush(FlushAllBlocks); EventPipeSequencePointBlock sequencePointBlock(pSequencePoint); + + if (HasErrors()) return; + m_pSerializer->WriteObject(&sequencePointBlock); // stack cache resets on sequence points @@ -278,13 +282,14 @@ void EventPipeFile::Flush(FlushFlags flags) NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(m_pSerializer != nullptr); PRECONDITION(m_pMetadataBlock != nullptr); PRECONDITION(m_pStackBlock != nullptr); PRECONDITION(m_pBlock != nullptr); } CONTRACTL_END; + if (HasErrors()) return; + // we write current blocks to the disk, whether they are full or not if ((m_pMetadataBlock->GetBytesWritten() != 0) && ((flags & FlushMetadataBlock) != 0)) { diff --git a/src/coreclr/src/vm/eventpipeprovider.cpp b/src/coreclr/src/vm/eventpipeprovider.cpp index f2d7760b5b32e..0351ff88438d8 100644 --- a/src/coreclr/src/vm/eventpipeprovider.cpp +++ b/src/coreclr/src/vm/eventpipeprovider.cpp @@ -152,7 +152,8 @@ EventPipeProviderCallbackData EventPipeProvider::UnsetConfiguration( return PrepareCallbackData(m_keywords, m_providerLevel, pFilterData); } -EventPipeEvent *EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength) +EventPipeEvent *EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, + BYTE *pMetadata, unsigned int metadataLength) { CONTRACTL { @@ -172,7 +173,6 @@ EventPipeEvent *EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords needStack, pMetadata, metadataLength); - // Add it to the list of events. AddEvent(*pEvent); return pEvent; @@ -255,11 +255,14 @@ void EventPipeProvider::AddEvent(EventPipeEvent &event) isEventFilterDescriptorInitialized = true; } + // NOTE: When we call the callback, we pass in enabled (which is either 1 or 0) as the ControlCode. + // If we want to add new ControlCode, we have to make corresponding change in eventtrace.cpp:EtwCallbackCommon + // to address this. See https://github.com/dotnet/runtime/pull/36733 for more discussions on this. if (pCallbackFunction != NULL && !g_fEEShutDown) { (*pCallbackFunction)( NULL, /* providerId */ - enabled, + enabled, /* ControlCode */ (UCHAR)providerLevel, keywords, 0 /* matchAllKeywords */, diff --git a/src/coreclr/src/vm/eventpipeprovider.h b/src/coreclr/src/vm/eventpipeprovider.h index d842f18044bb3..2fe93e969686a 100644 --- a/src/coreclr/src/vm/eventpipeprovider.h +++ b/src/coreclr/src/vm/eventpipeprovider.h @@ -76,7 +76,8 @@ class EventPipeProvider INT64 ComputeEventEnabledMask(INT64 keywords, EventPipeEventLevel eventLevel) const; // Create a new event. - EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0); + EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, + BYTE *pMetadata = NULL, unsigned int metadataLength = 0); private: diff --git a/src/coreclr/src/vm/eventtrace.cpp b/src/coreclr/src/vm/eventtrace.cpp index aee5caebdf7f5..026eec448fdaf 100644 --- a/src/coreclr/src/vm/eventtrace.cpp +++ b/src/coreclr/src/vm/eventtrace.cpp @@ -974,7 +974,7 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() #ifndef FEATURE_REDHAWK } EX_CATCH { } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); #endif // FEATURE_REDHAWK return hr; @@ -1752,7 +1752,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) return -1; @@ -1791,7 +1791,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) return -1; } @@ -1811,7 +1811,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) return -1; } @@ -1850,7 +1850,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) return -1; } @@ -1888,7 +1888,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) // won't have a name in it. pVal->sName.Clear(); } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); // Now that we know the full size of this type's data, see if it fits in our // batch or whether we need to flush @@ -1986,7 +1986,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) return; @@ -2551,7 +2551,7 @@ VOID ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) EX_CATCH { } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); } } @@ -2977,7 +2977,7 @@ BOOL ETW::TypeSystemLog::AddOrReplaceTypeLoggingInfo(ETW::LoggedTypesFromModule { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); return fSucceeded; } @@ -3384,7 +3384,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) { *pfCreatedNew = FALSE; @@ -3422,7 +3422,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) { *pfCreatedNew = FALSE; @@ -3518,7 +3518,7 @@ BOOL ETW::TypeSystemLog::AddTypeToGlobalCacheIfNotExists(TypeHandle th, BOOL * p { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) { *pfCreatedNew = FALSE; @@ -3550,7 +3550,7 @@ BOOL ETW::TypeSystemLog::AddTypeToGlobalCacheIfNotExists(TypeHandle th, BOOL * p { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) { *pfCreatedNew = FALSE; @@ -4267,6 +4267,10 @@ VOID EtwCallbackCommon( { ctxToUpdate->EventPipeProvider.Level = Level; ctxToUpdate->EventPipeProvider.EnabledKeywordsBitmask = MatchAnyKeyword; + ctxToUpdate->EventPipeProvider.IsEnabled = ControlCode; + + // For EventPipe, ControlCode can only be either 0 or 1. + _ASSERTE(ControlCode == 0 || ControlCode == 1); } if ( @@ -4641,7 +4645,6 @@ VOID ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept pExInfo = pExState->GetCurrentExceptionTracker(); _ASSERTE(pExInfo != NULL); bIsNestedException = (pExInfo->GetPreviousExceptionTracker() != NULL); - bIsCSE = (pExInfo->GetCorruptionSeverity() == ProcessCorrupting); bIsCLSCompliant = IsException((gc.exceptionObj)->GetMethodTable()) && ((gc.exceptionObj)->GetMethodTable() != MscorlibBinder::GetException(kRuntimeWrappedException)); @@ -4656,7 +4659,6 @@ VOID ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept exceptionFlags = ((bHasInnerException ? ETW::ExceptionLog::ExceptionStructs::HasInnerException : 0) | (bIsNestedException ? ETW::ExceptionLog::ExceptionStructs::IsNestedException : 0) | (bIsReThrownException ? ETW::ExceptionLog::ExceptionStructs::IsReThrownException : 0) | - (bIsCSE ? ETW::ExceptionLog::ExceptionStructs::IsCSE : 0) | (bIsCLSCompliant ? ETW::ExceptionLog::ExceptionStructs::IsCLSCompliant : 0)); if (pCf->IsFrameless()) @@ -6279,7 +6281,7 @@ VOID ETW::MethodLog::SendMethodDetailsEvent(MethodDesc *pMethodDesc) { fSucceeded = FALSE; } - EX_END_CATCH(RethrowCorruptingExceptions); + EX_END_CATCH(RethrowTerminalExceptions); if (!fSucceeded) goto done; @@ -7614,7 +7616,12 @@ bool EventPipeHelper::IsEnabled(DOTNET_TRACE_CONTEXT Context, UCHAR Level, ULONG } CONTRACTL_END - if (Level <= Context.EventPipeProvider.Level || Context.EventPipeProvider.Level == 0) + if (!Context.EventPipeProvider.IsEnabled) + { + return false; + } + + if (Level <= Context.EventPipeProvider.Level) { return (Keyword == (ULONGLONG)0) || (Keyword & Context.EventPipeProvider.EnabledKeywordsBitmask) != 0; } diff --git a/src/coreclr/src/vm/excep.cpp b/src/coreclr/src/vm/excep.cpp index 2dd54dbb42ac0..ff2e67489c801 100644 --- a/src/coreclr/src/vm/excep.cpp +++ b/src/coreclr/src/vm/excep.cpp @@ -121,11 +121,7 @@ typedef struct { PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord(); BOOL IsUnmanagedToManagedSEHHandler(EXCEPTION_REGISTRATION_RECORD*); -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity = NotCorrupting -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); +VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow); //------------------------------------------------------------------------------- // Basically, this asks whether the exception is a managed exception thrown by @@ -2711,85 +2707,6 @@ LONG RaiseExceptionFilter(EXCEPTION_POINTERS* ep, LPVOID pv) return EXCEPTION_CONTINUE_SEARCH; } -//========================================================================== -// Throw an object. -//========================================================================== -VOID DECLSPEC_NORETURN RaiseTheException(OBJECTREF throwable, BOOL rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ) -{ - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_MODE_COOPERATIVE; - - LOG((LF_EH, LL_INFO100, "RealCOMPlusThrow throwing %s\n", - throwable->GetMethodTable()->GetDebugClassName())); - - if (throwable == NULL) - { - _ASSERTE(!"RealCOMPlusThrow(OBJECTREF) called with NULL argument. Somebody forgot to post an exception!"); - EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); - } - - _ASSERTE(throwable != CLRException::GetPreallocatedStackOverflowException()); - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - if (!g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - // This is Scenario 3 described in clrex.h around the definition of SET_CE_RETHROW_FLAG_FOR_EX_CATCH macro. - // - // We are here because the VM is attempting to throw a managed exception. It is posssible this exception - // may not be seen by CLR's exception handler for managed code (e.g. there maybe an EX_CATCH up the stack - // that will swallow or rethrow this exception). In the following scenario: - // - // [VM1 - RethrowCSE] -> [VM2 - RethrowCSE] -> [VM3 - RethrowCSE] -> - // - // When managed code throws a CSE (e.g. TargetInvocationException flagged as CSE), [VM3] will rethrow it and we will - // enter EX_CATCH in VM2 which is supposed to rethrow it as well. Two things can happen: - // - // 1) The implementation of EX_CATCH in VM2 throws a new managed exception *before* rethrow policy is applied and control - // will reach EX_CATCH in VM1, OR - // - // 2) EX_CATCH in VM2 swallows the exception, comes out of the catch block and later throws a new managed exception that - // will be caught by EX_CATCH in VM1. - // - // In either of the cases, rethrow in VM1 should be on the basis of the new managed exception's corruption severity. - // - // To support this scenario, we set corruption severity of the managed exception VM is throwing. If its a rethrow, - // it implies we are rethrowing the last exception that was seen by CLR's managed code exception handler. In such a case, - // we will copy over the corruption severity of that exception. - - // If throwable indicates corrupted state, forcibly set the severity. - if (CEHelper::IsProcessCorruptedStateException(throwable)) - { - severity = ProcessCorrupting; - } - - // No one should have passed us an invalid severity. - _ASSERTE(severity > NotSet); - - if (severity == NotSet) - { - severity = NotCorrupting; - } - - // Update the corruption severity of the exception being thrown by the VM. - GetThread()->GetExceptionState()->SetLastActiveExceptionCorruptionSeverity(severity); - - // Exception's corruption severity should be reused in reraise if this exception leaks out from the VM - // into managed code - CEHelper::MarkLastActiveExceptionCorruptionSeverityForReraiseReuse(); - - LOG((LF_EH, LL_INFO100, "RaiseTheException - Set VM thrown managed exception severity to %d.\n", severity)); - } - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - - RaiseTheExceptionInternalOnly(throwable,rethrow); -} - HRESULT GetHRFromThrowable(OBJECTREF throwable) { STATIC_CONTRACT_THROWS; @@ -2965,11 +2882,8 @@ VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL r // INSTALL_COMPLUS_EXCEPTION_HANDLER has a filter, so must put the call in a separate fcn -static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS -) { +static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL rethrow) +{ STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_ANY; @@ -2982,23 +2896,24 @@ static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL r // TODO: Do we need to install COMPlusFrameHandler here? INSTALL_COMPLUS_EXCEPTION_HANDLER(); - RaiseTheException(throwable, rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + if (throwable == NULL) + { + _ASSERTE(!"RealCOMPlusThrow(OBJECTREF) called with NULL argument. Somebody forgot to post an exception!"); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); + } + RaiseTheExceptionInternalOnly(throwable, rethrow); UNINSTALL_COMPLUS_EXCEPTION_HANDLER(); } - -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS -) { +VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow) +{ STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_ANY; + + LOG((LF_EH, LL_INFO100, "RealCOMPlusThrow throwing %s\n", + throwable->GetMethodTable()->GetDebugClassName())); + GCPROTECT_BEGIN(throwable); _ASSERTE(IsException(throwable->GetMethodTable())); @@ -3019,20 +2934,12 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow ExceptionPreserveStackTrace(throwable); } - RealCOMPlusThrowWorker(throwable, rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + RealCOMPlusThrowWorker(throwable, rethrow); GCPROTECT_END(); } -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ) +VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable) { CONTRACTL { @@ -3042,11 +2949,7 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable } CONTRACTL_END; - RealCOMPlusThrow(throwable, FALSE -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + RealCOMPlusThrow(throwable, FALSE); } // this function finds the managed callback to get a resource @@ -3709,14 +3612,6 @@ BOOL IsUncatchable(OBJECTREF *pThrowable) if (OBJECTREFToObject(*pThrowable)->GetMethodTable() == g_pExecutionEngineExceptionClass) return TRUE; - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Corrupting exceptions are also uncatchable - if (CEHelper::IsProcessCorruptedStateException(*pThrowable)) - { - return TRUE; - } -#endif //FEATURE_CORRUPTING_EXCEPTIONS } return FALSE; @@ -8552,35 +8447,6 @@ LONG ReflectionInvocationExceptionFilter( } #endif // !TARGET_UNIX - // If the application has opted into triggering a failfast when a CorruptedStateException enters the Reflection system, - // then do the needful. - if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_FailFastOnCorruptedStateException) == 1) - { - // Get the thread and the managed exception object - they must exist at this point - Thread *pCurThread = GetThread(); - _ASSERTE(pCurThread != NULL); - - // Get the thread exception state - ThreadExceptionState * pCurTES = pCurThread->GetExceptionState(); - _ASSERTE(pCurTES != NULL); - - // Get the exception tracker for the current exception -#ifdef FEATURE_EH_FUNCLETS - PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker(); -#elif TARGET_X86 - PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker(); -#else // !(HOST_64BIT || TARGET_X86) -#error Unsupported platform -#endif // HOST_64BIT - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - if (pEHTracker->GetCorruptionSeverity() == ProcessCorrupting) - { - EEPolicy::HandleFatalError(COR_E_FAILFAST, reinterpret_cast(pExceptionInfo->ExceptionRecord->ExceptionAddress), NULL, pExceptionInfo); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - } - return ret; } // LONG ReflectionInvocationExceptionFilter() @@ -9050,7 +8916,7 @@ BOOL SetupWatsonBucketsForEscapingPreallocatedExceptions() CONTRACTL { - GC_NOTRIGGER; + GC_TRIGGERS; MODE_ANY; NOTHROW; PRECONDITION(GetThread() != NULL); @@ -9470,7 +9336,7 @@ PTR_EHWatsonBucketTracker GetWatsonBucketTrackerForPreallocatedException(OBJECTR #ifndef DACCESS_COMPILE CONTRACTL { - GC_NOTRIGGER; + GC_TRIGGERS; MODE_COOPERATIVE; NOTHROW; PRECONDITION(GetThread() != NULL); @@ -11011,7 +10877,7 @@ void EHWatsonBucketTracker::CaptureUnhandledInfoForWatson(TypeOfReportedError to CONTRACTL { NOTHROW; - GC_NOTRIGGER; + GC_TRIGGERS; MODE_ANY; PRECONDITION(IsWatsonEnabled()); } @@ -11095,781 +10961,43 @@ PTR_ExInfo GetEHTrackerForException(OBJECTREF oThrowable, PTR_ExInfo pStartingEH return fFoundTracker ? pEHTracker : NULL; } -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -// ----------------------------------------------------------------------- -// Support for CorruptedState Exceptions -// ----------------------------------------------------------------------- - // Given an exception code, this method returns a BOOL to indicate if the // code belongs to a corrupting exception or not. /* static */ -BOOL CEHelper::IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO /*= TRUE*/) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return FALSE; - } - - // Call into the utilcode helper function to check if this - // is a CE or not. - return (::IsProcessCorruptedStateException(dwExceptionCode, fCheckForSO)); -} - -// This is used in the VM folder version of "SET_CE_RETHROW_FLAG_FOR_EX_CATCH" (in clrex.h) -// to check if the managed exception caught by EX_END_CATCH is CSE or not. -// -// If you are using it from rethrow boundaries (e.g. SET_CE_RETHROW_FLAG_FOR_EX_CATCH -// macro that is used to automatically rethrow corrupting exceptions), then you may -// want to set the "fMarkForReuseIfCorrupting" to TRUE to enable propagation of the -// corruption severity when the reraised exception is seen by managed code again. -/* static */ -BOOL CEHelper::IsLastActiveExceptionCorrupting(BOOL fMarkForReuseIfCorrupting /* = FALSE */) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(GetThread() != NULL); - } - CONTRACTL_END; - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return FALSE; - } - - BOOL fIsCorrupting = FALSE; - ThreadExceptionState *pCurTES = GetThread()->GetExceptionState(); - - // Check the corruption severity - CorruptionSeverity severity = pCurTES->GetLastActiveExceptionCorruptionSeverity(); - fIsCorrupting = (severity == ProcessCorrupting); - if (fIsCorrupting && fMarkForReuseIfCorrupting) - { - // Mark the corruption severity for reuse - CEHelper::MarkLastActiveExceptionCorruptionSeverityForReraiseReuse(); - } - - LOG((LF_EH, LL_INFO100, "CEHelper::IsLastActiveExceptionCorrupting - Using corruption severity from TES.\n")); - - return fIsCorrupting; -} - -// Given a MethodDesc, this method will return a BOOL to indicate if -// the containing assembly was built for PreV4 runtime or not. -/* static */ -BOOL CEHelper::IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(pMethodDesc != NULL); - } - CONTRACTL_END; - - // By default, assume that the containing assembly was not - // built for PreV4 runtimes. - BOOL fBuiltForPreV4Runtime = FALSE; - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return TRUE; - } - - LPCSTR pszVersion = NULL; - - // Retrieve the manifest metadata reference since that contains - // the "built-for" runtime details - IMDInternalImport *pImport = pMethodDesc->GetAssembly()->GetManifestImport(); - if (pImport && SUCCEEDED(pImport->GetVersionString(&pszVersion))) - { - if (pszVersion != NULL) - { - // If version begins with "v1.*" or "v2.*", it was built for preV4 runtime - if ((pszVersion[0] == 'v' || pszVersion[0] == 'V') && - IS_DIGIT(pszVersion[1]) && - (pszVersion[2] == '.') ) - { - // Looks like a version. Is it lesser than v4.0 major version where we start using new behavior? - fBuiltForPreV4Runtime = ((DIGIT_TO_INT(pszVersion[1]) != 0) && - (DIGIT_TO_INT(pszVersion[1]) <= HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME)); - } - } - } - - return fBuiltForPreV4Runtime; -} - -// Given a MethodDesc and CorruptionSeverity, this method will return a -// BOOL indicating if the method can handle those kinds of CEs or not. -/* static */ -BOOL CEHelper::CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity) -{ - BOOL fCanMethodHandleSeverity = FALSE; - -#ifndef DACCESS_COMPILE - CONTRACTL - { - GC_NOTRIGGER; - THROWS; - MODE_ANY; - PRECONDITION(pMethodDesc != NULL); - } - CONTRACTL_END; - - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return TRUE; - } - - // Since the method is Security Critical, now check if it is - // attributed to handle the CE or not. - IMDInternalImport *pImport = pMethodDesc->GetMDImport(); - if (pImport != NULL) - { - mdMethodDef methodDef = pMethodDesc->GetMemberDef(); - switch(severity) - { - case ProcessCorrupting: - fCanMethodHandleSeverity = (S_OK == pImport->GetCustomAttributeByName( - methodDef, - HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE, - NULL, - NULL)); - break; - default: - _ASSERTE(!"Unknown Exception Corruption Severity!"); - break; - } - } -#endif // !DACCESS_COMPILE - - return fCanMethodHandleSeverity; -} - -// Given a MethodDesc, this method will return a BOOL to indicate if the method should be examined for exception -// handlers for the specified exception. -// -// This method accounts for both corrupting and non-corrupting exceptions. -/* static */ -BOOL CEHelper::CanMethodHandleException(CorruptionSeverity severity, PTR_MethodDesc pMethodDesc) -{ - CONTRACTL - { - GC_NOTRIGGER; - THROWS; - MODE_ANY; - PRECONDITION(pMethodDesc != NULL); - } - CONTRACTL_END; - - // By default, assume that the runtime shouldn't look for exception handlers - // in the method pointed by the MethodDesc - BOOL fLookForExceptionHandlersInMethod = FALSE; - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return TRUE; - } - - // If we have been asked to use the last active corruption severity (e.g. in cases of Reflection - // or COM interop), then retrieve it. - if (severity == UseLast) - { - LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Using LastActiveExceptionCorruptionSeverity.\n")); - severity = GetThread()->GetExceptionState()->GetLastActiveExceptionCorruptionSeverity(); - } - - LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Processing CorruptionSeverity: %d.\n", severity)); - - if (severity > NotCorrupting) - { - // If the method lies in an assembly built for pre-V4 runtime, allow the runtime - // to look for exception handler for the CE. - BOOL fIsMethodInPreV4Assembly = FALSE; - fIsMethodInPreV4Assembly = CEHelper::IsMethodInPreV4Assembly(pMethodDesc); - - if (!fIsMethodInPreV4Assembly) - { - // Method lies in an assembly built for V4 or later runtime. - LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Method is in an assembly built for V4 or later runtime.\n")); - - // Depending upon the corruption severity of the exception, see if the - // method supports handling that. - LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Exception is corrupting.\n")); - - // Check if the method can handle the severity specified in the exception object. - fLookForExceptionHandlersInMethod = CEHelper::CanMethodHandleCE(pMethodDesc, severity); - } - else - { - // Method is in a Pre-V4 assembly - allow it to be examined for processing the CE - fLookForExceptionHandlersInMethod = TRUE; - } - } - else - { - // Non-corrupting exceptions can continue to be delivered - fLookForExceptionHandlersInMethod = TRUE; - } - - return fLookForExceptionHandlersInMethod; -} - -// Given a managed exception object, this method will return a BOOL -// indicating if it corresponds to a ProcessCorruptedState exception -// or not. -/* static */ -BOOL CEHelper::IsProcessCorruptedStateException(OBJECTREF oThrowable) +BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, OBJECTREF throwable) { CONTRACTL { NOTHROW; GC_NOTRIGGER; MODE_COOPERATIVE; - PRECONDITION(oThrowable != NULL); } CONTRACTL_END; - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) + switch (dwExceptionCode) { + case STATUS_ACCESS_VIOLATION: + if (throwable != NULL && MscorlibBinder::IsException(throwable->GetMethodTable(), kNullReferenceException)) + return FALSE; + break; + case STATUS_STACK_OVERFLOW: + case EXCEPTION_ILLEGAL_INSTRUCTION: + case EXCEPTION_IN_PAGE_ERROR: + case EXCEPTION_INVALID_DISPOSITION: + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + case EXCEPTION_PRIV_INSTRUCTION: + case STATUS_UNWIND_CONSOLIDATE: + break; + default: return FALSE; } -#ifndef DACCESS_COMPILE - // If the throwable represents preallocated SO, then indicate it as a CSE - if (CLRException::GetPreallocatedStackOverflowException() == oThrowable) - { - return TRUE; - } -#endif // !DACCESS_COMPILE - - // Check if we have an exception tracker for this exception - // and if so, if it represents corrupting exception or not. - // Get the exception tracker for the current exception -#ifdef FEATURE_EH_FUNCLETS - PTR_ExceptionTracker pEHTracker = GetEHTrackerForException(oThrowable, NULL); -#elif TARGET_X86 - PTR_ExInfo pEHTracker = GetEHTrackerForException(oThrowable, NULL); -#else -#error Unsupported platform -#endif - - if (pEHTracker != NULL) - { - // Found the tracker for exception object - check if its CSE or not. - return (pEHTracker->GetCorruptionSeverity() == ProcessCorrupting); - } - - return FALSE; -} - -#ifdef FEATURE_EH_FUNCLETS -void CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass(Thread *pCurThread, PTR_ExceptionTracker pEHTracker, BOOL fIsFirstPass, - DWORD dwExceptionCode) -{ -#ifndef DACCESS_COMPILE - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(!fIsFirstPass); // This method should only be called during an unwind - PRECONDITION(pCurThread != NULL); - } - CONTRACTL_END; - - // - // - // Typically, exception tracker is created for an exception when the OS is in the first pass. - // However, it may be created during the 2nd pass under specific cases. Managed C++ provides - // such a scenario. In the following, stack grows left to right: - // - // CallDescrWorker -> ILStub1 -> -> UMThunkStub -> IL_Stub2 -> - // - // If a CSE exception goes unhandled from managed main, it will reach the OS. The [CRT in?] OS triggers - // unwind that results in invoking the personality routine of UMThunkStub, called UMThunkStubUnwindFrameChainHandler, - // that releases all exception trackers below it. Thus, the tracker for the CSE, which went unhandled, is also - // released. This detail is 64bit specific and the crux of this issue. - // - // Now, it is expected that by the time we are in the unwind pass, the corruption severity would have already been setup in the - // exception tracker and thread exception state (TES) as part of the first pass, and thus, are identical. - // - // However, for the scenario above, when the unwind continues and reaches ILStub1, its personality routine (which is ProcessCLRException) - // is invoked. It attempts to get the exception tracker corresponding to the exception. Since none exists, it creates a brand new one, - // which has the exception corruption severity as NotSet. - // - // During the stack walk, we know (from TES) that the active exception was a CSE, and thus, ILStub1 cannot handle the exception. Prior - // to bailing out, we assert that our data structures are intact by comparing the exception severity in TES with the one in the current - // exception tracker. Since the tracker was recreated, it had the severity as NotSet and this does not match the severity in TES. - // Thus, the assert fires. [This check is performed in ProcessManagedCallFrame.] - // - // To address such a case, if we have created a new exception tracker in the unwind (2nd) pass, then set its - // exception corruption severity to what the TES holds currently. This will maintain the same semantic as the case - // where new tracker is not created (for e.g. the exception was caught in Managed main). - // - // The exception is the scenario of code that uses longjmp to jump to a different context. Longjmp results in a raise - // of a new exception with the longjmp exception code (0x80000026) but with ExceptionFlags set indicating unwind. When this is - // seen by ProcessCLRException (64bit personality routine), it will create a new tracker in the 2nd pass. - // - // Longjmp outside an exceptional path does not interest us, but the one in the exceptional - // path would only happen when a method attributed to handle CSE invokes it. Thus, if the longjmp happened during the 2nd pass of a CSE, - // we want it to proceed (and thus, jump) as expected and not apply the CSE severity to the tracker - this is equivalent to - // a catch block that handles a CSE and then does a "throw new Exception();". The new exception raised is - // non-CSE in nature as well. - // - // http://www.nynaeve.net/?p=105 has a brief description of how exception-safe setjmp/longjmp works. - // - // - if (pEHTracker->GetCorruptionSeverity() == NotSet) - { - // Get the thread exception state - ThreadExceptionState *pCurTES = pCurThread->GetExceptionState(); - - // Set the tracker to have the same corruption severity as the last active severity unless we are dealing - // with LONGJMP - if (dwExceptionCode == STATUS_LONGJUMP) - { - pCurTES->SetLastActiveExceptionCorruptionSeverity(NotCorrupting); - } - - pEHTracker->SetCorruptionSeverity(pCurTES->GetLastActiveExceptionCorruptionSeverity()); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass - Setup the corruption severity in the second pass.\n")); - } -#endif // !DACCESS_COMPILE -} -#endif // FEATURE_EH_FUNCLETS - -// This method is invoked from the personality routine for managed code and is used to setup the -// corruption severity for the active exception on the thread exception state and the -// exception tracker corresponding to the exception. -/* static */ -void CEHelper::SetupCorruptionSeverityForActiveException(BOOL fIsRethrownException, BOOL fIsNestedException, BOOL fShouldTreatExceptionAsNonCorrupting /* = FALSE */) -{ -#ifndef DACCESS_COMPILE - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - // Get the thread and the managed exception object - they must exist at this point - Thread *pCurThread = GetThread(); - _ASSERTE(pCurThread != NULL); - - OBJECTREF oThrowable = pCurThread->GetThrowable(); - _ASSERTE(oThrowable != NULL); - - // Get the thread exception state - ThreadExceptionState * pCurTES = pCurThread->GetExceptionState(); - _ASSERTE(pCurTES != NULL); - - // Get the exception tracker for the current exception -#ifdef FEATURE_EH_FUNCLETS - PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker(); -#elif TARGET_X86 - PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker(); -#else // !(HOST_64BIT || TARGET_X86) -#error Unsupported platform -#endif // HOST_64BIT - - _ASSERTE(pEHTracker != NULL); - - // Get the current exception code from the tracker. - PEXCEPTION_RECORD pEHRecord = pCurTES->GetExceptionRecord(); - _ASSERTE(pEHRecord != NULL); - DWORD dwActiveExceptionCode = pEHRecord->ExceptionCode; - - if (pEHTracker->GetCorruptionSeverity() != NotSet) - { - // Since the exception tracker already has the corruption severity set, - // we dont have much to do. Just confirm that our assumptions are correct. - _ASSERTE(pEHTracker->GetCorruptionSeverity() == pCurTES->GetLastActiveExceptionCorruptionSeverity()); - - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Current tracker already has the corruption severity set.\n")); - return; - } - - // If the exception in question is to be treated as non-corrupting, - // then flag it and exit. - if (fShouldTreatExceptionAsNonCorrupting || g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - pEHTracker->SetCorruptionSeverity(NotCorrupting); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Exception treated as non-corrupting.\n")); - goto done; - } - - if (!fIsRethrownException && !fIsNestedException) - { - // There should be no previously active exception for this case - _ASSERTE(pEHTracker->GetPreviousExceptionTracker() == NULL); - - CorruptionSeverity severityTES = NotSet; - - if (pCurTES->ShouldLastActiveExceptionCorruptionSeverityBeReused()) - { - // Get the corruption severity from the ThreadExceptionState (TES) for the last active exception - severityTES = pCurTES->GetLastActiveExceptionCorruptionSeverity(); - - // Incase of scenarios like AD transition or Reflection invocation, - // TES would hold corruption severity of the last active exception. To propagate it - // to the current exception, we will apply it to current tracker and only if the applied - // severity is "NotSet", will we proceed to check the current exception for corruption - // severity. - pEHTracker->SetCorruptionSeverity(severityTES); - } - - // Reset TES Corruption Severity - pCurTES->SetLastActiveExceptionCorruptionSeverity(NotSet); - - if (severityTES == NotSet) - { - // Since the last active exception's severity was "NotSet", we will look up the - // exception code and the exception object to see if the exception should be marked - // corrupting. - // - // Since this exception was neither rethrown nor is nested, it implies that we are - // outside an active exception. Thus, even if it contains inner exceptions, we wont have - // corruption severity for them since that information is tracked in EH tracker and - // we wont have an EH tracker for the inner most exception. - - if (CEHelper::IsProcessCorruptedStateException(dwActiveExceptionCode) || - CEHelper::IsProcessCorruptedStateException(oThrowable)) - { - pEHTracker->SetCorruptionSeverity(ProcessCorrupting); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked non-rethrow/non-nested exception as ProcessCorrupting.\n")); - } - else - { - pEHTracker->SetCorruptionSeverity(NotCorrupting); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked non-rethrow/non-nested exception as NotCorrupting.\n")); - } - } - else - { - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity to tracker from ThreadExceptionState for non-rethrow/non-nested exception.\n")); - } - } - else - { - // Its either a rethrow or nested exception - -#ifdef FEATURE_EH_FUNCLETS - PTR_ExceptionTracker pOrigEHTracker = NULL; -#elif TARGET_X86 - PTR_ExInfo pOrigEHTracker = NULL; -#else -#error Unsupported platform -#endif - - BOOL fDoWeHaveCorruptionSeverity = FALSE; - - if (fIsRethrownException) - { - // Rethrown exceptions are nested by nature (of our implementation). The - // original EHTracker will exist for the exception - infact, it will be - // the tracker previous to the current one. We will simply copy - // its severity to the current EH tracker representing the rethrow. - pOrigEHTracker = pEHTracker->GetPreviousExceptionTracker(); - _ASSERTE(pOrigEHTracker != NULL); - - // Ideally, we would like have the assert below enabled. But, as may happen under OOM - // stress, this can be false. Here's how it will happen: - // - // An exception is thrown, which is later caught and rethrown in the catch block. Rethrow - // results in calling IL_Rethrow that will call RaiseTheExceptionInternalOnly to actually - // raise the exception. Prior to the raise, we update the last thrown object on the thread - // by calling Thread::SafeSetLastThrownObject which, internally, could have an OOM, resulting - // in "changing" the throwable used to raise the exception to be preallocated OOM object. - // - // When the rethrow happens and CLR's exception handler for managed code sees the exception, - // the exception tracker created for the rethrown exception will contain the reference to - // the last thrown object, which will be the preallocated OOM object. - // - // Thus, though, we came here because of a rethrow, and logically, the throwable should remain - // the same, it neednt be. Simply put, rethrow can result in working with a completely different - // exception object than what was originally thrown. - // - // Hence, the assert cannot be enabled. - // - // Thus, we will use the EH tracker corresponding to the original exception, to get the - // rethrown exception's corruption severity, only when the rethrown throwable is the same - // as the original throwable. Otherwise, we will pretend that we didnt get the original tracker - // and will automatically enter the path below to set the corruption severity based upon the - // rethrown throwable. - - // _ASSERTE(pOrigEHTracker->GetThrowable() == oThrowable); - if (pOrigEHTracker->GetThrowable() != oThrowable) - { - pOrigEHTracker = NULL; - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Rethrown throwable does not match the original throwable. Corruption severity will be set based upon rethrown throwable.\n")); - } - } - else - { - // Get the corruption severity from the ThreadExceptionState (TES) for the last active exception - CorruptionSeverity severityTES = NotSet; - - if (pCurTES->ShouldLastActiveExceptionCorruptionSeverityBeReused()) - { - severityTES = pCurTES->GetLastActiveExceptionCorruptionSeverity(); - - // Incase of scenarios like AD transition or Reflection invocation, - // TES would hold corruption severity of the last active exception. To propagate it - // to the current exception, we will apply it to current tracker and only if the applied - // severity is "NotSet", will we proceed to check the current exception for corruption - // severity. - pEHTracker->SetCorruptionSeverity(severityTES); - } - - // Reset TES Corruption Severity - pCurTES->SetLastActiveExceptionCorruptionSeverity(NotSet); - - // If the last exception didnt have any corruption severity, proceed to look for it. - if (severityTES == NotSet) - { - // This is a nested exception - check if it has an inner exception(s). If it does, - // find the EH tracker corresponding to the innermost exception and we will copy the - // corruption severity from the original tracker to the current one. - OBJECTREF oInnermostThrowable = ((EXCEPTIONREF)oThrowable)->GetBaseException(); - if (oInnermostThrowable != NULL) - { - // Find the tracker corresponding to the inner most exception, starting from - // the tracker previous to the current one. An EH tracker may not be found if - // the code did the following inside a catch clause: - // - // Exception ex = new Exception("inner exception"); - // throw new Exception("message", ex); - // - // Or, an exception like AV happened in the catch clause. - pOrigEHTracker = GetEHTrackerForException(oInnermostThrowable, pEHTracker->GetPreviousExceptionTracker()); - } - } - else - { - // We have the corruption severity from the TES. Set the flag indicating so. - fDoWeHaveCorruptionSeverity = TRUE; - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity to tracker from ThreadExceptionState for nested exception.\n")); - } - } - - if (!fDoWeHaveCorruptionSeverity) - { - if (pOrigEHTracker != NULL) - { - // Copy the severity from the original EH tracker to the current one - CorruptionSeverity origCorruptionSeverity = pOrigEHTracker->GetCorruptionSeverity(); - _ASSERTE(origCorruptionSeverity != NotSet); - pEHTracker->SetCorruptionSeverity(origCorruptionSeverity); - - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity (%d) from the original EH tracker for rethrown exception.\n", origCorruptionSeverity)); - } - else - { - if (CEHelper::IsProcessCorruptedStateException(dwActiveExceptionCode) || - CEHelper::IsProcessCorruptedStateException(oThrowable)) - { - pEHTracker->SetCorruptionSeverity(ProcessCorrupting); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked nested exception as ProcessCorrupting.\n")); - } - else - { - pEHTracker->SetCorruptionSeverity(NotCorrupting); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked nested exception as NotCorrupting.\n")); - } - } - } - } - -done: - // Save the current exception's corruption severity in the ThreadExceptionState (TES) - // for cases when we catch the managed exception in the runtime using EX_CATCH. - // At such a time, all exception trackers get released (due to unwind triggered - // by EX_END_CATCH) and yet we need the corruption severity information for - // scenarios like AD Transition, Reflection invocation, etc. - CorruptionSeverity currentSeverity = pEHTracker->GetCorruptionSeverity(); - - // We should be having a valid corruption severity at this point - _ASSERTE(currentSeverity != NotSet); - - // Save it in the TES - pCurTES->SetLastActiveExceptionCorruptionSeverity(currentSeverity); - LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity (%d) to ThreadExceptionState.\n", currentSeverity)); - -#endif // !DACCESS_COMPILE -} - -// CE can be caught in the VM and later reraised again. Examples of such scenarios -// include AD transition, COM interop, Reflection invocation, to name a few. -// In such cases, we want to mark the corruption severity for reuse upon reraise, -// implying that when the VM does a reraise of such an exception, we should use -// the original corruption severity for the new raised exception, instead of creating -// a new one for it. -/* static */ -void CEHelper::MarkLastActiveExceptionCorruptionSeverityForReraiseReuse() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(GetThread() != NULL); - } - CONTRACTL_END; - - // If the last active exception's corruption severity is anything but - // "NotSet", mark it for ReraiseReuse - ThreadExceptionState *pCurTES = GetThread()->GetExceptionState(); - _ASSERTE(pCurTES != NULL); - - CorruptionSeverity severityTES = pCurTES->GetLastActiveExceptionCorruptionSeverity(); - if (severityTES != NotSet) - { - pCurTES->SetLastActiveExceptionCorruptionSeverity((CorruptionSeverity)(severityTES | ReuseForReraise)); - } -} - -// This method will return a BOOL to indicate if the current exception is to be treated as -// non-corrupting. Currently, this returns true for NullReferenceException only. -/* static */ -BOOL CEHelper::ShouldTreatActiveExceptionAsNonCorrupting() -{ - BOOL fShouldTreatAsNonCorrupting = FALSE; - -#ifndef DACCESS_COMPILE - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(GetThread() != NULL); - } - CONTRACTL_END; - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return TRUE; - } - - DWORD dwActiveExceptionCode = GetThread()->GetExceptionState()->GetExceptionRecord()->ExceptionCode; - if (dwActiveExceptionCode == STATUS_ACCESS_VIOLATION) - { - // NullReference has the same exception code as AV - OBJECTREF oThrowable = NULL; - GCPROTECT_BEGIN(oThrowable); - - // Get the throwable and check if it represents null reference exception - oThrowable = GetThread()->GetThrowable(); - _ASSERTE(oThrowable != NULL); - if (MscorlibBinder::GetException(kNullReferenceException) == oThrowable->GetMethodTable()) - { - fShouldTreatAsNonCorrupting = TRUE; - } - GCPROTECT_END(); - } -#endif // !DACCESS_COMPILE - - return fShouldTreatAsNonCorrupting; -} - -// If we were working in a nested exception scenario, reset the corruption severity to the last -// exception we were processing, based upon its EH tracker. -// -// If none was present, reset it to NotSet. -// -// Note: This method must be called once the exception trackers have been adjusted post catch-block execution. -/* static */ -void CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler(Thread *pThread) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(pThread != NULL); - } - CONTRACTL_END; - - ThreadExceptionState *pCurTES = pThread->GetExceptionState(); - - // By this time, we would have set the correct exception tracker for the active exception domain, - // if applicable. An example is throwing and catching an exception within a catch block. We will update - // the LastActiveCorruptionSeverity based upon the active exception domain. If we are not in one, we will - // set it to "NotSet". -#ifdef FEATURE_EH_FUNCLETS - PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker(); -#elif TARGET_X86 - PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker(); -#else -#error Unsupported platform -#endif - - if (pEHTracker) - { - pCurTES->SetLastActiveExceptionCorruptionSeverity(pEHTracker->GetCorruptionSeverity()); - } - else - { - pCurTES->SetLastActiveExceptionCorruptionSeverity(NotSet); - } - - LOG((LF_EH, LL_INFO100, "CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler - Reset LastActiveException corruption severity to %d.\n", - pCurTES->GetLastActiveExceptionCorruptionSeverity())); -} - -// This method will return a BOOL indicating if the target of IDispatch can handle the specified exception or not. -/* static */ -BOOL CEHelper::CanIDispatchTargetHandleException() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(GetThread() != NULL); - } - CONTRACTL_END; - - // By default, assume that the target of IDispatch cannot handle the exception. - BOOL fCanMethodHandleException = FALSE; - - if (g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - return TRUE; - } - - // IDispatch implementation in COM interop works by invoking the actual target via reflection. - // Thus, a COM client could use the V4 runtime to invoke a V2 method. In such a case, a CSE - // could come unhandled at the actual target invoked via reflection. - // - // Reflection invocation would have set a flag for us, indicating if the actual target was - // enabled to handle the CE or not. If it is, then we should allow the COM client to get the - // hresult from the call and not let the exception continue up the stack. - ThreadExceptionState *pCurTES = GetThread()->GetExceptionState(); - fCanMethodHandleException = pCurTES->CanReflectionTargetHandleException(); - - // Reset the flag so that subsequent invocations work as expected. - pCurTES->SetCanReflectionTargetHandleException(FALSE); + if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy)) + return FALSE; - return fCanMethodHandleException; + return TRUE; } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - #ifndef DACCESS_COMPILE // This method will deliver the actual exception notification. Its assumed that the caller has done the necessary checks, including // checking whether the delegate can be invoked for the exception's corruption severity. @@ -11964,7 +11092,7 @@ void ExceptionNotifications::GetEventArgsForNotification(ExceptionNotificationHa *pOutEventArgs = NULL; LOG((LF_EH, LL_INFO100, "ExceptionNotifications::GetEventArgsForNotification: Setting event args to NULL due to an exception.\n")); } - EX_END_CATCH(RethrowCorruptingExceptions); // Dont swallow any CSE that may come in from the .ctor. + EX_END_CATCH(RethrowTerminalExceptions); } // This SEH filter will be invoked when an exception escapes out of the exception notification @@ -11975,89 +11103,6 @@ static LONG ExceptionNotificationFilter(PEXCEPTION_POINTERS pExceptionInfo, LPVO return -1; } -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -// This method will return a BOOL indicating if the delegate should be invoked for the exception -// of the specified corruption severity. -BOOL ExceptionNotifications::CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(pDelegate != NULL && IsProtectedByGCFrame(pDelegate) && (*pDelegate != NULL)); - PRECONDITION(severity > NotSet); - } - CONTRACTL_END; - - // Notifications for CSE are only delivered if the delegate target follows CSE rules. - BOOL fCanMethodHandleException = g_pConfig->LegacyCorruptedStateExceptionsPolicy() ? TRUE:(severity == NotCorrupting); - if (!fCanMethodHandleException) - { - EX_TRY - { - // Get the MethodDesc of the delegate to be invoked - MethodDesc *pMDDelegate = COMDelegate::GetMethodDesc(*pDelegate); - _ASSERTE(pMDDelegate != NULL); - - // Check the callback target and see if it is following CSE rules or not. - fCanMethodHandleException = CEHelper::CanMethodHandleException(severity, pMDDelegate); - } - EX_CATCH - { - // Incase of any exceptions, pretend we cannot handle the exception - fCanMethodHandleException = FALSE; - LOG((LF_EH, LL_INFO100, "ExceptionNotifications::CanDelegateBeInvokedForException: Exception while trying to determine if exception notification can be invoked or not.\n")); - } - EX_END_CATCH(RethrowCorruptingExceptions); // Dont swallow any CSEs. - } - - return fCanMethodHandleException; -} -#endif // FEATURE_CORRUPTING_EXCEPTIONS - -// This method will make the actual delegate invocation for the exception notification to be delivered. If an -// exception escapes out of the notification, our filter in ExceptionNotifications::DeliverNotification will -// address it. -void ExceptionNotifications::InvokeNotificationDelegate(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs, - OBJECTREF *pAppDomain -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(pDelegate != NULL && IsProtectedByGCFrame(pDelegate) && (*pDelegate != NULL)); - PRECONDITION(pEventArgs != NULL && IsProtectedByGCFrame(pEventArgs)); - PRECONDITION(pAppDomain != NULL && IsProtectedByGCFrame(pAppDomain)); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - PRECONDITION(severity > NotSet); -#endif // FEATURE_CORRUPTING_EXCEPTIONS - // Unhandled Exception Notification is delivered via Unhandled Exception Processing - // mechanism. - PRECONDITION(notificationType != UnhandledExceptionHandler); - } - CONTRACTL_END; - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Notifications are delivered based upon corruption severity of the exception - if (!ExceptionNotifications::CanDelegateBeInvokedForException(pDelegate, severity)) - { - LOG((LF_EH, LL_INFO100, "ExceptionNotifications::InvokeNotificationDelegate: Delegate cannot be invoked for corruption severity %d\n", - severity)); - return; - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - - // We've already exercised the prestub on this delegate's COMDelegate::GetMethodDesc, - // as part of wiring up a reliable event sink in the BCL. Deliver the notification. - ExceptionNotifications::DeliverExceptionNotification(notificationType, pDelegate, pAppDomain, pEventArgs); -} - // This method returns a BOOL to indicate if the AppDomain is ready to receive exception notifications or not. BOOL ExceptionNotifications::CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType) { @@ -12087,11 +11132,7 @@ BOOL ExceptionNotifications::CanDeliverNotificationToCurrentAppDomain(ExceptionN // so that if an exception escapes out of the notification callback, we will trigger failfast from // our filter. void ExceptionNotifications::DeliverNotification(ExceptionNotificationHandlerType notificationType, - OBJECTREF *pThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ) + OBJECTREF *pThrowable) { STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_NOTHROW; // NOTHROW because incase of an exception, we will FailFast. @@ -12101,26 +11142,16 @@ void ExceptionNotifications::DeliverNotification(ExceptionNotificationHandlerTyp { ExceptionNotificationHandlerType notificationType; OBJECTREF *pThrowable; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - CorruptionSeverity severity; -#endif // FEATURE_CORRUPTING_EXCEPTIONS } args; args.notificationType = notificationType; args.pThrowable = pThrowable; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - args.severity = severity; -#endif // FEATURE_CORRUPTING_EXCEPTIONS PAL_TRY(TryArgs *, pArgs, &args) { // Make the call to the actual method that will invoke the callbacks ExceptionNotifications::DeliverNotificationInternal(pArgs->notificationType, - pArgs->pThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , pArgs->severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + pArgs->pThrowable); } PAL_EXCEPT_FILTER(ExceptionNotificationFilter) { @@ -12134,11 +11165,7 @@ void ExceptionNotifications::DeliverNotification(ExceptionNotificationHandlerTyp // This method will deliver the exception notification to the current AppDomain. void ExceptionNotifications::DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType, - OBJECTREF *pThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ) + OBJECTREF *pThrowable) { CONTRACTL { @@ -12151,9 +11178,6 @@ void ExceptionNotifications::DeliverNotificationInternal(ExceptionNotificationHa PRECONDITION(notificationType != UnhandledExceptionHandler); PRECONDITION((pThrowable != NULL) && (*pThrowable != NULL)); PRECONDITION(ExceptionNotifications::CanDeliverNotificationToCurrentAppDomain(notificationType)); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - PRECONDITION(severity > NotSet); // Exception corruption severity must be valid at this point. -#endif // FEATURE_CORRUPTING_EXCEPTIONS } CONTRACTL_END; @@ -12220,12 +11244,7 @@ void ExceptionNotifications::DeliverNotificationInternal(ExceptionNotificationHa gc.arrDelegates = (PTRARRAYREF) ((DELEGATEREF)(gc.oNotificationDelegate))->GetInvocationList(); if (gc.arrDelegates == NULL || !gc.arrDelegates->GetMethodTable()->IsArray()) { - ExceptionNotifications::InvokeNotificationDelegate(notificationType, &gc.oNotificationDelegate, &gc.oEventArgs, - &gc.oCurAppDomain -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + ExceptionNotifications::DeliverExceptionNotification(notificationType, &gc.oNotificationDelegate, &gc.oCurAppDomain, &gc.oEventArgs); } else { @@ -12237,12 +11256,7 @@ void ExceptionNotifications::DeliverNotificationInternal(ExceptionNotificationHa for (UINT_PTR i=0; im_Array[i]; - ExceptionNotifications::InvokeNotificationDelegate(notificationType, &gc.oInnerDelegate, &gc.oEventArgs, - &gc.oCurAppDomain -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + ExceptionNotifications::DeliverExceptionNotification(notificationType, &gc.oInnerDelegate, &gc.oCurAppDomain, &gc.oEventArgs); } } } @@ -12282,11 +11296,7 @@ void ExceptionNotifications::DeliverFirstChanceNotification() oThrowable = pCurTES->GetThrowable(); _ASSERTE(oThrowable != NULL); - ExceptionNotifications::DeliverNotification(FirstChanceExceptionHandler, &oThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , pCurTES->GetCurrentExceptionTracker()->GetCorruptionSeverity() -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + ExceptionNotifications::DeliverNotification(FirstChanceExceptionHandler, &oThrowable); GCPROTECT_END(); } diff --git a/src/coreclr/src/vm/excep.h b/src/coreclr/src/vm/excep.h index c31ead4d38529..661eefe813bb7 100644 --- a/src/coreclr/src/vm/excep.h +++ b/src/coreclr/src/vm/excep.h @@ -26,6 +26,8 @@ BOOL IsExceptionFromManagedCode(const EXCEPTION_RECORD * pExceptionRecord); BOOL IsIPinVirtualStub(PCODE f_IP); bool IsIPInMarkedJitHelper(UINT_PTR uControlPc); +BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, OBJECTREF throwable); + BOOL AdjustContextForJITHelpers(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContext); #if defined(FEATURE_HIJACK) && (!defined(TARGET_X86) || defined(TARGET_UNIX)) @@ -70,8 +72,6 @@ struct ThrowCallbackType void * pPrevExceptionRecord; #endif - // Is the current exception a longjmp? - CORRUPTING_EXCEPTIONS_ONLY(BOOL m_fIsLongJump;) void Init() { LIMITED_METHOD_CONTRACT; @@ -92,8 +92,6 @@ struct ThrowCallbackType pCurrentExceptionRecord = 0; pPrevExceptionRecord = 0; #endif - // By default, the current exception is not a longjmp - CORRUPTING_EXCEPTIONS_ONLY(m_fIsLongJump = FALSE;) } }; @@ -251,11 +249,7 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowNonLocalized(RuntimeExceptionKind reKind, // Throw an object. //========================================================================== -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity = NotCorrupting -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); +VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable); //========================================================================== // Throw an undecorated runtime exception. @@ -800,44 +794,6 @@ LONG ReflectionInvocationExceptionFilter( EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function. PVOID pParam); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -// ----------------------------------------------------------------------- -// Support for Corrupted State Exceptions -// ----------------------------------------------------------------------- -#ifndef HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE -#define HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE "System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute" -#endif // HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE - -#ifndef HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME -#define HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME 2 -#endif // HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME - -// This helper class contains static method to support working with Corrupted State Exceptions, -// including checking if a method can handle it or not, copy state across throwables, etc. -class CEHelper -{ - BOOL static IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc); - BOOL static CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity); - -public: - BOOL static CanMethodHandleException(CorruptionSeverity severity, PTR_MethodDesc pMethodDesc); - BOOL static CanIDispatchTargetHandleException(); - BOOL static IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE); - BOOL static IsProcessCorruptedStateException(OBJECTREF oThrowable); - BOOL static IsLastActiveExceptionCorrupting(BOOL fMarkForReuseIfCorrupting = FALSE); - BOOL static ShouldTreatActiveExceptionAsNonCorrupting(); - void static MarkLastActiveExceptionCorruptionSeverityForReraiseReuse(); - void static SetupCorruptionSeverityForActiveException(BOOL fIsRethrownException, BOOL fIsNestedException, BOOL fShouldTreatExceptionAsNonCorrupting = FALSE); -#ifdef FEATURE_EH_FUNCLETS - typedef DPTR(class ExceptionTracker) PTR_ExceptionTracker; - void static SetupCorruptionSeverityForActiveExceptionInUnwindPass(Thread *pCurThread, PTR_ExceptionTracker pEHTracker, BOOL fIsFirstPass, - DWORD dwExceptionCode); -#endif // FEATURE_EH_FUNCLETS - void static ResetLastActiveCorruptionSeverityPostCatchHandler(Thread *pThread); -}; - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - #ifndef DACCESS_COMPILE // exception filter invoked for unhandled exceptions on the entry point thread (thread 0) LONG EntryPointFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID _pData); @@ -860,36 +816,17 @@ class ExceptionNotifications OBJECTREF *pOutEventArgs, OBJECTREF *pThrowable); void static DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType, - OBJECTREF *pThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); - - void static InvokeNotificationDelegate(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs, - OBJECTREF *pAppDomain -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + OBJECTREF *pThrowable); public: - BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType); + void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs, + OBJECTREF *pAppDomain); - void static DeliverNotification(ExceptionNotificationHandlerType notificationType, - OBJECTREF *pThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - BOOL static CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity); -#endif // FEATURE_CORRUPTING_EXCEPTIONS + void static DeliverNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pThrowable); public: - void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, - OBJECTREF *pAppDomain, OBJECTREF *pEventArgs); void static DeliverFirstChanceNotification(); }; diff --git a/src/coreclr/src/vm/exceptionhandling.cpp b/src/coreclr/src/vm/exceptionhandling.cpp index 740678e978e17..c655fe8ded92c 100644 --- a/src/coreclr/src/vm/exceptionhandling.cpp +++ b/src/coreclr/src/vm/exceptionhandling.cpp @@ -1006,23 +1006,13 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord !(dwExceptionFlags & EXCEPTION_UNWINDING), &STState); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Only setup the Corruption Severity in the first pass if (!(dwExceptionFlags & EXCEPTION_UNWINDING)) { // Switch to COOP mode GCX_COOP(); - if (pTracker && pTracker->GetThrowable() != NULL) - { - // Setup the state in current exception tracker indicating the corruption severity - // of the active exception. - CEHelper::SetupCorruptionSeverityForActiveException((STState == ExceptionTracker::STS_FirstRethrowFrame), (pTracker->GetPreviousExceptionTracker() != NULL), - CEHelper::ShouldTreatActiveExceptionAsNonCorrupting()); - } - // Failfast if exception indicates corrupted process state - if (pTracker->GetCorruptionSeverity() == ProcessCorrupting) + if (IsProcessCorruptedStateException(pExceptionRecord->ExceptionCode, pTracker->GetThrowable())) { OBJECTREF oThrowable = NULL; SString message; @@ -1045,7 +1035,6 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(pExceptionRecord->ExceptionCode, (LPCWSTR)message); } } -#endif // FEATURE_CORRUPTING_EXCEPTIONS #ifndef TARGET_UNIX // Watson is on Windows only // Setup bucketing details for nested exceptions (rethrow and non-rethrow) only if we are in the first pass @@ -2446,25 +2435,6 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame( if (fIsILStub && !fIsFunclet) // only make this callback on the main method body of IL stubs pUserMDForILStub = GetUserMethodForILStub(pThread, sf.SP, pMD, &pILStubFrame); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - BOOL fCanMethodHandleException = TRUE; - CorruptionSeverity currentSeverity = NotCorrupting; - { - // Switch to COOP mode since we are going to request throwable - GCX_COOP(); - - // We must defer to the MethodDesc of the user method instead of the IL stub - // itself because the user can specify the policy on a per-method basis and - // that won't be reflected via the IL stub's MethodDesc. - MethodDesc * pMDWithCEAttribute = (pUserMDForILStub != NULL) ? pUserMDForILStub : pMD; - - // Check if the exception can be delivered to the method? It will check if the exception - // is a CE or not. If it is, it will check if the method can process it or not. - currentSeverity = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetCorruptionSeverity(); - fCanMethodHandleException = CEHelper::CanMethodHandleException(currentSeverity, pMDWithCEAttribute); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - // Doing rude abort. Skip all non-constrained execution region code. // When rude abort is initiated, we cannot intercept any exceptions. if (pThread->IsRudeAbortInitiated()) @@ -2673,27 +2643,7 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame( const METHODTOKEN& MethToken = pcfThisFrame->GetMethodToken(); EH_CLAUSE_ENUMERATOR EnumState; - unsigned EHCount; - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // The method cannot handle the exception (e.g. cannot handle the CE), then simply bail out - // without examining the EH clauses in it. - if (!fCanMethodHandleException) - { - LOG((LF_EH, LL_INFO100, "ProcessManagedCallFrame - CEHelper decided not to look for exception handlers in the method(MD:%p).\n", pMD)); - - // Set the flag to skip this frame since the CE cannot be delivered - _ASSERTE(currentSeverity == ProcessCorrupting); - - // Force EHClause count to be zero - EHCount = 0; - } - else -#endif // FEATURE_CORRUPTING_EXCEPTIONS - { - EHCount = pJitMan->InitializeEHEnumeration(MethToken, &EnumState); - } - + unsigned EHCount = pJitMan->InitializeEHEnumeration(MethToken, &EnumState); if (!fIsFirstPass) { @@ -3961,20 +3911,6 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( } } } - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - if (fCreateNewTracker) - { - // Exception tracker should be in the 2nd pass right now - _ASSERTE(!pTracker->IsInFirstPass()); - - // The corruption severity of a newly created tracker is NotSet - _ASSERTE(pTracker->GetCorruptionSeverity() == NotSet); - - // See comment in CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass for details - CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass(pThread, pTracker, FALSE, pExceptionRecord->ExceptionCode); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS } _ASSERTE(pTracker->m_pLimitFrame >= pThread->GetFrame()); @@ -4776,20 +4712,6 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex, bool isHar ThreadExceptionState * pCurTES = pCurThread->GetExceptionState(); _ASSERTE(pCurTES != NULL); - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - ExceptionTracker* pEHTracker = pCurTES->GetCurrentExceptionTracker(); - if (pEHTracker == NULL) - { - CorruptionSeverity severity = NotCorrupting; - if (CEHelper::IsProcessCorruptedStateException(ex.GetExceptionRecord()->ExceptionCode)) - { - severity = ProcessCorrupting; - } - - pCurTES->SetLastActiveExceptionCorruptionSeverity(severity); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS } throw std::move(ex); diff --git a/src/coreclr/src/vm/exceptionhandling.h b/src/coreclr/src/vm/exceptionhandling.h index 2f56f20340e77..dfdaf49726edc 100644 --- a/src/coreclr/src/vm/exceptionhandling.h +++ b/src/coreclr/src/vm/exceptionhandling.h @@ -70,11 +70,6 @@ class ExceptionTracker m_WatsonBucketTracker.Init(); #endif // !TARGET_UNIX -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Initialize the default exception severity to NotCorrupting - m_CorruptionSeverity = NotSet; -#endif // FEATURE_CORRUPTING_EXCEPTIONS - // By default, mark the tracker as not having delivered the first // chance exception notification m_fDeliveredFirstChanceNotification = FALSE; @@ -130,11 +125,6 @@ class ExceptionTracker m_WatsonBucketTracker.Init(); #endif // !TARGET_UNIX -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Initialize the default exception severity to NotCorrupting - m_CorruptionSeverity = NotSet; -#endif // FEATURE_CORRUPTING_EXCEPTIONS - // By default, mark the tracker as not having delivered the first // chance exception notification m_fDeliveredFirstChanceNotification = FALSE; @@ -586,25 +576,6 @@ class ExceptionTracker } #endif // !TARGET_UNIX -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -private: - CorruptionSeverity m_CorruptionSeverity; -public: - inline CorruptionSeverity GetCorruptionSeverity() - { - LIMITED_METHOD_CONTRACT; - - return (CorruptionSeverity)GET_CORRUPTION_SEVERITY(m_CorruptionSeverity); - } - - inline void SetCorruptionSeverity(CorruptionSeverity severityToSet) - { - LIMITED_METHOD_CONTRACT; - - m_CorruptionSeverity = severityToSet; - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - private: BOOL m_fDeliveredFirstChanceNotification; diff --git a/src/coreclr/src/vm/exceptmacros.h b/src/coreclr/src/vm/exceptmacros.h index 55bfec8f28ca3..31fb8c73cdf71 100644 --- a/src/coreclr/src/vm/exceptmacros.h +++ b/src/coreclr/src/vm/exceptmacros.h @@ -246,38 +246,6 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); // Actual UEF worker prototype for use by GCUnhandledExceptionFilter. extern LONG InternalUnhandledExceptionFilter_Worker(PEXCEPTION_POINTERS pExceptionInfo); -//========================================================================== -// Installs a handler to unwind exception frames, but not catch the exception -//========================================================================== - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -// ----------------------------------------------------------------------- -// Support for Corrupted State Exceptions -// ----------------------------------------------------------------------- -// This enumeration defines the corruption severity of an exception and -// whether it should be reused for the next exception thrown or not. -enum CorruptionSeverity -{ - UseLast = 0x0, // When specified, the last active corruption severity from TES should be used - NotSet = 0x1, // Corruption Severity has not been set - this is the default/reset value - NotCorrupting = 0x2, // Indicates exception is not corrupting - ProcessCorrupting = 0x4, // Indicates exception represents process corrupted state - ReuseForReraise = 0x2000 // Indicates that the corruption severity should be reused for the next exception thrown, - // provided its not nested and isnt a rethrow. This flag is used typically for propagation of - // severity across boundaries like Reflection invocation, AD transition etc. -}; - -#define GET_CORRUPTION_SEVERITY(severity) (((severity) & (~ReuseForReraise))) -#define CAN_REUSE_CORRUPTION_SEVERITY(severity) (((severity) & ReuseForReraise) == ReuseForReraise) - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - -VOID DECLSPEC_NORETURN RaiseTheException(OBJECTREF throwable, BOOL rethrow -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS -); - VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL rethrow, BOOL fForStackOverflow = FALSE); #if defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE) diff --git a/src/coreclr/src/vm/exinfo.cpp b/src/coreclr/src/vm/exinfo.cpp index 8a9ed80d257f5..58e353a016016 100644 --- a/src/coreclr/src/vm/exinfo.cpp +++ b/src/coreclr/src/vm/exinfo.cpp @@ -110,11 +110,6 @@ void ExInfo::Init() DestroyExceptionHandle(); m_hThrowable = NULL; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Initialize the default exception severity to NotCorrupting - m_CorruptionSeverity = NotSet; -#endif // FEATURE_CORRUPTING_EXCEPTIONS - // By default, mark the tracker as not having delivered the first // chance exception notification m_fDeliveredFirstChanceNotification = FALSE; diff --git a/src/coreclr/src/vm/exinfo.h b/src/coreclr/src/vm/exinfo.h index 5e57e0ce77ae8..332d2248342ab 100644 --- a/src/coreclr/src/vm/exinfo.h +++ b/src/coreclr/src/vm/exinfo.h @@ -90,25 +90,6 @@ class ExInfo } #endif -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -private: - CorruptionSeverity m_CorruptionSeverity; -public: - inline CorruptionSeverity GetCorruptionSeverity() - { - LIMITED_METHOD_CONTRACT; - - return (CorruptionSeverity)GET_CORRUPTION_SEVERITY(m_CorruptionSeverity); - } - - inline void SetCorruptionSeverity(CorruptionSeverity severityToSet) - { - LIMITED_METHOD_CONTRACT; - - m_CorruptionSeverity = severityToSet; - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - private: BOOL m_fDeliveredFirstChanceNotification; public: diff --git a/src/coreclr/src/vm/exstate.cpp b/src/coreclr/src/vm/exstate.cpp index c2c2c0adb63f4..db238df8bafe1 100644 --- a/src/coreclr/src/vm/exstate.cpp +++ b/src/coreclr/src/vm/exstate.cpp @@ -43,13 +43,6 @@ ThreadExceptionState::ThreadExceptionState() // Init the UE Watson BucketTracker m_UEWatsonBucketTracker.Init(); #endif // !TARGET_UNIX - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Initialize the default exception severity to NotCorrupting - m_LastActiveExceptionCorruptionSeverity = NotSet; - m_fCanReflectionTargetHandleException = FALSE; -#endif // FEATURE_CORRUPTING_EXCEPTIONS - } ThreadExceptionState::~ThreadExceptionState() diff --git a/src/coreclr/src/vm/exstate.h b/src/coreclr/src/vm/exstate.h index 1ea8790a11dc1..e3971d356b5a7 100644 --- a/src/coreclr/src/vm/exstate.h +++ b/src/coreclr/src/vm/exstate.h @@ -162,56 +162,6 @@ class ThreadExceptionState } #endif -#ifdef FEATURE_CORRUPTING_EXCEPTIONS -private: - CorruptionSeverity m_LastActiveExceptionCorruptionSeverity; - BOOL m_fCanReflectionTargetHandleException; - -public: - // Returns the corruption severity of the last active exception - inline CorruptionSeverity GetLastActiveExceptionCorruptionSeverity() - { - LIMITED_METHOD_CONTRACT; - - return (CorruptionSeverity)GET_CORRUPTION_SEVERITY(m_LastActiveExceptionCorruptionSeverity); - } - - // Set the corruption severity of the last active exception - inline void SetLastActiveExceptionCorruptionSeverity(CorruptionSeverity severityToSet) - { - LIMITED_METHOD_CONTRACT; - - m_LastActiveExceptionCorruptionSeverity = severityToSet; - } - - // Returns a bool indicating if the last active exception's corruption severity should - // be used when exception is reraised (e.g. Reflection Invocation, AD transition, etc) - inline BOOL ShouldLastActiveExceptionCorruptionSeverityBeReused() - { - LIMITED_METHOD_CONTRACT; - - return CAN_REUSE_CORRUPTION_SEVERITY(m_LastActiveExceptionCorruptionSeverity); - } - - // Returns a BOOL to indicate if reflection target can handle CSE or not. - // This is used in DispatchInfo::CanIDispatchTargetHandleException. - inline BOOL CanReflectionTargetHandleException() - { - LIMITED_METHOD_CONTRACT; - - return m_fCanReflectionTargetHandleException; - } - - // Sets a BOOL indicate if the Reflection invocation target can handle exception or not. - // Used in ReflectionInvocation.cpp. - inline void SetCanReflectionTargetHandleException(BOOL fCanReflectionTargetHandleException) - { - LIMITED_METHOD_CONTRACT; - - m_fCanReflectionTargetHandleException = fCanReflectionTargetHandleException; - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - private: ThreadExceptionFlag m_flag; diff --git a/src/coreclr/src/vm/frames.h b/src/coreclr/src/vm/frames.h index 5c8a1ca869d74..3437030705f18 100644 --- a/src/coreclr/src/vm/frames.h +++ b/src/coreclr/src/vm/frames.h @@ -742,11 +742,7 @@ class Frame : public FrameBase friend class StackFrameIterator; friend class TailCallFrame; friend class AppDomain; - friend VOID RealCOMPlusThrow(OBJECTREF -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , CorruptionSeverity severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + friend VOID RealCOMPlusThrow(OBJECTREF); friend FCDECL0(VOID, JIT_StressGC); #ifdef _DEBUG friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo); diff --git a/src/coreclr/src/vm/gcenv.os.cpp b/src/coreclr/src/vm/gcenv.os.cpp index 6b9e042f04e9b..e7add3b29e08b 100644 --- a/src/coreclr/src/vm/gcenv.os.cpp +++ b/src/coreclr/src/vm/gcenv.os.cpp @@ -756,7 +756,7 @@ uint32_t GCToOSInterface::GetCurrentProcessCpuCount() // Return the size of the user-mode portion of the virtual address space of this process. // Return: -// non zero if it has succeeded, 0 if it has failed +// non zero if it has succeeded, (size_t)-1 if not available size_t GCToOSInterface::GetVirtualMemoryLimit() { LIMITED_METHOD_CONTRACT; @@ -771,16 +771,6 @@ static size_t g_RestrictedPhysicalMemoryLimit = (size_t)MAX_PTR; #ifndef TARGET_UNIX -// For 32-bit processes the virtual address range could be smaller than the amount of physical -// memory on the machine/in the container, we need to restrict by the VM. -static bool g_UseRestrictedVirtualMemory = false; - -typedef BOOL (WINAPI *PGET_PROCESS_MEMORY_INFO)(HANDLE handle, PROCESS_MEMORY_COUNTERS* memCounters, uint32_t cb); -static PGET_PROCESS_MEMORY_INFO GCGetProcessMemoryInfo = 0; - -typedef BOOL (WINAPI *PIS_PROCESS_IN_JOB)(HANDLE processHandle, HANDLE jobHandle, BOOL* result); -typedef BOOL (WINAPI *PQUERY_INFORMATION_JOB_OBJECT)(HANDLE jobHandle, JOBOBJECTINFOCLASS jobObjectInfoClass, void* lpJobObjectInfo, DWORD cbJobObjectInfoLength, LPDWORD lpReturnLength); - static size_t GetRestrictedPhysicalMemoryLimit() { LIMITED_METHOD_CONTRACT; @@ -793,34 +783,14 @@ static size_t GetRestrictedPhysicalMemoryLimit() uint64_t total_virtual = 0; uint64_t total_physical = 0; BOOL in_job_p = FALSE; - HINSTANCE hinstKernel32 = 0; - - PIS_PROCESS_IN_JOB GCIsProcessInJob = 0; - PQUERY_INFORMATION_JOB_OBJECT GCQueryInformationJobObject = 0; - - GCIsProcessInJob = &(::IsProcessInJob); - if (!GCIsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) + if (!IsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) goto exit; if (in_job_p) { - hinstKernel32 = WszLoadLibrary(L"kernel32.dll"); - if (!hinstKernel32) - goto exit; - - GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstKernel32, "K32GetProcessMemoryInfo"); - - if (!GCGetProcessMemoryInfo) - goto exit; - - GCQueryInformationJobObject = &(::QueryInformationJobObject); - - if (!GCQueryInformationJobObject) - goto exit; - JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info; - if (GCQueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, &limit_info, + if (QueryInformationJobObject(NULL, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info), NULL)) { size_t job_memory_limit = (size_t)MAX_PTR; @@ -867,13 +837,6 @@ static size_t GetRestrictedPhysicalMemoryLimit() if (job_physical_memory_limit == (size_t)MAX_PTR) { job_physical_memory_limit = 0; - - if (hinstKernel32 != 0) - { - FreeLibrary(hinstKernel32); - hinstKernel32 = 0; - GCGetProcessMemoryInfo = 0; - } } // Check to see if we are limited by VM. @@ -893,15 +856,8 @@ static size_t GetRestrictedPhysicalMemoryLimit() if (total_virtual < total_physical) { - if (hinstKernel32 != 0) - { - // We can also free the lib here - if we are limited by VM we will not be calling - // GetProcessMemoryInfo. - FreeLibrary(hinstKernel32); - GCGetProcessMemoryInfo = 0; - } - g_UseRestrictedVirtualMemory = true; - job_physical_memory_limit = (size_t)total_virtual; + // Limited by virtual address space + job_physical_memory_limit = 0; } VolatileStore(&g_RestrictedPhysicalMemoryLimit, job_physical_memory_limit); @@ -928,9 +884,6 @@ static size_t GetRestrictedPhysicalMemoryLimit() // Get the physical memory that this process can use. // Return: // non zero if it has succeeded, 0 if it has failed -// -// PERF TODO: Requires more work to not treat the restricted case to be special. -// To be removed before 3.0 ships. uint64_t GCToOSInterface::GetPhysicalMemoryLimit(bool* is_restricted) { LIMITED_METHOD_CONTRACT; @@ -941,11 +894,7 @@ uint64_t GCToOSInterface::GetPhysicalMemoryLimit(bool* is_restricted) size_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) { - if (is_restricted -#ifndef TARGET_UNIX - && !g_UseRestrictedVirtualMemory -#endif - ) + if (is_restricted) *is_restricted = true; return restricted_limit; @@ -965,26 +914,22 @@ uint64_t GCToOSInterface::GetPhysicalMemoryLimit(bool* is_restricted) // available_page_file - The maximum amount of memory the current process can commit, in bytes. // Remarks: // Any parameter can be null. -void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) +void GCToOSInterface::GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { LIMITED_METHOD_CONTRACT; - uint64_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) { size_t workingSetSize; BOOL status = FALSE; #ifndef TARGET_UNIX - if (!g_UseRestrictedVirtualMemory) - { - PROCESS_MEMORY_COUNTERS pmc; - status = GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); - workingSetSize = pmc.WorkingSetSize; - } + PROCESS_MEMORY_COUNTERS pmc; + status = GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); + workingSetSize = pmc.WorkingSetSize; #else status = PAL_GetPhysicalMemoryUsed(&workingSetSize); #endif - if(status) + if (status) { if (memory_load) *memory_load = (uint32_t)((float)workingSetSize * 100.0 / (float)restricted_limit); @@ -1009,9 +954,10 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available GetProcessMemoryLoad(&ms); #ifndef TARGET_UNIX - if (g_UseRestrictedVirtualMemory) + // For 32-bit processes the virtual address range could be smaller than the amount of physical + // memory on the machine/in the container, we need to restrict by the VM. + if (ms.ullTotalVirtual < ms.ullTotalPhys) { - _ASSERTE (ms.ullTotalVirtual == restricted_limit); if (memory_load != NULL) *memory_load = (uint32_t)((float)(ms.ullTotalVirtual - ms.ullAvailVirtual) * 100.0 / (float)ms.ullTotalVirtual); if (available_physical != NULL) diff --git a/src/coreclr/src/vm/gchandleutilities.h b/src/coreclr/src/vm/gchandleutilities.h index b875644b853b5..d90a2f0faef09 100644 --- a/src/coreclr/src/vm/gchandleutilities.h +++ b/src/coreclr/src/vm/gchandleutilities.h @@ -201,9 +201,9 @@ inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object) // Special handle creation convenience functions #ifdef FEATURE_COMINTEROP -inline OBJECTHANDLE CreateWinRTWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pWinRTWeakReference) +inline OBJECTHANDLE CreateNativeComWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pComWeakReference) { - OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_WINRT, (void*)pWinRTWeakReference); + OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_NATIVE_COM, (void*)pComWeakReference); if (!hnd) { COMPlusThrowOM(); @@ -363,7 +363,7 @@ inline void DestroyTypedHandle(OBJECTHANDLE handle) } #ifdef FEATURE_COMINTEROP -inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle) +inline void DestroyNativeComWeakHandle(OBJECTHANDLE handle) { CONTRACTL { @@ -375,7 +375,7 @@ inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle) CONTRACTL_END; // Release the WinRT weak reference if we have one. We're assuming that this will not reenter the - // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT + // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_NATIVE_COM // but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG. void* pExtraInfo = GCHandleUtilities::GetGCHandleManager()->GetExtraInfoFromHandle(handle); IWeakReference* pWinRTWeakReference = reinterpret_cast(pExtraInfo); @@ -385,7 +385,7 @@ inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle) } DiagHandleDestroyed(handle); - GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT); + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_NATIVE_COM); } #endif diff --git a/src/coreclr/src/vm/gdbjit.cpp b/src/coreclr/src/vm/gdbjit.cpp index 1642c9fbf7d56..8d8e34e6362f4 100644 --- a/src/coreclr/src/vm/gdbjit.cpp +++ b/src/coreclr/src/vm/gdbjit.cpp @@ -1792,16 +1792,6 @@ void VarDebugInfo::DumpDebugInfo(char* ptr, int& offset) offset += len; } -/* static data for symbol strings */ -struct Elf_Symbol { - const char* m_name; - int m_off; - TADDR m_value; - int m_section, m_size; - NewArrayHolder m_symbol_name; - Elf_Symbol() : m_name(nullptr), m_off(0), m_value(0), m_section(0), m_size(0) {} -}; - template static int countFuncs(T &arr, int n) { diff --git a/src/coreclr/src/vm/gdbjit.h b/src/coreclr/src/vm/gdbjit.h index 8d9359c16ca5e..fa5a4883cb742 100644 --- a/src/coreclr/src/vm/gdbjit.h +++ b/src/coreclr/src/vm/gdbjit.h @@ -334,7 +334,16 @@ class VarDebugInfo: public DwarfDumpable uintptr_t m_high_pc; }; -struct Elf_Symbol; +/* static data for symbol strings */ +struct Elf_Symbol { + const char* m_name; + int m_off; + TADDR m_value; + int m_section, m_size; + NewArrayHolder m_symbol_name; + Elf_Symbol() : m_name(nullptr), m_off(0), m_value(0), m_section(0), m_size(0) {} +}; + class Elf_Builder; class DebugStringsCU; diff --git a/src/coreclr/src/vm/i386/excepx86.cpp b/src/coreclr/src/vm/i386/excepx86.cpp index 5b333e9f9857e..a89e715956692 100644 --- a/src/coreclr/src/vm/i386/excepx86.cpp +++ b/src/coreclr/src/vm/i386/excepx86.cpp @@ -1065,18 +1065,11 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc. GCPROTECT_BEGIN(throwable); throwable = pThread->GetThrowable(); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS + if (IsProcessCorruptedStateException(exceptionCode, throwable)) { - // Setup the state in current exception tracker indicating the corruption severity - // of the active exception. - CEHelper::SetupCorruptionSeverityForActiveException(bRethrownException, bNestedException, - CEHelper::ShouldTreatActiveExceptionAsNonCorrupting()); - // Failfast if exception indicates corrupted process state - if (pExInfo->GetCorruptionSeverity() == ProcessCorrupting) - EEPOLICY_HANDLE_FATAL_ERROR(exceptionCode); + EEPOLICY_HANDLE_FATAL_ERROR(exceptionCode); } -#endif // FEATURE_CORRUPTING_EXCEPTIONS // If we're out of memory, then we figure there's probably not memory to maintain a stack trace, so we skip it. // If we've got a stack overflow, then we figure the stack will be so huge as to make tracking the stack trace @@ -1392,10 +1385,6 @@ CPFH_UnwindFrames1(Thread* pThread, EXCEPTION_REGISTRATION_RECORD* pEstablisherF tct.pTopFrame = GetCurrFrame(pEstablisherFrame); // highest frame to search to tct.pBottomFrame = NULL; - // Set the flag indicating if the current exception represents a longjmp. - // See comment in COMPlusUnwindCallback for details. - CORRUPTING_EXCEPTIONS_ONLY(tct.m_fIsLongJump = (exceptionCode == STATUS_LONGJUMP);) - #ifdef _DEBUG tct.pCurrentExceptionRecord = pEstablisherFrame; tct.pPrevExceptionRecord = GetPrevSEHRecord(pEstablisherFrame); @@ -2366,20 +2355,6 @@ StackWalkAction COMPlusThrowCallback( // SWA value if (fIsILStub) pUserMDForILStub = GetUserMethodForILStub(pThread, currentSP, pFunc, &pILStubFrame); -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - CorruptionSeverity currentSeverity = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetCorruptionSeverity(); - { - // We must defer to the MethodDesc of the user method instead of the IL stub - // itself because the user can specify the policy on a per-method basis and - // that won't be reflected via the IL stub's MethodDesc. - MethodDesc * pMDWithCEAttribute = fIsILStub ? pUserMDForILStub : pFunc; - - // Check if the exception can be delivered to the method? It will check if the exception - // is a CE or not. If it is, it will check if the method can process it or not. - fMethodCanHandleException = CEHelper::CanMethodHandleException(currentSeverity, pMDWithCEAttribute); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - // Let the profiler know that we are searching for a handler within this function instance if (fGiveDebuggerAndProfilerNotification) EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionEnter(pFunc); @@ -2406,29 +2381,12 @@ StackWalkAction COMPlusThrowCallback( // SWA value ExceptionNotifications::DeliverFirstChanceNotification(); } } + IJitManager* pJitManager = pCf->GetJitManager(); _ASSERTE(pJitManager); - EH_CLAUSE_ENUMERATOR pEnumState; - unsigned EHCount = 0; - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // If exception cannot be handled, then just bail out. We shouldnt examine the EH clauses - // in such a method. - if (!fMethodCanHandleException) - { - LOG((LF_EH, LL_INFO100, "COMPlusThrowCallback - CEHelper decided not to look for exception handlers in the method(MD:%p).\n", pFunc)); - // Set the flag to skip this frame since the CE cannot be delivered - _ASSERTE(currentSeverity == ProcessCorrupting); - - // Ensure EHClause count is zero - EHCount = 0; - } - else -#endif // FEATURE_CORRUPTING_EXCEPTIONS - { - EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState); - } + EH_CLAUSE_ENUMERATOR pEnumState; + unsigned EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState); if (EHCount == 0) { @@ -2708,59 +2666,6 @@ StackWalkAction COMPlusUnwindCallback (CrawlFrame *pCf, ThrowCallbackType *pData TypeHandle thrownType = TypeHandle(); - BOOL fCanMethodHandleException = TRUE; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // MethodDesc's security information (i.e. whether it is critical or transparent) is calculated lazily. - // If this method's security information was not precalculated, then it would have been in the first pass - // already using Security::IsMethodCritical which could take have taken us down a path which is GC_TRIGGERS. - // - // - // However, this unwind callback (for X86) is GC_NOTRIGGER and at this point the security information would have been - // calculated already. Hence, we wouldnt endup in the GC_TRIGGERS path. Thus, to keep SCAN.EXE (static contract analyzer) happy, - // we will pass a FALSE to the CanMethodHandleException call, indicating we dont need to calculate security information (and thus, - // not go down the GC_TRIGGERS path. - // - // Check if the exception can be delivered to the method? It will check if the exception - // is a CE or not. If it is, it will check if the method can process it or not. - CorruptionSeverity currentSeverity = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetCorruptionSeverity(); - - // We have to do this check for x86 since, unlike 64bit which will setup a new exception tracker for longjmp, - // x86 only sets up new trackers in the first pass (and longjmp is 2nd pass only exception). Hence, we pass - // this information in the callback structure without affecting any existing exception tracker (incase longjmp was - // a nested exception). - if (pData->m_fIsLongJump) - { - // Longjump is not a CSE. With a CSE in progress, this can be invoked by either: - // - // 1) Managed code (e.g. finally/fault/catch), OR - // 2) By native code - // - // In scenario (1), managed code can invoke it only if it was attributed with HPCSE attribute. Thus, - // longjmp is no different than managed code doing a "throw new Exception();". - // - // In scenario (2), longjmp is no different than any other non-CSE native exception raised. - // - // In both these case, longjmp should be treated as non-CSE. Since x86 does not setup a tracker for - // it (see comment above), we pass this information (of whether the current exception is a longjmp or not) - // to this callback (from UnwindFrames) to setup the correct corruption severity. - // - // http://www.nynaeve.net/?p=105 has a brief description of how exception-safe setjmp/longjmp works. - currentSeverity = NotCorrupting; - } - { - MethodDesc * pFuncWithCEAttribute = pFunc; - Frame * pILStubFrame = NULL; - if (pFunc->IsILStub()) - { - // We must defer to the MethodDesc of the user method instead of the IL stub - // itself because the user can specify the policy on a per-method basis and - // that won't be reflected via the IL stub's MethodDesc. - pFuncWithCEAttribute = GetUserMethodForILStub(pThread, (UINT_PTR)pStack, pFunc, &pILStubFrame); - } - fCanMethodHandleException = CEHelper::CanMethodHandleException(currentSeverity, pFuncWithCEAttribute); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - #ifdef DEBUGGING_SUPPORTED LOG((LF_EH, LL_INFO1000, "COMPlusUnwindCallback: Intercept %d, pData->pFunc 0x%X, pFunc 0x%X, pData->pStack 0x%X, pStack 0x%X\n", pExInfo->m_ExceptionFlags.DebuggerInterceptInfo(), @@ -2786,24 +2691,7 @@ StackWalkAction COMPlusUnwindCallback (CrawlFrame *pCf, ThrowCallbackType *pData EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionEnter(pFunc); EH_CLAUSE_ENUMERATOR pEnumState; - unsigned EHCount; - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - if (!fCanMethodHandleException) - { - LOG((LF_EH, LL_INFO100, "COMPlusUnwindCallback - CEHelper decided not to look for exception handlers in the method(MD:%p).\n", pFunc)); - - // Set the flag to skip this frame since the CE cannot be delivered - _ASSERTE(currentSeverity == ProcessCorrupting); - - // Force EHClause count to be zero - EHCount = 0; - } - else -#endif // FEATURE_CORRUPTING_EXCEPTIONS - { - EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState); - } + unsigned EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState); if (EHCount == 0) { diff --git a/src/coreclr/src/vm/interopconverter.cpp b/src/coreclr/src/vm/interopconverter.cpp index 64312e1438214..00fa3cb6e4e8d 100644 --- a/src/coreclr/src/vm/interopconverter.cpp +++ b/src/coreclr/src/vm/interopconverter.cpp @@ -80,7 +80,7 @@ namespace //-------------------------------------------------------------------------------- // IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, ...) // Convert ObjectRef to a COM IP, based on MethodTable* pMT. -IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bSecurityCheck, BOOL bEnableCustomizedQueryInterface) +IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bEnableCustomizedQueryInterface) { CONTRACT (IUnknown*) { @@ -104,8 +104,15 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bSecuri if (TryGetComIPFromObjectRefUsingComWrappers(*poref, &pUnk)) { - pUnk.SuppressRelease(); - RETURN pUnk; + GUID iid; + pMT->GetGuid(&iid, /*bGenerateIfNotFound*/ FALSE, /*bClassic*/ FALSE); + + IUnknown* pvObj; + hr = SafeQueryInterface(pUnk, iid, &pvObj); + if (FAILED(hr)) + COMPlusThrowHR(hr); + + RETURN pvObj; } SyncBlock* pBlock = (*poref)->GetSyncBlock(); @@ -119,7 +126,6 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bSecuri CCWHolder pCCWHold = ComCallWrapper::InlineGetWrapper(poref); GetComIPFromCCW::flags flags = GetComIPFromCCW::None; - if (!bSecurityCheck) { flags |= GetComIPFromCCW::SuppressSecurityCheck; } if (!bEnableCustomizedQueryInterface) { flags |= GetComIPFromCCW::SuppressCustomizedQueryInterface; } pUnk = ComCallWrapper::GetComIPFromCCW(pCCWHold, GUID_NULL, pMT, flags); @@ -177,15 +183,20 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, ComIpType ReqIpType, ComIpType { hr = S_OK; - SafeComHolder pvObj; + IUnknown* pvObj; if (ReqIpType & ComIpType_Dispatch) { - hr = pUnk->QueryInterface(IID_IDispatch, &pvObj); + hr = SafeQueryInterface(pUnk, IID_IDispatch, &pvObj); + pUnk->Release(); } else if (ReqIpType & ComIpType_Inspectable) { - SafeComHolder pvObj; - hr = pUnk->QueryInterface(IID_IInspectable, &pvObj); + hr = SafeQueryInterface(pUnk, IID_IInspectable, &pvObj); + pUnk->Release(); + } + else + { + pvObj = pUnk; } if (FAILED(hr)) @@ -194,7 +205,7 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, ComIpType ReqIpType, ComIpType if (pFetchedIpType != NULL) *pFetchedIpType = ReqIpType; - RETURN pUnk; + RETURN pvObj; } MethodTable *pMT = (*poref)->GetMethodTable(); @@ -464,12 +475,13 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, REFIID iid, bool throwIfNoComI if (TryGetComIPFromObjectRefUsingComWrappers(*poref, &pUnk)) { - SafeComHolder pvObj; - hr = pUnk->QueryInterface(iid, &pvObj); + IUnknown* pvObj; + hr = SafeQueryInterface(pUnk, iid, &pvObj); + pUnk->Release(); if (FAILED(hr)) COMPlusThrowHR(hr); - RETURN pUnk; + RETURN pvObj; } MethodTable *pMT = (*poref)->GetMethodTable(); diff --git a/src/coreclr/src/vm/interopconverter.h b/src/coreclr/src/vm/interopconverter.h index ad6b9a0004d13..a41c169b716b5 100644 --- a/src/coreclr/src/vm/interopconverter.h +++ b/src/coreclr/src/vm/interopconverter.h @@ -113,7 +113,7 @@ enum ComIpType //-------------------------------------------------------------------------------- // IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, ...); // Convert ObjectRef to a COM IP, based on MethodTable* pMT. -IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bSecurityCheck = TRUE, BOOL bEnableCustomizedQueryInterface = TRUE); +IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bEnableCustomizedQueryInterface = TRUE); //-------------------------------------------------------------------------------- diff --git a/src/coreclr/src/vm/interoplibinterface.cpp b/src/coreclr/src/vm/interoplibinterface.cpp index 934e0bbf6fadc..9040e8176aff4 100644 --- a/src/coreclr/src/vm/interoplibinterface.cpp +++ b/src/coreclr/src/vm/interoplibinterface.cpp @@ -401,7 +401,8 @@ namespace Volatile ExtObjCxtCache::g_Instance; // Indicator for if a ComWrappers implementation is globally registered - bool g_IsGlobalComWrappersRegistered; + bool g_IsGlobalComWrappersRegisteredForMarshalling; + bool g_IsGlobalComWrappersRegisteredForTrackerSupport; // Defined handle types for the specific object uses. const HandleType InstanceHandleType{ HNDTYPE_STRONG }; @@ -469,7 +470,7 @@ namespace args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(*implPROTECTED); args[ARGNUM_2] = PTR_TO_ARGHOLDER(externalComObject); args[ARGNUM_3] = DWORD_TO_ARGHOLDER(flags); - CALL_MANAGED_METHOD(retObjRef, OBJECTREF, args); + CALL_MANAGED_METHOD_RETREF(retObjRef, OBJECTREF, args); return retObjRef; } @@ -843,7 +844,7 @@ namespace InteropLibImports HRESULT hr = S_OK; BEGIN_EXTERNAL_ENTRYPOINT(&hr) { - GCInterface::NewAddMemoryPressure(memoryInBytes); + GCInterface::AddMemoryPressure(memoryInBytes); } END_EXTERNAL_ENTRYPOINT; @@ -862,7 +863,7 @@ namespace InteropLibImports HRESULT hr = S_OK; BEGIN_EXTERNAL_ENTRYPOINT(&hr) { - GCInterface::NewRemoveMemoryPressure(memoryInBytes); + GCInterface::RemoveMemoryPressure(memoryInBytes); } END_EXTERNAL_ENTRYPOINT; @@ -1384,18 +1385,17 @@ void ComWrappersNative::MarkWrapperAsComActivated(_In_ IUnknown* wrapperMaybe) void QCALLTYPE GlobalComWrappersForMarshalling::SetGlobalInstanceRegisteredForMarshalling() { - // QCALL contracts are not used here because the managed declaration - // uses the SuppressGCTransition attribute + QCALL_CONTRACT_NO_GC_TRANSITION; - _ASSERTE(!g_IsGlobalComWrappersRegistered); - g_IsGlobalComWrappersRegistered = true; + _ASSERTE(!g_IsGlobalComWrappersRegisteredForMarshalling); + g_IsGlobalComWrappersRegisteredForMarshalling = true; } bool GlobalComWrappersForMarshalling::TryGetOrCreateComInterfaceForObject( _In_ OBJECTREF instance, _Outptr_ void** wrapperRaw) { - if (!g_IsGlobalComWrappersRegistered) + if (!g_IsGlobalComWrappersRegisteredForMarshalling) return false; // Switch to Cooperative mode since object references @@ -1420,7 +1420,7 @@ bool GlobalComWrappersForMarshalling::TryGetOrCreateObjectForComInstance( _In_ INT32 objFromComIPFlags, _Out_ OBJECTREF* objRef) { - if (!g_IsGlobalComWrappersRegistered) + if (!g_IsGlobalComWrappersRegisteredForMarshalling) return false; // Determine the true identity of the object @@ -1452,6 +1452,109 @@ bool GlobalComWrappersForMarshalling::TryGetOrCreateObjectForComInstance( } } +void QCALLTYPE GlobalComWrappersForTrackerSupport::SetGlobalInstanceRegisteredForTrackerSupport() +{ + QCALL_CONTRACT_NO_GC_TRANSITION; + + _ASSERTE(!g_IsGlobalComWrappersRegisteredForTrackerSupport); + g_IsGlobalComWrappersRegisteredForTrackerSupport = true; +} + +bool GlobalComWrappersForTrackerSupport::TryGetOrCreateComInterfaceForObject( + _In_ OBJECTREF instance, + _Outptr_ void** wrapperRaw) +{ + CONTRACTL + { + THROWS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + if (!g_IsGlobalComWrappersRegisteredForTrackerSupport) + return false; + + // Passing NULL as the ComWrappers implementation indicates using the globally registered instance + return TryGetOrCreateComInterfaceForObjectInternal( + NULL, + instance, + CreateComInterfaceFlags::CreateComInterfaceFlags_TrackerSupport, + ComWrappersScenario::TrackerSupportGlobalInstance, + wrapperRaw); +} + +bool GlobalComWrappersForTrackerSupport::TryGetOrCreateObjectForComInstance( + _In_ IUnknown* externalComObject, + _Out_ OBJECTREF* objRef) +{ + CONTRACTL + { + THROWS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + if (!g_IsGlobalComWrappersRegisteredForTrackerSupport) + return false; + + // Determine the true identity of the object + SafeComHolder identity; + { + GCX_PREEMP(); + + HRESULT hr = externalComObject->QueryInterface(IID_IUnknown, &identity); + _ASSERTE(hr == S_OK); + } + + // Passing NULL as the ComWrappers implementation indicates using the globally registered instance + return TryGetOrCreateObjectForComInstanceInternal( + NULL /*comWrappersImpl*/, + identity, + CreateObjectFlags::CreateObjectFlags_TrackerObject, + ComWrappersScenario::TrackerSupportGlobalInstance, + NULL /*wrapperMaybe*/, + objRef); +} + +IUnknown* ComWrappersNative::GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid) +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_COOPERATIVE; + PRECONDITION(CheckPointer(objectPROTECTED)); + } + CONTRACTL_END; + + ASSERT_PROTECTED(objectPROTECTED); + + SyncBlock* syncBlock = (*objectPROTECTED)->PassiveGetSyncBlock(); + if (syncBlock == nullptr) + { + return nullptr; + } + + InteropSyncBlockInfo* interopInfo = syncBlock->GetInteropInfoNoCreate(); + if (interopInfo == nullptr) + { + return nullptr; + } + + void* context; + if (interopInfo->TryGetExternalComObjectContext(&context)) + { + IUnknown* identity = reinterpret_cast(reinterpret_cast(context)->Identity); + GCX_PREEMP(); + IUnknown* result; + if (SUCCEEDED(identity->QueryInterface(riid, (void**)&result))) + { + return result; + } + } + return nullptr; +} + #endif // FEATURE_COMWRAPPERS void Interop::OnGCStarted(_In_ int nCondemnedGeneration) diff --git a/src/coreclr/src/vm/interoplibinterface.h b/src/coreclr/src/vm/interoplibinterface.h index 6a5884a66075c..3e5abda54cd6a 100644 --- a/src/coreclr/src/vm/interoplibinterface.h +++ b/src/coreclr/src/vm/interoplibinterface.h @@ -37,6 +37,9 @@ class ComWrappersNative public: // COM activation static void MarkWrapperAsComActivated(_In_ IUnknown* wrapperMaybe); + +public: // Unwrapping support + static IUnknown* GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid); }; class GlobalComWrappersForMarshalling @@ -58,6 +61,25 @@ class GlobalComWrappersForMarshalling _Out_ OBJECTREF* objRef); }; + +class GlobalComWrappersForTrackerSupport +{ +public: + // Native QCall for the ComWrappers managed type to indicate a global instance + // is registered for tracker support. This should be set if the private static member + // representing the global instance for tracker support on ComWrappers is non-null. + static void QCALLTYPE SetGlobalInstanceRegisteredForTrackerSupport(); + +public: // Functions operating on a registered global instance for tracker support + static bool TryGetOrCreateComInterfaceForObject( + _In_ OBJECTREF instance, + _Outptr_ void** wrapperRaw); + + static bool TryGetOrCreateObjectForComInstance( + _In_ IUnknown* externalComObject, + _Out_ OBJECTREF* objRef); +}; + #endif // FEATURE_COMWRAPPERS class Interop diff --git a/src/coreclr/src/vm/ipcstreamfactory.cpp b/src/coreclr/src/vm/ipcstreamfactory.cpp new file mode 100644 index 0000000000000..33d36e93de5ba --- /dev/null +++ b/src/coreclr/src/vm/ipcstreamfactory.cpp @@ -0,0 +1,206 @@ +// 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. + +#include "common.h" +#include "diagnosticsprotocol.h" +#include "ipcstreamfactory.h" + +#ifdef FEATURE_PERFTRACING + +CQuickArrayList IpcStreamFactory::s_rgpConnectionStates = CQuickArrayList(); +Volatile IpcStreamFactory::s_isShutdown = false; + +bool IpcStreamFactory::ClientConnectionState::GetIpcPollHandle(IpcStream::DiagnosticsIpc::IpcPollHandle *pIpcPollHandle, ErrorCallback callback) +{ + if (_pStream == nullptr) + { + // cache is empty, reconnect, e.g., there was a disconnect + IpcStream *pConnection = _pIpc->Connect(callback); + if (pConnection == nullptr) + { + if (callback != nullptr) + callback("Failed to connect to client connection", -1); + return false; + } + if (!DiagnosticsIpc::SendIpcAdvertise_V1(pConnection)) + { + if (callback != nullptr) + callback("Failed to send advertise message", -1); + delete pConnection; + return false; + } + + _pStream = pConnection; + } + *pIpcPollHandle = { nullptr, _pStream, 0, this }; + return true; +} + +IpcStream *IpcStreamFactory::ClientConnectionState::GetConnectedStream(ErrorCallback callback) +{ + IpcStream *pStream = _pStream; + _pStream = nullptr; + return pStream; +} + +void IpcStreamFactory::ClientConnectionState::Reset(ErrorCallback callback) +{ + delete _pStream; + _pStream = nullptr; +} + +bool IpcStreamFactory::ServerConnectionState::GetIpcPollHandle(IpcStream::DiagnosticsIpc::IpcPollHandle *pIpcPollHandle, ErrorCallback callback) +{ + *pIpcPollHandle = { _pIpc, nullptr, 0, this }; + return true; +} + +IpcStream *IpcStreamFactory::ServerConnectionState::GetConnectedStream(ErrorCallback callback) +{ + return _pIpc->Accept(callback); +} + +// noop for server +void IpcStreamFactory::ServerConnectionState::Reset(ErrorCallback) +{ + return; +} + +bool IpcStreamFactory::CreateServer(const char *const pIpcName, ErrorCallback callback) +{ + IpcStream::DiagnosticsIpc *pIpc = IpcStream::DiagnosticsIpc::Create(pIpcName, IpcStream::DiagnosticsIpc::ConnectionMode::SERVER, callback); + if (pIpc != nullptr) + { + if (pIpc->Listen(callback)) + { + s_rgpConnectionStates.Push(new ServerConnectionState(pIpc)); + return true; + } + else + { + delete pIpc; + return false; + } + } + else + { + return false; + } +} + +bool IpcStreamFactory::CreateClient(const char *const pIpcName, ErrorCallback callback) +{ + IpcStream::DiagnosticsIpc *pIpc = IpcStream::DiagnosticsIpc::Create(pIpcName, IpcStream::DiagnosticsIpc::ConnectionMode::CLIENT, callback); + if (pIpc != nullptr) + { + s_rgpConnectionStates.Push(new ClientConnectionState(pIpc)); + return true; + } + else + { + return false; + } +} + +bool IpcStreamFactory::HasActiveConnections() +{ + return !s_isShutdown && s_rgpConnectionStates.Size() > 0; +} + +void IpcStreamFactory::CloseConnections(ErrorCallback callback) +{ + for (uint32_t i = 0; i < (uint32_t)s_rgpConnectionStates.Size(); i++) + s_rgpConnectionStates[i]->Close(callback); +} + +void IpcStreamFactory::Shutdown(ErrorCallback callback) +{ + if (s_isShutdown) + return; + s_isShutdown = true; + for (uint32_t i = 0; i < (uint32_t)s_rgpConnectionStates.Size(); i++) + s_rgpConnectionStates[i]->Close(true, callback); +} + +// helper function for getting timeout +int32_t IpcStreamFactory::GetNextTimeout(int32_t currentTimeoutMs) +{ + if (currentTimeoutMs == s_pollTimeoutInfinite) + { + return s_pollTimeoutMinMs; + } + else + { + return (currentTimeoutMs >= s_pollTimeoutMaxMs) ? + s_pollTimeoutMaxMs : + (int32_t)((float)currentTimeoutMs * s_pollTimeoutFalloffFactor); + } +} + +IpcStream *IpcStreamFactory::GetNextAvailableStream(ErrorCallback callback) +{ + IpcStream *pStream = nullptr; + CQuickArrayList rgIpcPollHandles; + + int32_t pollTimeoutMs = s_pollTimeoutInfinite; + bool fConnectSuccess = true; + uint32_t nPollAttempts = 0; + + while (pStream == nullptr) + { + fConnectSuccess = true; + for (uint32_t i = 0; i < (uint32_t)s_rgpConnectionStates.Size(); i++) + { + IpcStream::DiagnosticsIpc::IpcPollHandle pollHandle = {}; + if (s_rgpConnectionStates[i]->GetIpcPollHandle(&pollHandle, callback)) + { + rgIpcPollHandles.Push(pollHandle); + } + else + { + fConnectSuccess = false; + } + } + + pollTimeoutMs = fConnectSuccess ? + s_pollTimeoutInfinite : + GetNextTimeout(pollTimeoutMs); + + int32_t retval = IpcStream::DiagnosticsIpc::Poll(rgIpcPollHandles.Ptr(), (uint32_t)rgIpcPollHandles.Size(), pollTimeoutMs, callback); + nPollAttempts++; + STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - Poll attempt: %d, timeout: %dms.\n", nPollAttempts, pollTimeoutMs); + + if (retval != 0) + { + for (uint32_t i = 0; i < (uint32_t)rgIpcPollHandles.Size(); i++) + { + switch ((IpcStream::DiagnosticsIpc::PollEvents)rgIpcPollHandles[i].revents) + { + case IpcStream::DiagnosticsIpc::PollEvents::HANGUP: + ((ConnectionState*)(rgIpcPollHandles[i].pUserData))->Reset(callback); + STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - Poll attempt: %d, connection hung up.\n", nPollAttempts); + pollTimeoutMs = s_pollTimeoutMinMs; + break; + case IpcStream::DiagnosticsIpc::PollEvents::SIGNALED: + if (pStream == nullptr) // only use first signaled stream; will get others on subsequent calls + pStream = ((ConnectionState*)(rgIpcPollHandles[i].pUserData))->GetConnectedStream(callback); + break; + case IpcStream::DiagnosticsIpc::PollEvents::ERR: + return nullptr; + default: + // TODO: Error handling + break; + } + } + } + + // clear the view + while (rgIpcPollHandles.Size() > 0) + rgIpcPollHandles.Pop(); + } + + return pStream; +} + +#endif // FEATURE_PERFTRACING \ No newline at end of file diff --git a/src/coreclr/src/vm/ipcstreamfactory.h b/src/coreclr/src/vm/ipcstreamfactory.h new file mode 100644 index 0000000000000..04d92bef84628 --- /dev/null +++ b/src/coreclr/src/vm/ipcstreamfactory.h @@ -0,0 +1,103 @@ +// 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. + +#ifndef __IPC_STREAM_FACTORY_H__ +#define __IPC_STREAM_FACTORY_H__ + +#ifdef FEATURE_PERFTRACING + +#include "diagnosticsipc.h" + +class IpcStreamFactory +{ +public: + struct ConnectionState + { + public: + ConnectionState(IpcStream::DiagnosticsIpc *pIpc) : + _pIpc(pIpc), + _pStream(nullptr) + { } + + // returns a pollable handle and performs any preparation required + // e.g., as a side-effect, will connect and advertise on reverse connections + virtual bool GetIpcPollHandle(IpcStream::DiagnosticsIpc::IpcPollHandle *pIpcPollHandle, ErrorCallback callback = nullptr) = 0; + + // Returns the signaled stream in a usable state + virtual IpcStream *GetConnectedStream(ErrorCallback callback = nullptr) = 0; + + // Resets the connection in the event of a hangup + virtual void Reset(ErrorCallback callback = nullptr) = 0; + + // closes the underlying connections + // only performs minimal cleanup if isShutdown==true + void Close(bool isShutdown = false, ErrorCallback callback = nullptr) + { + if (_pIpc != nullptr) + _pIpc->Close(isShutdown, callback); + if (_pStream != nullptr && !isShutdown) + _pStream->Close(callback); + } + + protected: + IpcStream::DiagnosticsIpc *_pIpc; + IpcStream *_pStream; + }; + + struct ClientConnectionState : public ConnectionState + { + ClientConnectionState(IpcStream::DiagnosticsIpc *pIpc) : ConnectionState(pIpc) { } + + // returns a pollable handle and performs any preparation required + bool GetIpcPollHandle(IpcStream::DiagnosticsIpc::IpcPollHandle *pIpcPollHandle, ErrorCallback callback = nullptr) override; + + // Returns the signaled stream in a usable state + IpcStream *GetConnectedStream(ErrorCallback callback = nullptr) override; + + // Resets the connection in the event of a hangup + void Reset(ErrorCallback callback = nullptr) override; + }; + + struct ServerConnectionState : public ConnectionState + { + ServerConnectionState(IpcStream::DiagnosticsIpc *pIpc) : ConnectionState(pIpc) { } + + // returns a pollable handle and performs any preparation required + bool GetIpcPollHandle(IpcStream::DiagnosticsIpc::IpcPollHandle *pIpcPollHandle, ErrorCallback callback = nullptr) override; + + // Returns the signaled stream in a usable state + IpcStream *GetConnectedStream(ErrorCallback callback = nullptr) override; + + // Resets the connection in the event of a hangup + void Reset(ErrorCallback callback = nullptr) override; + }; + + static bool CreateServer(const char *const pIpcName, ErrorCallback = nullptr); + static bool CreateClient(const char *const pIpcName, ErrorCallback = nullptr); + static IpcStream *GetNextAvailableStream(ErrorCallback = nullptr); + static bool HasActiveConnections(); + static void CloseConnections(ErrorCallback callback = nullptr); + static void Shutdown(ErrorCallback callback = nullptr); +private: + static CQuickArrayList s_rgpConnectionStates; + static Volatile s_isShutdown; + + // Polling timeout semantics + // If client connection is opted in + // and connection succeeds => set timeout to infinite + // and connection fails => set timeout to minimum and scale by falloff factor + // else => set timeout to -1 (infinite) + // + // If an agent closes its socket while we're still connected, + // Poll will return and let us know which connection hung up + static int32_t GetNextTimeout(int32_t currentTimeoutMs); + constexpr static float s_pollTimeoutFalloffFactor = 1.25; + constexpr static int32_t s_pollTimeoutInfinite = -1; + constexpr static int32_t s_pollTimeoutMinMs = 10; + constexpr static int32_t s_pollTimeoutMaxMs = 500; +}; + +#endif // FEATURE_PERFTRACING + +#endif // __IPC_STREAM_FACTORY_H__ \ No newline at end of file diff --git a/src/coreclr/src/vm/jithelpers.cpp b/src/coreclr/src/vm/jithelpers.cpp index 8e5d20d993ff6..38a6af10e6dfa 100644 --- a/src/coreclr/src/vm/jithelpers.cpp +++ b/src/coreclr/src/vm/jithelpers.cpp @@ -4185,23 +4185,6 @@ HCIMPL1(void, IL_Throw, Object* obj) } } -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - if (!g_pConfig->LegacyCorruptedStateExceptionsPolicy()) - { - // Within the VM, we could have thrown and caught a managed exception. This is done by - // RaiseTheException that will flag that exception's corruption severity to be used - // incase it leaks out to managed code. - // - // If it does not leak out, but ends up calling into managed code that throws, - // we will come here. In such a case, simply reset the corruption-severity - // since we want the exception being thrown to have its correct severity set - // when CLR's managed code exception handler sets it. - - ThreadExceptionState *pExState = GetThread()->GetExceptionState(); - pExState->SetLastActiveExceptionCorruptionSeverity(NotSet); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - RaiseTheExceptionInternalOnly(oref, FALSE); HELPER_METHOD_FRAME_END(); diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 312afabe00e6b..94f3d1865754d 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -66,6 +66,10 @@ #include "perfmap.h" #endif +#ifdef FEATURE_PGO +#include "pgo.h" +#endif + #include "tailcallhelp.h" // The Stack Overflow probe takes place in the COOPERATIVE_TRANSITION_BEGIN() macro @@ -99,6 +103,27 @@ GARY_IMPL(VMHELPDEF, hlpDynamicFuncTable, DYNAMIC_CORINFO_HELP_COUNT); #else // DACCESS_COMPILE +uint64_t g_cbILJitted = 0; +uint32_t g_cMethodsJitted = 0; + +#ifndef CROSSGEN_COMPILE +FCIMPL0(INT64, GetJittedBytes) +{ + FCALL_CONTRACT; + + return g_cbILJitted; +} +FCIMPLEND + +FCIMPL0(INT32, GetJittedMethodsCount) +{ + FCALL_CONTRACT; + + return g_cMethodsJitted; +} +FCIMPLEND +#endif + /*********************************************************************/ inline CORINFO_MODULE_HANDLE GetScopeHandle(MethodDesc* method) @@ -11786,8 +11811,6 @@ HRESULT CEEJitInfo::allocMethodBlockCounts ( JIT_TO_EE_TRANSITION(); -#ifdef FEATURE_PREJIT - // We need to know the code size. Typically we can get the code size // from m_ILHeader. For dynamic methods, m_ILHeader will be NULL, so // for that case we need to use DynamicResolver to get the code size. @@ -11805,11 +11828,16 @@ HRESULT CEEJitInfo::allocMethodBlockCounts ( codeSize = m_ILHeader->GetCodeSize(); } +#ifdef FEATURE_PREJIT *pBlockCounts = m_pMethodBeingCompiled->GetLoaderModule()->AllocateMethodBlockCounts(m_pMethodBeingCompiled->GetMemberDef(), count, codeSize); hr = (*pBlockCounts != nullptr) ? S_OK : E_OUTOFMEMORY; #else // FEATURE_PREJIT +#ifdef FEATURE_PGO + hr = PgoManager::allocMethodBlockCounts(m_pMethodBeingCompiled, count, pBlockCounts, codeSize); +#else _ASSERTE(!"allocMethodBlockCounts not implemented on CEEJitInfo!"); hr = E_NOTIMPL; +#endif // !FEATURE_PGO #endif // !FEATURE_PREJIT EE_TO_JIT_TRANSITION(); @@ -11826,9 +11854,55 @@ HRESULT CEEJitInfo::getMethodBlockCounts ( UINT32 * pNumRuns ) { - LIMITED_METHOD_CONTRACT; + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + HRESULT hr = E_FAIL; + *pCount = 0; + *pBlockCounts = NULL; + *pNumRuns = 0; + + JIT_TO_EE_TRANSITION(); + +#ifdef FEATURE_PGO + + // For now, only return the info for the method being jitted. + // Will need to fix this to gain access to pgo data for inlinees. + MethodDesc* pMD = (MethodDesc*)ftnHnd; + + if (pMD == m_pMethodBeingCompiled) + { + unsigned codeSize = 0; + if (pMD->IsDynamicMethod()) + { + unsigned stackSize, ehSize; + CorInfoOptions options; + DynamicResolver * pResolver = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetResolver(); + pResolver->GetCodeInfo(&codeSize, &stackSize, &options, &ehSize); + } + else + { + codeSize = m_ILHeader->GetCodeSize(); + } + + hr = PgoManager::getMethodBlockCounts(pMD, codeSize, pCount, pBlockCounts, pNumRuns); + } + else + { + hr = E_NOTIMPL; + } + +#else _ASSERTE(!"getMethodBlockCounts not implemented on CEEJitInfo!"); - return E_NOTIMPL; + hr = E_NOTIMPL; +#endif + + EE_TO_JIT_TRANSITION(); + + return hr; } void CEEJitInfo::allocMem ( @@ -12551,6 +12625,30 @@ CORJIT_FLAGS GetCompileFlags(MethodDesc * ftn, CORJIT_FLAGS flags, CORINFO_METHO flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); } +#ifdef FEATURE_PGO + + if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_WritePGOData) > 0) + { + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); + } + else if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TieredPGO) > 0) + && flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0)) + { + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); + } + + if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ReadPGOData) > 0) + { + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); + } + else if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TieredPGO) > 0) + && flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER1)) + { + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); + } + +#endif + return flags; } @@ -12585,10 +12683,6 @@ void ThrowExceptionForJit(HRESULT res) } // ******************************************************************** -#ifdef _DEBUG -LONG g_JitCount = 0; -#endif - //#define PERF_TRACK_METHOD_JITTIMES #ifdef TARGET_AMD64 BOOL g_fAllowRel32 = TRUE; @@ -12965,7 +13059,6 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, } #ifdef _DEBUG - FastInterlockIncrement(&g_JitCount); static BOOL fHeartbeat = -1; if (fHeartbeat == -1) @@ -12975,6 +13068,9 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, printf("."); #endif // _DEBUG + FastInterlockExchangeAddLong((LONG64*)&g_cbILJitted, methodInfo.ILCodeSize); + FastInterlockIncrement((LONG*)&g_cMethodsJitted); + COOPERATIVE_TRANSITION_END(); return ret; } diff --git a/src/coreclr/src/vm/jitinterface.h b/src/coreclr/src/vm/jitinterface.h index faf4300a5c66c..0e52a1eccc572 100644 --- a/src/coreclr/src/vm/jitinterface.h +++ b/src/coreclr/src/vm/jitinterface.h @@ -1684,5 +1684,8 @@ CORJIT_FLAGS GetDebuggerCompileFlags(Module* pModule, CORJIT_FLAGS flags); bool __stdcall TrackAllocationsEnabled(); +FCDECL0(INT64, GetJittedBytes); +FCDECL0(INT32, GetJittedMethodsCount); + #endif // JITINTERFACE_H diff --git a/src/coreclr/src/vm/listlock.h b/src/coreclr/src/vm/listlock.h index 0fdaf6e68c91c..2b135b19d784b 100644 --- a/src/coreclr/src/vm/listlock.h +++ b/src/coreclr/src/vm/listlock.h @@ -55,10 +55,6 @@ class ListLockEntryBase HRESULT m_hrResultCode; LOADERHANDLE m_hInitException; PTR_LoaderAllocator m_pLoaderAllocator; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Field to maintain the corruption severity of the exception - CorruptionSeverity m_CorruptionSeverity; -#endif // FEATURE_CORRUPTING_EXCEPTIONS ListLockEntryBase(List_t *pList, ELEMENT data, const char *description = NULL) : m_deadlock(description), @@ -72,10 +68,6 @@ class ListLockEntryBase m_hrResultCode(S_FALSE), m_hInitException(NULL), m_pLoaderAllocator(dac_cast(nullptr)) -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , - m_CorruptionSeverity(NotCorrupting) -#endif // FEATURE_CORRUPTING_EXCEPTIONS { WRAPPER_NO_CONTRACT; } diff --git a/src/coreclr/src/vm/marshalnative.cpp b/src/coreclr/src/vm/marshalnative.cpp index 56657944eb8a5..75c1e514420f1 100644 --- a/src/coreclr/src/vm/marshalnative.cpp +++ b/src/coreclr/src/vm/marshalnative.cpp @@ -558,7 +558,7 @@ FCIMPL2(LPVOID, MarshalNative::GCHandleInternalAlloc, Object *obj, int type) OBJECTREF objRef(obj); - assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT); + assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_NATIVE_COM); if (CORProfilerTrackGC()) { @@ -923,7 +923,7 @@ FCIMPL4(IUnknown*, MarshalNative::GetComInterfaceForObjectNative, Object* orefUN if (fOnlyInContext && !IsObjectInContext(&oref)) retVal = NULL; else - retVal = GetComIPFromObjectRef(&oref, th.GetMethodTable(), TRUE, bEnableCustomizedQueryInterface); + retVal = GetComIPFromObjectRef(&oref, th.GetMethodTable(), bEnableCustomizedQueryInterface); HELPER_METHOD_FRAME_END(); return retVal; diff --git a/src/coreclr/src/vm/method.cpp b/src/coreclr/src/vm/method.cpp index 314b777052cd8..690051b905bf8 100644 --- a/src/coreclr/src/vm/method.cpp +++ b/src/coreclr/src/vm/method.cpp @@ -5307,6 +5307,23 @@ FARPROC NDirectMethodDesc::FindEntryPointWithMangling(NATIVE_LIBRARY_HANDLE hMod return pFunc; } + +FARPROC NDirectMethodDesc::FindEntryPointWithSuffix(NATIVE_LIBRARY_HANDLE hMod, PTR_CUTF8 entryPointName, char suffix) const +{ + // Allocate space for a copy of the entry point name. + DWORD entryPointWithSuffixLen = (DWORD)(strlen(entryPointName) + 1); // +1 for charset decorations + int dstbufsize = (int)(sizeof(char) * (entryPointWithSuffixLen + 1)); // +1 for the null terminator + LPSTR entryPointWithSuffix = ((LPSTR)_alloca(dstbufsize)); + + // Copy the name so we can mangle it. + strcpy_s(entryPointWithSuffix, dstbufsize, entryPointName); + entryPointWithSuffix[entryPointWithSuffixLen] = '\0'; // Null terminator + entryPointWithSuffix[entryPointWithSuffixLen - 1] = suffix; // Charset suffix + + // Look for entry point with the suffix based on charset + return FindEntryPointWithMangling(hMod, entryPointWithSuffix); +} + #endif //******************************************************************************* @@ -5332,39 +5349,27 @@ LPVOID NDirectMethodDesc::FindEntryPoint(NATIVE_LIBRARY_HANDLE hMod) const return reinterpret_cast(GetProcAddress(hMod, (LPCSTR)(size_t)((UINT16)ordinal))); } - // Just look for the user-provided name without charset suffixes. - // If it is unicode fcn, we are going - // to need to check for the 'W' API because it takes precedence over the - // unmangled one (on NT some APIs have unmangled ANSI exports). - FARPROC pFunc = FindEntryPointWithMangling(hMod, funcName); - if ((pFunc != NULL && IsNativeAnsi()) || IsNativeNoMangled()) + FARPROC pFunc = NULL; + if (IsNativeNoMangled()) { - return reinterpret_cast(pFunc); + // Look for the user-provided entry point name only + pFunc = FindEntryPointWithMangling(hMod, funcName); } - - DWORD probedEntrypointNameLength = (DWORD)(strlen(funcName) + 1); // +1 for charset decorations - - // Allocate space for a copy of the entry point name. - int dstbufsize = (int)(sizeof(char) * (probedEntrypointNameLength + 1)); // +1 for the null terminator - - LPSTR szProbedEntrypointName = ((LPSTR)_alloca(dstbufsize)); - - // Copy the name so we can mangle it. - strcpy_s(szProbedEntrypointName, dstbufsize, funcName); - szProbedEntrypointName[probedEntrypointNameLength] = '\0'; // Add an extra '\0'. - - if(!IsNativeNoMangled()) + else if (IsNativeAnsi()) { - szProbedEntrypointName[probedEntrypointNameLength - 1] = IsNativeAnsi() ? 'A' : 'W'; - - FARPROC pProbedFunc = FindEntryPointWithMangling(hMod, szProbedEntrypointName); - - if(pProbedFunc != NULL) - { - pFunc = pProbedFunc; - } - - probedEntrypointNameLength++; + // For ANSI, look for the user-provided entry point name first. + // If that does not exist, try the charset suffix. + pFunc = FindEntryPointWithMangling(hMod, funcName); + if (pFunc == NULL) + pFunc = FindEntryPointWithSuffix(hMod, funcName, 'A'); + } + else + { + // For Unicode, look for the entry point name with the charset suffix first. + // The 'W' API takes precedence over the undecorated one. + pFunc = FindEntryPointWithSuffix(hMod, funcName, 'W'); + if (pFunc == NULL) + pFunc = FindEntryPointWithMangling(hMod, funcName); } return reinterpret_cast(pFunc); diff --git a/src/coreclr/src/vm/method.hpp b/src/coreclr/src/vm/method.hpp index 8870e7a5f5a23..ba5f6ae096778 100644 --- a/src/coreclr/src/vm/method.hpp +++ b/src/coreclr/src/vm/method.hpp @@ -3150,6 +3150,7 @@ class NDirectMethodDesc : public MethodDesc #ifdef TARGET_WINDOWS private: FARPROC FindEntryPointWithMangling(NATIVE_LIBRARY_HANDLE mod, PTR_CUTF8 entryPointName) const; + FARPROC FindEntryPointWithSuffix(NATIVE_LIBRARY_HANDLE mod, PTR_CUTF8 entryPointName, char suffix) const; #endif public: diff --git a/src/coreclr/src/vm/methodtable.cpp b/src/coreclr/src/vm/methodtable.cpp index 1706f0c327c4e..2332f44e98371 100644 --- a/src/coreclr/src/vm/methodtable.cpp +++ b/src/coreclr/src/vm/methodtable.cpp @@ -3123,39 +3123,6 @@ BOOL MethodTable::RunClassInitEx(OBJECTREF *pThrowable) // a subclass of Error *pThrowable = GET_THROWABLE(); _ASSERTE(fRet == FALSE); - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // If active thread state does not have a CorruptionSeverity set for the exception, - // then set one up based upon the current exception code and/or the throwable. - // - // When can we be here and current exception tracker may not have corruption severity set? - // Incase of SO in managed code, SO is never seen by CLR's exception handler for managed code - // and if this happens in cctor, we can end up here without the corruption severity set. - Thread *pThread = GetThread(); - _ASSERTE(pThread != NULL); - ThreadExceptionState *pCurTES = pThread->GetExceptionState(); - _ASSERTE(pCurTES != NULL); - if (pCurTES->GetLastActiveExceptionCorruptionSeverity() == NotSet) - { - if (CEHelper::IsProcessCorruptedStateException(GetCurrentExceptionCode()) || - CEHelper::IsProcessCorruptedStateException(*pThrowable)) - { - // Process Corrupting - pCurTES->SetLastActiveExceptionCorruptionSeverity(ProcessCorrupting); - LOG((LF_EH, LL_INFO100, "MethodTable::RunClassInitEx - Exception treated as ProcessCorrupting.\n")); - } - else - { - // Not Corrupting - pCurTES->SetLastActiveExceptionCorruptionSeverity(NotCorrupting); - LOG((LF_EH, LL_INFO100, "MethodTable::RunClassInitEx - Exception treated as non-corrupting.\n")); - } - } - else - { - LOG((LF_EH, LL_INFO100, "MethodTable::RunClassInitEx - Exception already has corruption severity set.\n")); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS } EX_END_CATCH(SwallowAllExceptions) @@ -3289,17 +3256,7 @@ void MethodTable::DoRunClassInitThrowing() ((EXCEPTIONREF)(gc.pThrowable))->ClearStackTraceForThrow(); } - // - // Specify the corruption severity to be used to raise this exception in COMPlusThrow below. - // This will ensure that when the exception is seen by the managed code personality routine, - // it will setup the correct corruption severity in the exception tracker. - // - - COMPlusThrow(gc.pThrowable -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , pEntry->m_CorruptionSeverity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + COMPlusThrow(gc.pThrowable); } description = ".cctor lock"; @@ -3389,21 +3346,7 @@ void MethodTable::DoRunClassInitThrowing() pEntry->m_hrResultCode = E_FAIL; SetClassInitError(); - #ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Save the corruption severity of the exception so that if the type system - // attempts to pick it up from its cache list and throw again, it should - // treat the exception as corrupting, if applicable. - pEntry->m_CorruptionSeverity = pThread->GetExceptionState()->GetLastActiveExceptionCorruptionSeverity(); - - // We should be having a valid corruption severity at this point - _ASSERTE(pEntry->m_CorruptionSeverity != NotSet); - #endif // FEATURE_CORRUPTING_EXCEPTIONS - - COMPlusThrow(gc.pThrowable - #ifdef FEATURE_CORRUPTING_EXCEPTIONS - , pEntry->m_CorruptionSeverity - #endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + COMPlusThrow(gc.pThrowable); } GCPROTECT_END(); @@ -8674,7 +8617,7 @@ MethodDesc *MethodTable::MethodDataInterfaceImpl::GetImplMethodDesc(UINT32 slotN if (implSlotNumber == INVALID_SLOT_NUMBER) { return NULL; } - return m_pImpl->GetImplMethodDesc(MapToImplSlotNumber(slotNumber)); + return m_pImpl->GetImplMethodDesc(implSlotNumber); } //========================================================================================== @@ -8685,7 +8628,7 @@ void MethodTable::MethodDataInterfaceImpl::InvalidateCachedVirtualSlot(UINT32 sl if (implSlotNumber == INVALID_SLOT_NUMBER) { return; } - return m_pImpl->InvalidateCachedVirtualSlot(MapToImplSlotNumber(slotNumber)); + return m_pImpl->InvalidateCachedVirtualSlot(implSlotNumber); } //========================================================================================== diff --git a/src/coreclr/src/vm/nativeimage.cpp b/src/coreclr/src/vm/nativeimage.cpp index 7cda61993ddb9..e181bfb06446f 100644 --- a/src/coreclr/src/vm/nativeimage.cpp +++ b/src/coreclr/src/vm/nativeimage.cpp @@ -61,14 +61,24 @@ void NativeImage::Initialize(READYTORUN_HEADER *pHeader, LoaderAllocator *pLoade HENUMInternal assemblyEnum; HRESULT hr = m_pManifestMetadata->EnumAllInit(mdtAssemblyRef, &assemblyEnum); mdAssemblyRef assemblyRef; - int assemblyIndex = 0; + m_manifestAssemblyCount = 0; while (m_pManifestMetadata->EnumNext(&assemblyEnum, &assemblyRef)) { LPCSTR assemblyName; hr = m_pManifestMetadata->GetAssemblyRefProps(assemblyRef, NULL, NULL, &assemblyName, NULL, NULL, NULL, NULL); - m_assemblySimpleNameToIndexMap.Add(AssemblyNameIndex(assemblyName, assemblyIndex)); - assemblyIndex++; + m_assemblySimpleNameToIndexMap.Add(AssemblyNameIndex(assemblyName, m_manifestAssemblyCount)); + m_manifestAssemblyCount++; } + + // When a composite image contributes to a larger version bubble, its manifest assembly + // count may exceed its component assembly count as it may contain references to + // assemblies outside of the composite image that are part of its version bubble. + _ASSERTE(m_manifestAssemblyCount >= m_componentAssemblyCount); + + S_SIZE_T dwAllocSize = S_SIZE_T(sizeof(PTR_Assembly)) * S_SIZE_T(m_manifestAssemblyCount); + + // Note: Memory allocated on loader heap is zero filled + m_pNativeMetadataAssemblyRefMap = (PTR_Assembly*)pamTracker->Track(pLoaderAllocator->GetLowFrequencyHeap()->AllocMem(dwAllocSize)); } NativeImage::~NativeImage() @@ -115,7 +125,7 @@ NativeImage *NativeImage::Open( #endif #ifndef DACCESS_COMPILE -Assembly *NativeImage::LoadComponentAssembly(uint32_t rowid) +Assembly *NativeImage::LoadManifestAssembly(uint32_t rowid) { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/src/vm/nativeimage.h b/src/coreclr/src/vm/nativeimage.h index 2c3f538043bb0..323a509ecbc83 100644 --- a/src/coreclr/src/vm/nativeimage.h +++ b/src/coreclr/src/vm/nativeimage.h @@ -62,9 +62,11 @@ class NativeImage ReadyToRunInfo *m_pReadyToRunInfo; IMDInternalImport *m_pManifestMetadata; PEImageLayout *m_pImageLayout; + PTR_Assembly *m_pNativeMetadataAssemblyRefMap; IMAGE_DATA_DIRECTORY *m_pComponentAssemblies; uint32_t m_componentAssemblyCount; + uint32_t m_manifestAssemblyCount; SHash m_assemblySimpleNameToIndexMap; Crst m_eagerFixupsLock; @@ -93,8 +95,10 @@ class NativeImage uint32_t GetComponentAssemblyCount() const { return m_componentAssemblyCount; } ReadyToRunInfo *GetReadyToRunInfo() const { return m_pReadyToRunInfo; } IMDInternalImport *GetManifestMetadata() const { return m_pManifestMetadata; } + uint32_t GetManifestAssemblyCount() const { return m_manifestAssemblyCount; } + PTR_Assembly *GetManifestMetadataAssemblyRefMap() { return m_pNativeMetadataAssemblyRefMap; } - Assembly *LoadComponentAssembly(uint32_t rowid); + Assembly *LoadManifestAssembly(uint32_t rowid); PTR_READYTORUN_CORE_HEADER GetComponentAssemblyHeader(LPCUTF8 assemblySimpleName); diff --git a/src/coreclr/src/vm/object.cpp b/src/coreclr/src/vm/object.cpp index 836911433f126..06e7bb6c8bf67 100644 --- a/src/coreclr/src/vm/object.cpp +++ b/src/coreclr/src/vm/object.cpp @@ -1872,7 +1872,7 @@ void ThreadBaseObject::SetInternal(Thread *it) // Now the native Thread will only be destroyed after the managed Thread is collected. // Tell the GC that the managed Thread actually represents much more memory. - GCInterface::NewAddMemoryPressure(sizeof(Thread)); + GCInterface::AddMemoryPressure(sizeof(Thread)); } void ThreadBaseObject::ClearInternal() @@ -1881,7 +1881,7 @@ void ThreadBaseObject::ClearInternal() _ASSERTE(m_InternalThread != NULL); m_InternalThread = NULL; - GCInterface::NewRemoveMemoryPressure(sizeof(Thread)); + GCInterface::RemoveMemoryPressure(sizeof(Thread)); } #endif // #ifndef DACCESS_COMPILE diff --git a/src/coreclr/src/vm/pefile.cpp b/src/coreclr/src/vm/pefile.cpp index 7da14c95cf3a8..ae9c966cb7983 100644 --- a/src/coreclr/src/vm/pefile.cpp +++ b/src/coreclr/src/vm/pefile.cpp @@ -295,12 +295,15 @@ void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==F if (GetILimage()->IsFile()) { #ifdef TARGET_UNIX - if (GetILimage()->IsILOnly()) + bool loadILImage = GetILimage()->IsILOnly(); +#else // TARGET_UNIX + bool loadILImage = GetILimage()->IsILOnly() && GetILimage()->IsInBundle(); +#endif // TARGET_UNIX + if (loadILImage) { GetILimage()->Load(); } else -#endif // TARGET_UNIX { GetILimage()->LoadFromMapped(); } diff --git a/src/coreclr/src/vm/peimage.cpp b/src/coreclr/src/vm/peimage.cpp index 7dc580fe8f8d8..be06ebc837a14 100644 --- a/src/coreclr/src/vm/peimage.cpp +++ b/src/coreclr/src/vm/peimage.cpp @@ -973,7 +973,7 @@ PTR_PEImageLayout PEImage::GetLayoutInternal(DWORD imageLayoutMask,DWORD flags) BOOL bIsFlatLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_FLAT) != 0); #if !defined(TARGET_UNIX) - if (bIsMappedLayoutSuitable) + if (!IsInBundle() && bIsMappedLayoutSuitable) { bIsFlatLayoutSuitable = FALSE; } @@ -1183,7 +1183,14 @@ void PEImage::Load() } #ifdef TARGET_UNIX - if (m_pLayouts[IMAGE_FLAT] != NULL + bool canUseLoadedFlat = true; +#else + bool canUseLoadedFlat = IsInBundle(); +#endif // TARGET_UNIX + + + if (canUseLoadedFlat + && m_pLayouts[IMAGE_FLAT] != NULL && m_pLayouts[IMAGE_FLAT]->CheckILOnlyFormat() && !m_pLayouts[IMAGE_FLAT]->HasWriteableSections()) { @@ -1200,7 +1207,6 @@ void PEImage::Load() SetLayout(IMAGE_LOADED, m_pLayouts[IMAGE_FLAT]); } else -#endif // TARGET_UNIX { if(!IsFile()) { @@ -1328,19 +1334,19 @@ HANDLE PEImage::GetFileHandle() { ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); - m_hFile=WszCreateFile((LPCWSTR) m_path, - GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + m_hFile=WszCreateFile((LPCWSTR) GetPathToLoad(), + GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); } if (m_hFile == INVALID_HANDLE_VALUE) { #if !defined(DACCESS_COMPILE) - EEFileLoadException::Throw(m_path, HRESULT_FROM_WIN32(GetLastError())); + EEFileLoadException::Throw(GetPathToLoad(), HRESULT_FROM_WIN32(GetLastError())); #else // defined(DACCESS_COMPILE) ThrowLastError(); #endif // !defined(DACCESS_COMPILE) @@ -1374,14 +1380,14 @@ HRESULT PEImage::TryOpenFile() if (m_hFile!=INVALID_HANDLE_VALUE) return S_OK; { - ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); - m_hFile=WszCreateFile((LPCWSTR) m_path, - GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); + m_hFile=WszCreateFile((LPCWSTR)GetPathToLoad(), + GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); } if (m_hFile != INVALID_HANDLE_VALUE) return S_OK; diff --git a/src/coreclr/src/vm/peimage.h b/src/coreclr/src/vm/peimage.h index 1edf05d8ec217..2a9b0b76ac10a 100644 --- a/src/coreclr/src/vm/peimage.h +++ b/src/coreclr/src/vm/peimage.h @@ -19,6 +19,7 @@ #include "peimagelayout.h" #include "sstring.h" #include "holder.h" +#include class SimpleRWLock; // -------------------------------------------------------------------------------- @@ -102,7 +103,8 @@ class PEImage #endif // !TARGET_UNIX static PTR_PEImage OpenImage( LPCWSTR pPath, - MDInternalImportFlags flags = MDInternalImport_Default); + MDInternalImportFlags flags = MDInternalImport_Default, + BundleFileLocation bundleFileLocation = BundleFileLocation::Invalid()); // clones the image with new flags (this is pretty much about cached / noncached difference) @@ -146,8 +148,13 @@ class PEImage // Accessors const SString &GetPath(); + const SString& GetPathToLoad(); BOOL IsFile(); + BOOL IsInBundle() const; HANDLE GetFileHandle(); + INT64 GetOffset() const; + INT64 GetSize() const; + void SetFileHandle(HANDLE hFile); HRESULT TryOpenFile(); @@ -237,7 +244,7 @@ class PEImage // Private routines // ------------------------------------------------------------ - void Init(LPCWSTR pPath); + void Init(LPCWSTR pPath, BundleFileLocation bundleFileLocation); void Init(IStream* pStream, UINT64 uStreamAsmId, DWORD dwModuleId, BOOL resourceFile); @@ -273,6 +280,10 @@ class PEImage SString m_path; LONG m_refCount; + BundleFileLocation m_bundleFileLocation; // If this image is located within a single-file bundle, + // the location within the bundle. If m_bundleFileLocation is vaild, + // it takes precedence over m_path for loading. + // This variable will have the data of module name. // It is only used by DAC to remap fusion loaded modules back to // disk IL. This really is a workaround. The real fix is for fusion loader diff --git a/src/coreclr/src/vm/peimage.inl b/src/coreclr/src/vm/peimage.inl index 03d8bc229ce05..eebae16e15f7a 100644 --- a/src/coreclr/src/vm/peimage.inl +++ b/src/coreclr/src/vm/peimage.inl @@ -33,6 +33,33 @@ inline const SString &PEImage::GetPath() return m_path; } +inline const SString& PEImage::GetPathToLoad() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return IsInBundle() ? m_bundleFileLocation.Path() : m_path; +} + +inline INT64 PEImage::GetOffset() const +{ + LIMITED_METHOD_CONTRACT; + + return m_bundleFileLocation.Offset; +} + +inline BOOL PEImage::IsInBundle() const +{ + LIMITED_METHOD_CONTRACT; + + return m_bundleFileLocation.IsValid(); +} + +inline INT64 PEImage::GetSize() const +{ + LIMITED_METHOD_CONTRACT; + return m_bundleFileLocation.Size; +} + inline void PEImage::SetModuleFileNameHintForDAC() { LIMITED_METHOD_DAC_CONTRACT; @@ -71,7 +98,7 @@ inline BOOL PEImage::IsFile() { WRAPPER_NO_CONTRACT; - return !m_path.IsEmpty(); + return !GetPathToLoad().IsEmpty(); } #ifndef DACCESS_COMPILE @@ -433,7 +460,7 @@ inline CHECK PEImage::CheckFormat() CHECK_OK; } -inline void PEImage::Init(LPCWSTR pPath) +inline void PEImage::Init(LPCWSTR pPath, BundleFileLocation bundleFileLocation) { CONTRACTL { @@ -442,8 +469,10 @@ inline void PEImage::Init(LPCWSTR pPath) MODE_ANY; } CONTRACTL_END; + m_path = pPath; m_path.Normalize(); + m_bundleFileLocation = bundleFileLocation; SetModuleFileNameHintForDAC(); } #ifndef DACCESS_COMPILE @@ -475,14 +504,14 @@ inline PTR_PEImage PEImage::FindByPath(LPCWSTR pPath) } /* static */ -inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags /* = MDInternalImport_Default */) +inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags /* = MDInternalImport_Default */, BundleFileLocation bundleFileLocation) { BOOL fUseCache = !((flags & MDInternalImport_NoCache) == MDInternalImport_NoCache); if (!fUseCache) { PEImageHolder pImage(new PEImage); - pImage->Init(pPath); + pImage->Init(pPath, bundleFileLocation); return dac_cast(pImage.Extract()); } @@ -504,7 +533,7 @@ inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags if (flags & MDInternalImport_TrustedNativeImage) pImage->SetIsTrustedNativeImage(); #endif - pImage->Init(pPath); + pImage->Init(pPath, bundleFileLocation); pImage->AddToHashMap(); return dac_cast(pImage.Extract()); diff --git a/src/coreclr/src/vm/peimagelayout.cpp b/src/coreclr/src/vm/peimagelayout.cpp index 79739716da430..33032108e7e3e 100644 --- a/src/coreclr/src/vm/peimagelayout.cpp +++ b/src/coreclr/src/vm/peimagelayout.cpp @@ -40,6 +40,17 @@ PEImageLayout* PEImageLayout::LoadFromFlat(PEImageLayout* pflatimage) return new ConvertedImageLayout(pflatimage); } +PEImageLayout* PEImageLayout::LoadConverted(PEImage* pOwner) +{ + STANDARD_VM_CONTRACT; + + PEImageLayoutHolder pFlat(new FlatImageLayout(pOwner)); + if (!pFlat->CheckFormat()) + ThrowHR(COR_E_BADIMAGEFORMAT); + + return new ConvertedImageLayout(pFlat); +} + PEImageLayout* PEImageLayout::Load(PEImage* pOwner, BOOL bNTSafeLoad, BOOL bThrowOnError) { STANDARD_VM_CONTRACT; @@ -47,6 +58,11 @@ PEImageLayout* PEImageLayout::Load(PEImage* pOwner, BOOL bNTSafeLoad, BOOL bThro #if defined(CROSSGEN_COMPILE) || defined(TARGET_UNIX) return PEImageLayout::Map(pOwner); #else + if (pOwner->IsInBundle()) + { + return PEImageLayout::LoadConverted(pOwner); + } + PEImageLayoutHolder pAlloc(new LoadedImageLayout(pOwner,bNTSafeLoad,bThrowOnError)); if (pAlloc->GetBase()==NULL) return NULL; @@ -83,11 +99,7 @@ PEImageLayout* PEImageLayout::Map(PEImage* pOwner) if (pAlloc->GetBase()==NULL) { //cross-platform or a bad image - PEImageLayoutHolder pFlat(new FlatImageLayout(pOwner)); - if (!pFlat->CheckFormat()) - ThrowHR(COR_E_BADIMAGEFORMAT); - - pAlloc=new ConvertedImageLayout(pFlat); + pAlloc = LoadConverted(pOwner); } else if(!pAlloc->CheckFormat()) @@ -393,8 +405,8 @@ ConvertedImageLayout::ConvertedImageLayout(PEImageLayout* source) m_FileMap.Assign(WszCreateFileMapping(INVALID_HANDLE_VALUE, NULL, - PAGE_READWRITE, 0, - source->GetVirtualSize(), NULL)); + PAGE_READWRITE, 0, + source->GetVirtualSize(), NULL)); if (m_FileMap == NULL) ThrowLastError(); @@ -428,6 +440,8 @@ MappedImageLayout::MappedImageLayout(PEImage* pOwner) m_pOwner=pOwner; HANDLE hFile = pOwner->GetFileHandle(); + INT64 offset = pOwner->GetOffset(); + INT64 size = pOwner->GetSize(); // If mapping was requested, try to do SEC_IMAGE mapping LOG((LF_LOADER, LL_INFO100, "PEImage: Opening OS mapped %S (hFile %p)\n", (LPCWSTR) GetPath(), hFile)); @@ -459,21 +473,24 @@ MappedImageLayout::MappedImageLayout(PEImage* pOwner) ThrowWin32(dwLastError); } -#endif // CROSSGEN_COMPILE +#endif // !CROSSGEN_COMPILE return; } + DWORD offsetLowPart = (DWORD)offset; + DWORD offsetHighPart = (DWORD)(offset >> 32); + #ifdef _DEBUG // Force relocs by occuping the preferred base while the actual mapping is performed CLRMapViewHolder forceRelocs; if (PEDecoder::GetForceRelocs()) { - forceRelocs.Assign(CLRMapViewOfFile(m_FileMap, 0, 0, 0, 0)); + forceRelocs.Assign(CLRMapViewOfFile(m_FileMap, 0, offsetHighPart, offsetLowPart, (SIZE_T)size)); } #endif // _DEBUG - m_FileView.Assign(CLRMapViewOfFile(m_FileMap, 0, 0, 0, 0)); + m_FileView.Assign(CLRMapViewOfFile(m_FileMap, 0, offsetHighPart, offsetLowPart, (SIZE_T)size)); if (m_FileView == NULL) ThrowLastError(); IfFailThrow(Init((void *) m_FileView)); @@ -502,7 +519,7 @@ MappedImageLayout::MappedImageLayout(PEImage* pOwner) } } else -#endif +#endif // CROSSGEN_COMPILE if (!IsNativeMachineFormat() && !IsI386()) { //can't rely on the image @@ -529,7 +546,7 @@ MappedImageLayout::MappedImageLayout(PEImage* pOwner) #else //!TARGET_UNIX #ifndef CROSSGEN_COMPILE - m_LoadedFile = PAL_LOADLoadPEFile(hFile); + m_LoadedFile = PAL_LOADLoadPEFile(hFile, offset); if (m_LoadedFile == NULL) { @@ -612,13 +629,19 @@ FlatImageLayout::FlatImageLayout(PEImage* pOwner) m_pOwner=pOwner; HANDLE hFile = pOwner->GetFileHandle(); + INT64 offset = pOwner->GetOffset(); + INT64 size = pOwner->GetSize(); LOG((LF_LOADER, LL_INFO100, "PEImage: Opening flat %S\n", (LPCWSTR) GetPath())); - COUNT_T size = SafeGetFileSize(hFile, NULL); - if (size == 0xffffffff && GetLastError() != NOERROR) + // If a size is not specified, load the whole file + if (size == 0) { - ThrowLastError(); + size = SafeGetFileSize(hFile, NULL); + if (size == 0xffffffff && GetLastError() != NOERROR) + { + ThrowLastError(); + } } // It's okay if resource files are length zero @@ -628,11 +651,16 @@ FlatImageLayout::FlatImageLayout(PEImage* pOwner) if (m_FileMap == NULL) ThrowLastError(); - m_FileView.Assign(CLRMapViewOfFile(m_FileMap, FILE_MAP_READ, 0, 0, 0)); + //DWORD lowPart = (DWORD)offset; + //DWORD highPart = (DWORD)(offset >> 32); + char *addr = (char*)CLRMapViewOfFile(m_FileMap, FILE_MAP_READ, 0, 0, 0); + addr += offset; + m_FileView.Assign((LPVOID)addr); + if (m_FileView == NULL) ThrowLastError(); } - Init(m_FileView, size); + Init(m_FileView, (COUNT_T)size); } NativeImageLayout::NativeImageLayout(LPCWSTR fullPath) @@ -655,7 +683,7 @@ NativeImageLayout::NativeImageLayout(LPCWSTR fullPath) ThrowLastError(); } - loadedImage = PAL_LOADLoadPEFile(fileHandle); + loadedImage = PAL_LOADLoadPEFile(fileHandle, 0); } #else loadedImage = CLRLoadLibraryEx(fullPath, NULL, GetLoadWithAlteredSearchPathFlag()); diff --git a/src/coreclr/src/vm/peimagelayout.h b/src/coreclr/src/vm/peimagelayout.h index 9ae14c4b74e54..bc846c54d6c74 100644 --- a/src/coreclr/src/vm/peimagelayout.h +++ b/src/coreclr/src/vm/peimagelayout.h @@ -54,6 +54,7 @@ class PEImageLayout : public PEDecoder static PEImageLayout* LoadFromFlat(PEImageLayout* pflatimage); static PEImageLayout* Load(PEImage* pOwner, BOOL bNTSafeLoad, BOOL bThrowOnError = TRUE); static PEImageLayout* LoadFlat(PEImage* pOwner); + static PEImageLayout* LoadConverted(PEImage* pOwner); static PEImageLayout* LoadNative(LPCWSTR fullPath); static PEImageLayout* Map(PEImage* pOwner); #endif diff --git a/src/coreclr/src/vm/pgo.cpp b/src/coreclr/src/vm/pgo.cpp new file mode 100644 index 0000000000000..3d1826b7eba3b --- /dev/null +++ b/src/coreclr/src/vm/pgo.cpp @@ -0,0 +1,368 @@ +// 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. + +#include "common.h" +#include "log.h" +#include "pgo.h" + +#ifdef FEATURE_PGO + +ICorJitInfo::BlockCounts* PgoManager::s_PgoData; +unsigned PgoManager::s_PgoIndex; +const char* const PgoManager::s_FileHeaderString = "*** START PGO Data, max index = %u ***\n"; +const char* const PgoManager::s_FileTrailerString = "*** END PGO Data ***\n"; +const char* const PgoManager::s_MethodHeaderString = "@@@ token 0x%08X hash 0x%08X ilSize 0x%08X records 0x%08X index %u\n"; +const char* const PgoManager::s_RecordString = "ilOffs %u count %u\n"; + +void PgoManager::Initialize() +{ + LIMITED_METHOD_CONTRACT; + + // If any PGO mode is active, allocate the slab + if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ReadPGOData) > 0) || + (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_WritePGOData) > 0) || + (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TieredPGO) > 0)) + { + s_PgoData = new ICorJitInfo::BlockCounts[BUFFER_SIZE]; + s_PgoIndex = 0; + } + + // If we're reading in counts, do that now + ReadPgoData(); +} + +void PgoManager::Shutdown() +{ + WritePgoData(); +} + +void PgoManager::WritePgoData() +{ + if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_WritePGOData) == 0) + { + return; + } + + if (s_PgoData == NULL) + { + return; + } + + CLRConfigStringHolder fileName(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PGODataPath)); + + if (fileName == NULL) + { + return; + } + + FILE* const pgoDataFile = _wfopen(fileName, W("w")); + + if (pgoDataFile == NULL) + { + return; + } + + fprintf(pgoDataFile, s_FileHeaderString, s_PgoIndex); + unsigned index = 0; + const unsigned maxIndex = s_PgoIndex; + + while (index < maxIndex) + { + const Header* const header = (Header*)&s_PgoData[index]; + + if ((header->recordCount < MIN_RECORD_COUNT) || (header->recordCount > MAX_RECORD_COUNT)) + { + fprintf(pgoDataFile, "Unreasonable record count %u at index %u\n", header->recordCount, index); + break; + } + + fprintf(pgoDataFile, s_MethodHeaderString, header->token, header->hash, header->ilSize, header->recordCount, index); + + index += 2; + + ICorJitInfo::BlockCounts* records = &s_PgoData[index]; + unsigned recordCount = header->recordCount - 2; + unsigned lastOffset = 0; + for (unsigned i = 0; i < recordCount; i++) + { + const unsigned thisOffset = records[i].ILOffset; + assert((thisOffset > lastOffset) || (lastOffset == 0)); + lastOffset = thisOffset; + fprintf(pgoDataFile, s_RecordString, records[i].ILOffset, records[i].ExecutionCount); + } + + index += recordCount; + } + + fprintf(pgoDataFile, s_FileTrailerString); + fclose(pgoDataFile); +} + +void PgoManager::ReadPgoData() +{ + // Skip, if we're not reading, or we're writing profile data, or doing tiered pgo + // + if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_WritePGOData) > 0) || + (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TieredPGO) > 0) || + (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ReadPGOData) == 0)) + { + return; + } + + // PGO data slab should already be set up, if not, just bail + // + if (s_PgoData == NULL) + { + return; + } + + CLRConfigStringHolder fileName(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PGODataPath)); + + if (fileName == NULL) + { + return; + } + + FILE* const pgoDataFile = _wfopen(fileName, W("r")); + + if (pgoDataFile == NULL) + { + return; + } + + char buffer[256]; + unsigned maxIndex = 0; + + // Header must be first line + // + if (fgets(buffer, sizeof(buffer), pgoDataFile) == nullptr) + { + return; + } + + if (sscanf_s(buffer, s_FileHeaderString, &maxIndex) != 1) + { + return; + } + + // Sanity check data will fit into the slab + // + if ((maxIndex == 0) || (maxIndex >= MAX_RECORD_COUNT)) + { + return; + } + + // Fill in the data + // + unsigned index = 0; + unsigned methods = 0; + unsigned probes = 0; + + bool failed = false; + while (!failed) + { + if (fgets(buffer, sizeof(buffer), pgoDataFile) == nullptr) + { + break; + } + + // Find the next method entry line + // + unsigned recordCount = 0; + unsigned token = 0; + unsigned hash = 0; + unsigned ilSize = 0; + unsigned rIndex = 0; + + if (sscanf_s(buffer, s_MethodHeaderString, &token, &hash, &ilSize, &recordCount, &rIndex) != 5) + { + continue; + } + + assert(index == rIndex); + methods++; + + // If there's not enough room left, bail + if ((index + recordCount) > maxIndex) + { + failed = true; + break; + } + + Header* const header = (Header*)&s_PgoData[index]; + + header->recordCount = recordCount; + header->token = token; + header->hash = hash; + header->ilSize = ilSize; + + // Sanity check + // + if ((recordCount < MIN_RECORD_COUNT) || (recordCount > MAX_RECORD_COUNT)) + { + failed = true; + break; + } + + index += 2; + + // Read il data + // + for (unsigned i = 0; i < recordCount - 2; i++) + { + if (fgets(buffer, sizeof(buffer), pgoDataFile) == nullptr) + { + failed = true; + break; + } + + if (sscanf_s(buffer, s_RecordString, &s_PgoData[index].ILOffset, &s_PgoData[index].ExecutionCount) != 2) + { + failed = true; + break; + } + + index++; + } + + probes += recordCount - 2; + } + + s_PgoIndex = maxIndex; +} + +HRESULT PgoManager::allocMethodBlockCounts(MethodDesc* pMD, UINT32 count, + ICorJitInfo::BlockCounts** pBlockCounts, unsigned ilSize) +{ + // Initialize our out param + *pBlockCounts = NULL; + + if (s_PgoData == nullptr) + { + return E_NOTIMPL; + } + + unsigned methodIndex = 0; + unsigned recordCount = count + 2; + + // Look for space in the profile buffer for this method. + // Note other jit invocations may be vying for space concurrently. + // + while (true) + { + const unsigned oldIndex = s_PgoIndex; + const unsigned newIndex = oldIndex + recordCount; + + // If there is no room left for this method, + // that's ok, we just won't profile this method. + // + if (newIndex >= BUFFER_SIZE) + { + return E_NOTIMPL; + } + + const unsigned updatedIndex = InterlockedCompareExchangeT(&s_PgoIndex, newIndex, oldIndex); + + if (updatedIndex == oldIndex) + { + // Found space + methodIndex = oldIndex; + break; + } + } + + // Fill in the header + Header* const header = (Header*)&s_PgoData[methodIndex]; + header->recordCount = recordCount; + header->token = pMD->IsDynamicMethod() ? 0 : pMD->GetMemberDef(); + header->hash = pMD->GetStableHash(); + header->ilSize = ilSize; + + // Return pointer to start of count records + *pBlockCounts = &s_PgoData[methodIndex + 2]; + return S_OK; +} + +HRESULT PgoManager::getMethodBlockCounts(MethodDesc* pMD, unsigned ilSize, UINT32* pCount, + ICorJitInfo::BlockCounts** pBlockCounts, UINT32* pNumRuns) +{ + // Initialize our out params + *pCount = 0; + *pBlockCounts = NULL; + *pNumRuns = 0; + + // Bail if there's no profile data. + // + if (s_PgoData == NULL) + { + return E_NOTIMPL; + } + + // See if we can find counts for this method in the profile buffer. + // + const unsigned maxIndex = s_PgoIndex; + const unsigned token = pMD->IsDynamicMethod() ? 0 : pMD->GetMemberDef(); + const unsigned hash = pMD->GetStableHash(); + + + unsigned index = 0; + unsigned methodsChecked = 0; + + while (index < maxIndex) + { + // The first two "records" of each entry are actually header data + // to identify the method. + // + Header* const header = (Header*)&s_PgoData[index]; + + // Sanity check that header data looks reasonable. If not, just + // fail the lookup. + // + if ((header->recordCount < MIN_RECORD_COUNT) || (header->recordCount > MAX_RECORD_COUNT)) + { + break; + } + + // See if the header info matches the current method. + // + if ((header->token == token) && (header->hash == hash) && (header->ilSize == ilSize)) + { + // Yep, found data. + // + *pBlockCounts = &s_PgoData[index + 2]; + *pCount = header->recordCount - 2; + *pNumRuns = 1; + return S_OK; + } + + index += header->recordCount; + methodsChecked++; + } + + return E_NOTIMPL; +} + +#else + +// Stub version for !FEATURE_PGO builds +// +HRESULT PgoManager::allocMethodBlockCounts(MethodDesc* pMD, UINT32 count, + ICorJitInfo::BlockCounts** pBlockCounts, unsigned ilSize) +{ + pBlockCounts = NULL; + return E_NOTIMPL; +} + +// Stub version for !FEATURE_PGO builds +// +HRESULT PgoManager::getMethodBlockCounts(MethodDesc* pMD, unsigned ilSize, UINT32* pCount, + ICorJitInfo::BlockCounts** pBlockCounts, UINT32* pNumRuns) +{ + pBlockCounts = NULL; + pCount = 0; + pNumRuns = 0; + return E_NOTIMPL; +} + +#endif // FEATURE_PGO diff --git a/src/coreclr/src/vm/pgo.h b/src/coreclr/src/vm/pgo.h new file mode 100644 index 0000000000000..acaf74712c867 --- /dev/null +++ b/src/coreclr/src/vm/pgo.h @@ -0,0 +1,72 @@ +// 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. + +#ifndef PGO_H +#define PGO_H + +// PgoManager handles in-process and out of band profile data for jitted code. +class PgoManager +{ +#ifdef FEATURE_PGO + +public: + + static void Initialize(); + static void Shutdown(); + +#endif // FEATURE_PGO + +public: + + // Allocate a profile block count buffer for a method + static HRESULT allocMethodBlockCounts(MethodDesc* pMD, UINT32 count, + ICorJitInfo::BlockCounts** pBlockCounts, unsigned ilSize); + + // Retreive the profile block count buffer for a method + static HRESULT getMethodBlockCounts(MethodDesc* pMD, unsigned ilSize, UINT32* pCount, + ICorJitInfo::BlockCounts** pBlockCounts, UINT32* pNumRuns); + +#ifdef FEATURE_PGO + +private: + + enum + { + // Number of ICorJitInfo::BlockCount records in the global slab + BUFFER_SIZE = 64 * 1024, + MIN_RECORD_COUNT = 3, + MAX_RECORD_COUNT = BUFFER_SIZE + }; + + struct Header + { + unsigned recordCount; + unsigned token; + unsigned hash; + unsigned ilSize; + }; + +private: + + static void ReadPgoData(); + static void WritePgoData(); + +private: + + // Global slab holding all pgo data + static ICorJitInfo::BlockCounts* s_PgoData; + + // Index of next free entry in the global slab + static unsigned s_PgoIndex; + + // Formatting strings for file input/output + static const char* const s_FileHeaderString; + static const char* const s_FileTrailerString; + static const char* const s_MethodHeaderString; + static const char* const s_RecordString; + +#endif // FEATURE_PGO +}; + +#endif // PGO_H diff --git a/src/coreclr/src/vm/profilinghelper.cpp b/src/coreclr/src/vm/profilinghelper.cpp index 1d41007c7d8f7..e5af2fcdfacac 100644 --- a/src/coreclr/src/vm/profilinghelper.cpp +++ b/src/coreclr/src/vm/profilinghelper.cpp @@ -702,10 +702,10 @@ HRESULT ProfilingAPIUtility::AttemptLoadProfilerForStartup() IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER, &wszClsid)); -#if defined(TARGET_X86) || defined(TARGET_ARM) - IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_32, &wszProfilerDLL)); -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) +#ifdef TARGET_64BIT IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_64, &wszProfilerDLL)); +#else + IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_32, &wszProfilerDLL)); #endif if(wszProfilerDLL == NULL) { diff --git a/src/coreclr/src/vm/qcall.h b/src/coreclr/src/vm/qcall.h index 380a041ca9215..32ce22f1bec8a 100644 --- a/src/coreclr/src/vm/qcall.h +++ b/src/coreclr/src/vm/qcall.h @@ -137,7 +137,13 @@ GC_TRIGGERS; \ MODE_PREEMPTIVE; \ +#define QCALL_CHECK_NO_GC_TRANSITION \ + THROWS; \ + GC_TRIGGERS; \ + MODE_COOPERATIVE; \ + #define QCALL_CONTRACT CONTRACTL { QCALL_CHECK; } CONTRACTL_END; +#define QCALL_CONTRACT_NO_GC_TRANSITION CONTRACTL { QCALL_CHECK_NO_GC_TRANSITION; } CONTRACTL_END; // // Scope class for QCall helper methods and types diff --git a/src/coreclr/src/vm/rcwwalker.cpp b/src/coreclr/src/vm/rcwwalker.cpp index 5c94a3ea53690..8c8e5f0d7f663 100644 --- a/src/coreclr/src/vm/rcwwalker.cpp +++ b/src/coreclr/src/vm/rcwwalker.cpp @@ -150,7 +150,7 @@ STDMETHODIMP CLRServicesImpl::AddMemoryPressure(UINT64 bytesAllocated) HRESULT hr = S_OK; BEGIN_EXTERNAL_ENTRYPOINT(&hr) { - GCInterface::NewAddMemoryPressure(bytesAllocated); + GCInterface::AddMemoryPressure(bytesAllocated); } END_EXTERNAL_ENTRYPOINT; return hr; @@ -168,7 +168,7 @@ STDMETHODIMP CLRServicesImpl::RemoveMemoryPressure(UINT64 bytesAllocated) HRESULT hr = S_OK; BEGIN_EXTERNAL_ENTRYPOINT(&hr) { - GCInterface::NewRemoveMemoryPressure(bytesAllocated); + GCInterface::RemoveMemoryPressure(bytesAllocated); } END_EXTERNAL_ENTRYPOINT; return hr; @@ -570,7 +570,7 @@ void RCWWalker::WalkRCWs() { hr = GET_EXCEPTION()->GetHR(); } - EX_END_CATCH(RethrowCorruptingExceptions) // Make sure we crash on AV (instead of swallowing everything) + EX_END_CATCH(RethrowTerminalExceptions) if (FAILED(hr)) { diff --git a/src/coreclr/src/vm/reflectioninvocation.cpp b/src/coreclr/src/vm/reflectioninvocation.cpp index 2724de4771b1f..c530786aa3879 100644 --- a/src/coreclr/src/vm/reflectioninvocation.cpp +++ b/src/coreclr/src/vm/reflectioninvocation.cpp @@ -882,15 +882,6 @@ void DECLSPEC_NORETURN ThrowInvokeMethodException(MethodDesc * pMethod, OBJECTRE } #endif // _DEBUG && !TARGET_UNIX -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Get the corruption severity of the exception that came in through reflection invocation. - CorruptionSeverity severity = GetThread()->GetExceptionState()->GetLastActiveExceptionCorruptionSeverity(); - - // Since we are dealing with an exception, set the flag indicating if the target of Reflection can handle exception or not. - // This flag is used in CEHelper::CanIDispatchTargetHandleException. - GetThread()->GetExceptionState()->SetCanReflectionTargetHandleException(CEHelper::CanMethodHandleException(severity, pMethod)); -#endif // FEATURE_CORRUPTING_EXCEPTIONS - OBJECTREF except = InvokeUtil::CreateTargetExcept(&targetException); #ifndef TARGET_UNIX @@ -944,11 +935,7 @@ void DECLSPEC_NORETURN ThrowInvokeMethodException(MethodDesc * pMethod, OBJECTRE // Since VM is throwing the exception, we set it to use the same corruption severity // that the original exception came in with from reflection invocation. - COMPlusThrow(except -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - , severity -#endif // FEATURE_CORRUPTING_EXCEPTIONS - ); + COMPlusThrow(except); GCPROTECT_END(); } @@ -1254,12 +1241,6 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod, ENDFORBIDGC(); } -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // By default, set the flag in TES indicating the reflection target can handle CSE. - // This flag is used in CEHelper::CanIDispatchTargetHandleException. - pThread->GetExceptionState()->SetCanReflectionTargetHandleException(TRUE); -#endif // FEATURE_CORRUPTING_EXCEPTIONS - if (pValueClasses != NULL) { pProtectValueClassFrame = new (_alloca (sizeof (FrameWithCookie))) @@ -2415,9 +2396,8 @@ FCIMPL1(Object *, ReflectionEnum::InternalGetEnumUnderlyingType, ReflectClassBas VALIDATEOBJECT(target); TypeHandle th = target->GetType(); - if (!th.IsEnum()) - FCThrowArgument(NULL, NULL); - + _ASSERTE(th.IsEnum()); + OBJECTREF result = NULL; HELPER_METHOD_FRAME_BEGIN_RET_0(); diff --git a/src/coreclr/src/vm/runtimecallablewrapper.cpp b/src/coreclr/src/vm/runtimecallablewrapper.cpp index 61475bf9ba0d5..d15ae5e6bbb7e 100644 --- a/src/coreclr/src/vm/runtimecallablewrapper.cpp +++ b/src/coreclr/src/vm/runtimecallablewrapper.cpp @@ -2432,23 +2432,12 @@ void RCW::AddMemoryPressure(GCPressureSize pressureSize) CONTRACTL_END; int pressure = s_rGCPressureTable[pressureSize]; - - if (pressureSize >= GCPressureSize_WinRT_Base) - { - // use the new implementation for WinRT RCWs - GCInterface::NewAddMemoryPressure(pressure); - } - else - { - // use the old implementation for classic COM interop - GCInterface::AddMemoryPressure(pressure); - } + GCInterface::AddMemoryPressure(pressure); // Remember the pressure we set. m_Flags.m_GCPressure = pressureSize; } - void RCW::RemoveMemoryPressure() { CONTRACTL @@ -2464,17 +2453,7 @@ void RCW::RemoveMemoryPressure() return; int pressure = s_rGCPressureTable[m_Flags.m_GCPressure]; - - if (m_Flags.m_GCPressure >= GCPressureSize_WinRT_Base) - { - // use the new implementation for WinRT RCWs - GCInterface::NewRemoveMemoryPressure(pressure); - } - else - { - // use the old implementation for classic COM interop - GCInterface::RemoveMemoryPressure(pressure); - } + GCInterface::RemoveMemoryPressure(pressure); m_Flags.m_GCPressure = GCPressureSize_None; } diff --git a/src/coreclr/src/vm/runtimehandles.cpp b/src/coreclr/src/vm/runtimehandles.cpp index a16bc1a1c2aaa..82c793bf3f7af 100644 --- a/src/coreclr/src/vm/runtimehandles.cpp +++ b/src/coreclr/src/vm/runtimehandles.cpp @@ -1110,7 +1110,7 @@ PVOID QCALLTYPE RuntimeTypeHandle::GetGCHandle(QCall::TypeHandle pTypeHandle, IN GCX_COOP(); TypeHandle th = pTypeHandle.AsTypeHandle(); - assert(handleType >= HNDTYPE_WEAK_SHORT && handleType <= HNDTYPE_WEAK_WINRT); + assert(handleType >= HNDTYPE_WEAK_SHORT && handleType <= HNDTYPE_WEAK_NATIVE_COM); objHandle = AppDomain::GetCurrentDomain()->CreateTypedHandle(NULL, static_cast(handleType)); th.GetLoaderAllocator()->RegisterHandleForCleanup(objHandle); diff --git a/src/coreclr/src/vm/stdinterfaces.cpp b/src/coreclr/src/vm/stdinterfaces.cpp index 7ca4975c32678..240bdc926bc3e 100644 --- a/src/coreclr/src/vm/stdinterfaces.cpp +++ b/src/coreclr/src/vm/stdinterfaces.cpp @@ -1502,7 +1502,7 @@ InternalDispatchImpl_Invoke hr = pDispInfo->InvokeMember(pSimpleWrap, dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL, puArgErr); } - END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS; // This will ensure that entry points wont swallow CE and continue to let them propagate out. + END_EXTERNAL_ENTRYPOINT; return hr; } diff --git a/src/coreclr/src/vm/stubmgr.cpp b/src/coreclr/src/vm/stubmgr.cpp index 2ff9311167a9d..12cbd4831f5ee 100644 --- a/src/coreclr/src/vm/stubmgr.cpp +++ b/src/coreclr/src/vm/stubmgr.cpp @@ -1844,6 +1844,12 @@ BOOL ILStubManager::TraceManager(Thread *thread, trace->InitForUnmanaged(target); } #endif // FEATURE_COMINTEROP + else if (pStubMD->IsStructMarshalStub()) + { + // There's no "target" for struct marshalling stubs + // so we have nowhere to tell the debugger to move the breakpoint. + return FALSE; + } else { // This is either direct forward P/Invoke or a CLR-to-COM call, the argument is MD diff --git a/src/coreclr/src/vm/threads.cpp b/src/coreclr/src/vm/threads.cpp index 19b318e58d598..324c65d67ce8c 100644 --- a/src/coreclr/src/vm/threads.cpp +++ b/src/coreclr/src/vm/threads.cpp @@ -4500,17 +4500,6 @@ void Thread::SyncManagedExceptionState(bool fIsDebuggerThread) // Syncup the LastThrownObject on the managed thread SafeUpdateLastThrownObject(); } - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - // Since the catch clause has successfully executed and we are exiting it, reset the corruption severity - // in the ThreadExceptionState for the last active exception. This will ensure that when the next exception - // gets thrown/raised, EH tracker wont pick up an invalid value. - if (!fIsDebuggerThread) - { - CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler(this); - } -#endif // FEATURE_CORRUPTING_EXCEPTIONS - } void Thread::SetLastThrownObjectHandle(OBJECTHANDLE h) diff --git a/src/coreclr/src/vm/vars.hpp b/src/coreclr/src/vm/vars.hpp index cd4080018f8e6..997c2157bcdae 100644 --- a/src/coreclr/src/vm/vars.hpp +++ b/src/coreclr/src/vm/vars.hpp @@ -690,12 +690,23 @@ struct ModuleIndex typedef DPTR(GSCookie) PTR_GSCookie; +#ifdef _MSC_VER +#define READONLY_ATTR +#else +#ifdef __APPLE__ +#define READONLY_ATTR_ARGS section("__TEXT,__const") +#else +#define READONLY_ATTR_ARGS section(".rodata") +#endif +#define READONLY_ATTR __attribute__((READONLY_ATTR_ARGS)) +#endif + #ifndef DACCESS_COMPILE // const is so that it gets placed in the .text section (which is read-only) // volatile is so that accesses to it do not get optimized away because of the const // -extern "C" RAW_KEYWORD(volatile) const GSCookie s_gsCookie; +extern "C" RAW_KEYWORD(volatile) READONLY_ATTR const GSCookie s_gsCookie; inline GSCookie * GetProcessGSCookiePtr() { return const_cast(&s_gsCookie); } diff --git a/src/coreclr/src/vm/vmholder.h b/src/coreclr/src/vm/vmholder.h index 9c265a1b366d7..003892b07addc 100644 --- a/src/coreclr/src/vm/vmholder.h +++ b/src/coreclr/src/vm/vmholder.h @@ -18,6 +18,7 @@ inline void DoTheReleaseHost(TYPE *value) } } -NEW_WRAPPER_TEMPLATE1(HostComHolder, DoTheReleaseHost<_TYPE>); +template +using HostComHolder = SpecializedWrapper<_TYPE, DoTheReleaseHost<_TYPE>>; #endif diff --git a/src/coreclr/src/vm/weakreferencenative.cpp b/src/coreclr/src/vm/weakreferencenative.cpp index b1dc825494f35..2cdb83ce9b81e 100644 --- a/src/coreclr/src/vm/weakreferencenative.cpp +++ b/src/coreclr/src/vm/weakreferencenative.cpp @@ -16,6 +16,7 @@ #include "typestring.h" #include "typeparse.h" #include "threadsuspend.h" +#include "interoplibinterface.h" //************************************************************************ @@ -34,7 +35,7 @@ const LPVOID specialWeakReferenceHandles[3] = { 0, 0, 0 }; // // A WeakReference instance can hold one of three types of handles - short or long weak handles, -// or a WinRT weak reference handle. The WinRT weak reference handle has the extra capability +// or a native COM weak reference handle. The native COM weak reference handle has the extra capability // of recreating an RCW for a COM object which is still alive even though the previous RCW had // been collected. In order to differentiate this type of handle from the standard weak handles, // the bottom bit is stolen. @@ -50,23 +51,23 @@ const LPVOID specialWeakReferenceHandles[3] = { 0, 0, 0 }; // The following functions are to set, test, and unset that bit before the handle is used. // -// Determine if an object handle is a WinRT weak reference handle -bool IsWinRTWeakReferenceHandle(OBJECTHANDLE handle) +// Determine if an object handle is a native COM weak reference handle +bool IsNativeComWeakReferenceHandle(OBJECTHANDLE handle) { STATIC_CONTRACT_LEAF; return (reinterpret_cast(handle) & 0x1) != 0x0; } -// Mark an object handle as being a WinRT weak reference handle -OBJECTHANDLE SetWinRTWeakReferenceHandle(OBJECTHANDLE handle) +// Mark an object handle as being a native COM weak reference handle +OBJECTHANDLE SetNativeComWeakReferenceHandle(OBJECTHANDLE handle) { STATIC_CONTRACT_LEAF; - _ASSERTE(!IsWinRTWeakReferenceHandle(handle)); + _ASSERTE(!IsNativeComWeakReferenceHandle(handle)); return reinterpret_cast(reinterpret_cast(handle) | 0x1); } -// Get the object handle value even if the object is a WinRT weak reference +// Get the object handle value even if the object is a native COM weak reference OBJECTHANDLE GetHandleValue(OBJECTHANDLE handle) { STATIC_CONTRACT_LEAF; @@ -102,17 +103,17 @@ struct WeakHandleSpinLockHolder #ifdef FEATURE_COMINTEROP -// Get a WinRT weak reference for the object underlying an RCW if applicable. If the incoming object cannot -// use a WinRT weak reference, nullptr is returned. Otherwise, an AddRef-ed IWeakReference* for the COM +// Get a native COM weak reference for the object underlying an RCW if applicable. If the incoming object cannot +// use a native COM weak reference, nullptr is returned. Otherwise, an AddRef-ed IWeakReference* for the COM // object underlying the RCW is returned. // -// In order to qualify to be used with a HNDTYPE_WEAK_WINRT, the incoming object must: +// In order to qualify to be used with a HNDTYPE_WEAK_NATIVE_COM, the incoming object must: // * be an RCW // * respond to a QI for IWeakReferenceSource // * succeed when asked for an IWeakReference* // // Note that *pObject should be GC protected on the way into this method -IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject) +IWeakReference* GetComWeakReference(OBJECTREF* pObject) { CONTRACTL { @@ -132,21 +133,24 @@ IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject) MethodTable* pMT = (*pObject)->GetMethodTable(); - // If the object is not an RCW, then we do not want to use a WinRT weak reference to it - if (!pMT->IsComObjectType()) - { - return nullptr; - } + SafeComHolder pWeakReferenceSource(nullptr); - // If the object is a managed type deriving from a COM type, then we also do not want to use a WinRT + // If the object is not an RCW, then we do not want to use a native COM weak reference to it + // If the object is a managed type deriving from a COM type, then we also do not want to use a native COM // weak reference to it. (Otherwise, we'll wind up resolving IWeakReference-s back into the CLR // when we don't want to have reentrancy). - if (pMT != g_pBaseCOMObject && pMT->IsExtensibleRCW()) + if (pMT->IsComObjectType() + && (pMT == g_pBaseCOMObject || !pMT->IsExtensibleRCW())) { - return nullptr; + pWeakReferenceSource = reinterpret_cast(GetComIPFromObjectRef(pObject, IID_IWeakReferenceSource, false /* throwIfNoComIP */)); + } +#ifdef FEATURE_COMWRAPPERS + else + { + pWeakReferenceSource = reinterpret_cast(ComWrappersNative::GetIdentityForObject(pObject, IID_IWeakReferenceSource)); } +#endif - SafeComHolder pWeakReferenceSource(reinterpret_cast(GetComIPFromObjectRef(pObject, IID_IWeakReferenceSource, false /* throwIfNoComIP */))); if (pWeakReferenceSource == nullptr) { return nullptr; @@ -162,17 +166,17 @@ IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject) return pWeakReference.Extract(); } -// Given an object handle that stores a WinRT weak reference, attempt to create an RCW -// and store it back in the handle, returning the RCW. If the underlying WinRT object +// Given an object handle that stores a native COM weak reference, attempt to create an RCW +// and store it back in the handle, returning the RCW. If the underlying native COM object // is not alive, then the result is NULL. // // In order to create a new RCW, we must: -// * Have an m_handle of HNDTYPE_WEAK_WINRT (ie the bottom bit of m_handle is set) +// * Have an m_handle of HNDTYPE_WEAK_NATIVE_COM (ie the bottom bit of m_handle is set) // * Have stored an IWeakReference* in the handle extra info when setting up the handle -// (see GetWinRTWeakReference) +// (see GetComWeakReference) // * The IWeakReference* must respond to a Resolve request for IID_IInspectable // * -NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, TypeHandle targetType, LPVOID __me) +NOINLINE Object* LoadComWeakReferenceTarget(WEAKREFERENCEREF weakReference, TypeHandle targetType, LPVOID __me) { CONTRACTL { @@ -200,14 +204,14 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty // // Since we're acquiring and releasing the lock multiple times, we need to check the handle state each time we // reacquire the lock to make sure that another thread hasn't reassigned the target of the handle or finalized it - SafeComHolder pWinRTWeakReference = nullptr; + SafeComHolder pComWeakReference = nullptr; { WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference); GCX_NOTRIGGER(); // Make sure that while we were not holding the spin lock, another thread did not change the target of // this weak reference. Only fetch the IWeakReference* if we still have a valid handle holding a NULL object - // and the handle is still a HNDTYPE_WEAK_WINRT type handle. + // and the handle is still a HNDTYPE_WEAK_NATIVE_COM type handle. if ((handle.Handle != NULL) && !IS_SPECIAL_HANDLE(handle.Handle)) { if (*(Object **)(handle.Handle) != NULL) @@ -217,22 +221,22 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty // weak reference is targeting. gc.target = ObjectToOBJECTREF(*(Object **)(handle.Handle)); } - else if(IsWinRTWeakReferenceHandle(handle.RawHandle)) + else if(IsNativeComWeakReferenceHandle(handle.RawHandle)) { - _ASSERTE(GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle.Handle) == HNDTYPE_WEAK_WINRT); + _ASSERTE(GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle.Handle) == HNDTYPE_WEAK_NATIVE_COM); // Retrieve the associated IWeakReference* for this weak reference. Add a reference to it while we release // the spin lock so that another thread doesn't release it out from underneath us. // - // Setting pWinRTWeakReference will claim that it triggers a GC, however that's not true in this case because + // Setting pComWeakReference will claim that it triggers a GC, however that's not true in this case because // it's always set to NULL here and there's nothing for it to release. - _ASSERTE(pWinRTWeakReference.IsNull()); + _ASSERTE(pComWeakReference.IsNull()); CONTRACT_VIOLATION(GCViolation); IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager(); - pWinRTWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle)); - if (!pWinRTWeakReference.IsNull()) + pComWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle)); + if (!pComWeakReference.IsNull()) { - pWinRTWeakReference->AddRef(); + pComWeakReference->AddRef(); } } } @@ -242,16 +246,16 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty // identity of the underlying COM object (assuming that object is still alive). This work is done without holding the // spin lock since it will call out to arbitrary code and as such we need to switch to preemptive mode. SafeComHolder pTargetIdentity = nullptr; - if (pWinRTWeakReference != nullptr) + if (pComWeakReference != nullptr) { _ASSERTE(gc.target == NULL); GCX_PREEMP(); - // Using the IWeakReference*, get ahold of the target WinRT object's IInspectable*. If this resolve fails, then we - // assume that the underlying WinRT object is no longer alive, and thus we cannot create a new RCW for it. + // Using the IWeakReference*, get ahold of the target native COM object's IInspectable*. If this resolve fails, then we + // assume that the underlying native COM object is no longer alive, and thus we cannot create a new RCW for it. SafeComHolderPreemp pTarget = nullptr; - if (SUCCEEDED(pWinRTWeakReference->Resolve(IID_IInspectable, &pTarget))) + if (SUCCEEDED(pComWeakReference->Resolve(IID_IInspectable, &pTarget))) { if (!pTarget.IsNull()) { @@ -264,7 +268,11 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty // If we were able to get an IUnkown identity for the object, then we can find or create an associated RCW for it. if (!pTargetIdentity.IsNull()) { - GetObjectRefFromComIP(&gc.rcw, pTargetIdentity); + // Try the global COM wrappers first before falling back to the built-in system. + if (!GlobalComWrappersForTrackerSupport::TryGetOrCreateObjectForComInstance(pTargetIdentity, &gc.rcw)) + { + GetObjectRefFromComIP(&gc.rcw, pTargetIdentity); + } } // If we were able to get an RCW, then we need to reacquire the spin lock and store the RCW in the handle. Note that @@ -272,7 +280,7 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty // building the RCW. In that case, we will defer to the hadle that the other thread set, and let the RCW die. if (gc.rcw != NULL) { - // Make sure the type we got back from the WinRT object is compatible with the type the managed + // Make sure the type we got back from the native COM object is compatible with the type the managed // weak reference expects. (For instance, in the WeakReference case, the returned type // had better be compatible with T). TypeHandle rcwType(gc.rcw->GetMethodTable()); @@ -284,7 +292,7 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty SString resolvedTypeName; TypeString::AppendType(resolvedTypeName, rcwType, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly); - COMPlusThrow(kInvalidCastException, IDS_EE_WINRT_WEAKREF_BAD_TYPE, weakReferenceTypeName.GetUnicode(), resolvedTypeName.GetUnicode()); + COMPlusThrow(kInvalidCastException, IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE, weakReferenceTypeName.GetUnicode(), resolvedTypeName.GetUnicode()); } WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference); @@ -420,12 +428,21 @@ FCIMPL3(void, WeakReferenceNative::Create, WeakReferenceObject * pThisUNSAFE, Ob // Create the handle. #ifdef FEATURE_COMINTEROP - IWeakReference* pRawWinRTWeakReference = GetWinRTWeakReference(&gc.pTarget); - if (pRawWinRTWeakReference != nullptr) + IWeakReference* pRawComWeakReference = nullptr; + if (gc.pTarget != NULL) { - SafeComHolder pWinRTWeakReferenceHolder(pRawWinRTWeakReference); - gc.pThis->m_Handle = SetWinRTWeakReferenceHandle(GetAppDomain()->CreateWinRTWeakHandle(gc.pTarget, pWinRTWeakReferenceHolder)); - pWinRTWeakReferenceHolder.SuppressRelease(); + SyncBlock* pSyncBlock = gc.pTarget->PassiveGetSyncBlock(); + if (pSyncBlock != nullptr && pSyncBlock->GetInteropInfoNoCreate() != nullptr) + { + pRawComWeakReference = GetComWeakReference(&gc.pTarget); + } + } + + if (pRawComWeakReference != nullptr) + { + SafeComHolder pComWeakReferenceHolder(pRawComWeakReference); + gc.pThis->m_Handle = SetNativeComWeakReferenceHandle(GetAppDomain()->CreateNativeComWeakHandle(gc.pTarget, pComWeakReferenceHolder)); + pComWeakReferenceHolder.SuppressRelease(); } else #endif // FEATURE_COMINTEROP @@ -463,12 +480,21 @@ FCIMPL3(void, WeakReferenceOfTNative::Create, WeakReferenceObject * pThisUNSAFE, // Create the handle. #ifdef FEATURE_COMINTEROP - IWeakReference* pRawWinRTWeakReference = GetWinRTWeakReference(&gc.pTarget); - if (pRawWinRTWeakReference != nullptr) + IWeakReference* pRawComWeakReference = nullptr; + if (gc.pTarget != NULL) + { + SyncBlock* pSyncBlock = gc.pTarget->PassiveGetSyncBlock(); + if (pSyncBlock != nullptr && pSyncBlock->GetInteropInfoNoCreate() != nullptr) + { + pRawComWeakReference = GetComWeakReference(&gc.pTarget); + } + } + + if (pRawComWeakReference != nullptr) { - SafeComHolder pWinRTWeakReferenceHolder(pRawWinRTWeakReference); - gc.pThis->m_Handle = SetWinRTWeakReferenceHandle(GetAppDomain()->CreateWinRTWeakHandle(gc.pTarget, pWinRTWeakReferenceHolder)); - pWinRTWeakReferenceHolder.SuppressRelease(); + SafeComHolder pComWeakReferenceHolder(pRawComWeakReference); + gc.pThis->m_Handle = SetNativeComWeakReferenceHandle(GetAppDomain()->CreateNativeComWeakHandle(gc.pTarget, pComWeakReferenceHolder)); + pComWeakReferenceHolder.SuppressRelease(); } else #endif // FEATURE_COMINTEROP @@ -499,7 +525,7 @@ void FinalizeWeakReference(Object * obj) // The suspension state of the runtime must be prevented from changing while in this function in order for this to be safe. OBJECTHANDLE handle = ThreadSuspend::SysIsSuspended() ? pThis->m_Handle.LoadWithoutBarrier() : AcquireWeakHandleSpinLock(pThis); OBJECTHANDLE handleToDestroy = NULL; - bool isWeakWinRTHandle = false; + bool isWeakNativeComHandle = false; // Check for not yet constructed or already finalized handle if ((handle != NULL) && !IS_SPECIAL_HANDLE(handle)) @@ -509,8 +535,8 @@ void FinalizeWeakReference(Object * obj) // Cache the old handle value HandleType handleType = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handleToDestroy); #ifdef FEATURE_COMINTEROP - _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT || handleType == HNDTYPE_WEAK_WINRT); - isWeakWinRTHandle = handleType == HNDTYPE_WEAK_WINRT; + _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT || handleType == HNDTYPE_WEAK_NATIVE_COM); + isWeakNativeComHandle = handleType == HNDTYPE_WEAK_NATIVE_COM; #else // !FEATURE_COMINTEROP _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT); #endif // FEATURE_COMINTEROP @@ -528,9 +554,9 @@ void FinalizeWeakReference(Object * obj) if (handleToDestroy != NULL) { #ifdef FEATURE_COMINTEROP - if (isWeakWinRTHandle) + if (isWeakNativeComHandle) { - DestroyWinRTWeakHandle(handleToDestroy); + DestroyNativeComWeakHandle(handleToDestroy); } else #endif // FEATURE_COMINTEROP @@ -645,14 +671,14 @@ FCIMPL1(Object *, WeakReferenceNative::GetTarget, WeakReferenceObject * pThisUNS OBJECTREF pTarget = GetWeakReferenceTarget(pThis); #ifdef FEATURE_COMINTEROP - // If we found an object, or we're not a WinRT weak reference, then we're done. Othewrise - // we can try to create a new RCW to the underlying WinRT object if it's still alive. - if (pTarget != NULL || !IsWinRTWeakReferenceHandle(pThis->m_Handle)) + // If we found an object, or we're not a native COM weak reference, then we're done. Othewrise + // we can try to create a new RCW to the underlying native COM object if it's still alive. + if (pTarget != NULL || !IsNativeComWeakReferenceHandle(pThis->m_Handle)) { FC_GC_POLL_AND_RETURN_OBJREF(pTarget); } - FC_INNER_RETURN(Object*, LoadWinRTWeakReferenceTarget(pThis, g_pObjectClass, GetEEFuncEntryPointMacro(WeakReferenceNative::GetTarget))); + FC_INNER_RETURN(Object*, LoadComWeakReferenceTarget(pThis, g_pObjectClass, GetEEFuncEntryPointMacro(WeakReferenceNative::GetTarget))); #else // !FEATURE_COMINTEROP FC_GC_POLL_AND_RETURN_OBJREF(pTarget); #endif // FEATURE_COMINTEROP @@ -673,14 +699,14 @@ FCIMPL1(Object *, WeakReferenceOfTNative::GetTarget, WeakReferenceObject * pThis #ifdef FEATURE_COMINTEROP - // If we found an object, or we're not a WinRT weak reference, then we're done. Othewrise - // we can try to create a new RCW to the underlying WinRT object if it's still alive. - if (pTarget != NULL || !IsWinRTWeakReferenceHandle(pThis->m_Handle)) + // If we found an object, or we're not a native COM weak reference, then we're done. Othewrise + // we can try to create a new RCW to the underlying native COM object if it's still alive. + if (pTarget != NULL || !IsNativeComWeakReferenceHandle(pThis->m_Handle)) { FC_GC_POLL_AND_RETURN_OBJREF(pTarget); } - FC_INNER_RETURN(Object*, LoadWinRTWeakReferenceTarget(pThis, pThis->GetMethodTable()->GetInstantiation()[0], GetEEFuncEntryPointMacro(WeakReferenceOfTNative::GetTarget))); + FC_INNER_RETURN(Object*, LoadComWeakReferenceTarget(pThis, pThis->GetMethodTable()->GetInstantiation()[0], GetEEFuncEntryPointMacro(WeakReferenceOfTNative::GetTarget))); #else // !FEATURE_COMINTEROP FC_GC_POLL_AND_RETURN_OBJREF(pTarget); #endif // FEATURE_COMINTEROP @@ -711,7 +737,7 @@ FCIMPLEND #include -// Slow path helper for setting the target of a weak reference. This code is used if a WinRT weak reference might +// Slow path helper for setting the target of a weak reference. This code is used if a native COM weak reference might // be required. NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF target, LPVOID __me) { @@ -721,7 +747,7 @@ NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF t HELPER_METHOD_FRAME_BEGIN_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, target, weakReference); #ifdef FEATURE_COMINTEROP - SafeComHolder pTargetWeakReference(GetWinRTWeakReference(&target)); + SafeComHolder pTargetWeakReference(GetComWeakReference(&target)); #endif // FEATURE_COMINTEROP @@ -735,30 +761,30 @@ NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF t // Existing target is a GC object, new target is a GC object: // * Just store the new object in the handle // - // Existing target is WinRT, new target is WinRT: + // Existing target is native COM weak reference, new target is native COM weak reference: // * Release the existing IWeakReference* // * Store the new IWeakReference* // * Store the new object in the handle // - // Existing target is WinRT, new target is GC: + // Existing target is native COM weak reference, new target is GC: // * Release the existing IWeakReference* // * Store null to the IWeakReference* field // * Store the new object in the handle // - // Existing target is GC, new target is WinRT: + // Existing target is GC, new target is native COM weak reference: // * Destroy the existing handle - // * Allocate a new WinRT weak handle for the new target + // * Allocate a new native COM weak handle for the new target // - if (IsWinRTWeakReferenceHandle(handle.RawHandle)) + if (IsNativeComWeakReferenceHandle(handle.RawHandle)) { - // If the existing reference is a WinRT weak reference, we need to release its IWeakReference pointer + // If the existing reference is a native COM weak reference, we need to release its IWeakReference pointer // and update it with the new weak reference pointer. If the incoming object is not an RCW that can // use IWeakReference, then pTargetWeakReference will be null. Therefore, no matter what the incoming // object type is, we can unconditionally store pTargetWeakReference to the object handle's extra data. IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager(); IWeakReference* pExistingWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle)); - mgr->SetExtraInfoForHandle(handle.Handle, HNDTYPE_WEAK_WINRT, reinterpret_cast(pTargetWeakReference.GetValue())); + mgr->SetExtraInfoForHandle(handle.Handle, HNDTYPE_WEAK_NATIVE_COM, reinterpret_cast(pTargetWeakReference.GetValue())); StoreObjectInHandle(handle.Handle, target); if (pExistingWeakReference != nullptr) @@ -768,15 +794,15 @@ NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF t } else if (pTargetWeakReference != nullptr) { - // The existing handle is not a WinRT weak reference, but we need to store the new object in - // a WinRT weak reference. Therefore we need to destroy the old handle and create a new WinRT + // The existing handle is not a native COM weak reference, but we need to store the new object in + // a native COM weak reference. Therefore we need to destroy the old handle and create a new native COM // handle. The new handle needs to be allocated first to prevent the weak reference from holding // a destroyed handle if we fail to allocate the new one. - _ASSERTE(!IsWinRTWeakReferenceHandle(handle.RawHandle)); + _ASSERTE(!IsNativeComWeakReferenceHandle(handle.RawHandle)); OBJECTHANDLE previousHandle = handle.RawHandle; - handle.Handle = GetAppDomain()->CreateWinRTWeakHandle(target, pTargetWeakReference); - handle.RawHandle = SetWinRTWeakReferenceHandle(handle.Handle); + handle.Handle = GetAppDomain()->CreateNativeComWeakHandle(target, pTargetWeakReference); + handle.RawHandle = SetNativeComWeakReferenceHandle(handle.Handle); DestroyTypedHandle(previousHandle); } @@ -822,7 +848,7 @@ FCIMPL2(void, WeakReferenceNative::SetTarget, WeakReferenceObject * pThisUNSAFE, // If the existing handle is a GC weak handle and the new target is not an RCW, then // we can avoid setting up a helper method frame and just reset the handle directly. - if (!IsWinRTWeakReferenceHandle(handle)) + if (!IsNativeComWeakReferenceHandle(handle)) { if (pTarget == NULL || !pTarget->GetMethodTable()->IsComObjectType()) { @@ -875,7 +901,7 @@ FCIMPL2(void, WeakReferenceOfTNative::SetTarget, WeakReferenceObject * pThisUNSA // If the existing handle is a GC weak handle and the new target is not an RCW, then // we can avoid setting up a helper method frame and just reset the handle directly. - if (!IsWinRTWeakReferenceHandle(handle)) + if (!IsNativeComWeakReferenceHandle(handle)) { if (pTarget == NULL || !pTarget->GetMethodTable()->IsComObjectType()) { diff --git a/src/coreclr/src/vm/wrappers.h b/src/coreclr/src/vm/wrappers.h index b9e40e89979b8..a256cb56ea3b2 100644 --- a/src/coreclr/src/vm/wrappers.h +++ b/src/coreclr/src/vm/wrappers.h @@ -109,11 +109,13 @@ inline void SafeComReleasePreemp(TYPE *value) SafeReleasePreemp((IUnknown*)value); } -NEW_WRAPPER_TEMPLATE1(SafeComHolder, SafeComRelease<_TYPE>); +template +using SafeComHolder = SpecializedWrapper<_TYPE, SafeComRelease<_TYPE>>; // Use this holder if you're already in preemptive mode for other reasons, // use SafeComHolder otherwise. -NEW_WRAPPER_TEMPLATE1(SafeComHolderPreemp, SafeComReleasePreemp<_TYPE>); +template +using SafeComHolderPreemp = SpecializedWrapper<_TYPE, SafeComReleasePreemp<_TYPE>>; @@ -166,7 +168,8 @@ void DeletePreemp(TYPE *value) delete value; } -NEW_WRAPPER_TEMPLATE1(NewPreempHolder, DeletePreemp<_TYPE>); +template +using NewPreempHolder = SpecializedWrapper<_TYPE, DeletePreemp<_TYPE>>; //----------------------------------------------------------------------------- diff --git a/src/coreclr/src/vm/zapsig.cpp b/src/coreclr/src/vm/zapsig.cpp index f0b836182f725..515ea2fb4dc1f 100644 --- a/src/coreclr/src/vm/zapsig.cpp +++ b/src/coreclr/src/vm/zapsig.cpp @@ -650,7 +650,7 @@ Module *ZapSig::DecodeModuleFromIndex(Module *fromModule, { if (nativeImage != NULL) { - pAssembly = nativeImage->LoadComponentAssembly(index); + pAssembly = nativeImage->LoadManifestAssembly(index); } else { diff --git a/src/coreclr/tests/dir.common.props b/src/coreclr/tests/dir.common.props index a6a75547a9f66..4fadf00b83276 100644 --- a/src/coreclr/tests/dir.common.props +++ b/src/coreclr/tests/dir.common.props @@ -12,7 +12,7 @@ $(TargetOS).$(TargetArchitecture).$(Configuration) - $(MSBuildThisFileDirectory)src + $(MSBuildThisFileDirectory)src $([MSBuild]::MakeRelative($(TestSrcDir), $(MSBuildProjectDirectory)))\$(MSBuildProjectName)\ - + @@ -33,10 +33,15 @@ RunInUnloadableContext=$(_RunInUnloadableContext); TimeoutPerTestCollectionInMinutes=$(_TimeoutPerTestCollectionInMinutes); TimeoutPerTestInMinutes=$(_TimeoutPerTestInMinutes); - RuntimeMode=$(_RuntimeMode) + RuntimeVariant=$(_RuntimeVariant); + BundledNETCoreAppPackageVersion=$(BundledNETCoreAppPackageVersion); + HelixRuntimeRid=$(HelixRuntimeRid) + + + @@ -59,12 +64,25 @@ + + + win-$(TargetArchitecture) + osx-$(TargetArchitecture) + linux-$(TargetArchitecture) + linux-musl-$(TargetArchitecture) + + $([MSBuild]::NormalizeDirectory($(TestWorkingDir))) $(BinDir)Tests\Core_Root\ $(BinDir)Payloads\ SetStressModes_$(Scenario).cmd SetStressModes_$(Scenario).sh + + true + runtime + $(BundledNETCoreAppPackageVersion) + $(HelixRuntimeRid) @@ -181,7 +199,6 @@ R2R-CG2 $(TestRunNamePrefix)$(TargetOS) $(TargetArchitecture) $(Configuration) @ $(TestRunNamePrefix)$(TargetOS) $(TargetArchitecture) $(Configuration) $(Scenario) @ - $(TestRunNamePrefix) Interpreter $([System.TimeSpan]::FromMinutes($(TimeoutPerTestInMinutes)).TotalMilliseconds) true <_XUnitParallelMode>collections @@ -208,7 +225,6 @@ - @@ -228,7 +244,6 @@ - @@ -236,12 +251,10 @@ - %CORE_ROOT%\CoreRun.exe %CORE_ROOT%\xunit.console.dll - $CORE_ROOT/corerun $CORE_ROOT/xunit.console.dll @@ -263,12 +276,13 @@ %(PayloadDirectory) - $(CoreRun) $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) - $(CoreRun) $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) -trait TestGroup=%(TestGroup) + dotnet $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) + dotnet $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) -trait TestGroup=%(TestGroup) $([System.TimeSpan]::FromMinutes($(TimeoutPerTestCollectionInMinutes))) + diff --git a/src/coreclr/tests/issues.targets b/src/coreclr/tests/issues.targets index 2c4deacb2d010..2b17bcb6e9b79 100644 --- a/src/coreclr/tests/issues.targets +++ b/src/coreclr/tests/issues.targets @@ -79,7 +79,6 @@ 19441;22020 - https://github.com/dotnet/runtime/issues/3893 @@ -116,6 +115,12 @@ https://github.com/dotnet/runtime/issues/3893 + + https://github.com/dotnet/runtime/issues/36850 + + + This test is to verify we are running mono, and therefore only makes sense on mono. + @@ -321,6 +326,9 @@ needs triage + + https://github.com/dotnet/runtime/issues/36418 + https://github.com/dotnet/runtime/issues/12216 @@ -596,57 +604,12 @@ https://github.com/dotnet/runtime/issues/31729 - - https://github.com/dotnet/runtime/issues/7430 - extremely memory/time intensive test - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - https://github.com/dotnet/runtime/issues/9270 - - https://github.com/dotnet/runtime/issues/7430 - - - https://github.com/dotnet/runtime/issues/7430 - needs triage @@ -999,6 +962,12 @@ + + PlatformDetection.IsPreciseGcSupported false on mono + + + PlatformDetection.IsPreciseGcSupported false on mono + needs triage @@ -1305,36 +1274,9 @@ needs triage - - needs triage - - - needs triage - - - needs triage - - - needs triage - - - needs triage - - - needs triage - - - needs triage - https://github.com/dotnet/runtime/issues/34068 - - needs triage - - - needs triage - https://github.com/dotnet/runtime/issues/34068 @@ -1344,9 +1286,6 @@ https://github.com/dotnet/runtime/issues/34068 - - needs triage - https://github.com/dotnet/runtime/issues/34068 @@ -1419,12 +1358,6 @@ needs triage - - needs triage - - - needs triage - https://github.com/dotnet/runtime/issues/34068 @@ -1440,18 +1373,6 @@ https://github.com/dotnet/runtime/issues/34068 - - https://github.com/dotnet/runtime/issues/34379 - - - needs triage - - - needs triage - - - needs triage - needs triage @@ -1597,7 +1518,6 @@ needs triage - needs triage needs triage @@ -1910,5 +1830,768 @@ needs triage + + + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + + + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + needs triage + + + + + needs triage + + diff --git a/src/coreclr/tests/runtest.py b/src/coreclr/tests/runtest.py index 68444d5d44089..e5ef2b0528ed1 100755 --- a/src/coreclr/tests/runtest.py +++ b/src/coreclr/tests/runtest.py @@ -934,6 +934,9 @@ def run_tests(args, print("Setting CORE_ROOT=%s" % args.core_root) os.environ["CORE_ROOT"] = args.core_root + # Set __TestDotNetCmd so tests which need to run dotnet can use the repo-local script on dev boxes + os.environ["__TestDotNetCmd"] = args.dotnetcli_script_path + # Set test env script path if it is set. if test_env_script_path is not None: print("Setting __TestEnv=%s" % test_env_script_path) diff --git a/src/coreclr/tests/scripts/run-corefx-tests.sh b/src/coreclr/tests/scripts/run-corefx-tests.sh index 03d186f04c9d5..39a87d03834d2 100755 --- a/src/coreclr/tests/scripts/run-corefx-tests.sh +++ b/src/coreclr/tests/scripts/run-corefx-tests.sh @@ -16,7 +16,7 @@ usage() echo "Flavor/OS/Architecture options:" echo " --configuration Configuration to run (Debug/Release)" echo " default: Debug" - echo " --os OS to run (FreeBSD, Linux, NetBSD or OSX)" + echo " --os OS to run (FreeBSD, Linux, NetBSD, OSX, SunOS)" echo " default: detect current OS" echo " --arch Architecture to run (x64, arm, armel, x86, arm64)" echo " default: detect current architecture" @@ -37,7 +37,7 @@ usage() echo "Runtime Code Coverage options:" echo " --coreclr-coverage Optional argument to get coreclr code coverage reports" echo " --coreclr-objs Location of root of the object directory" - echo " containing the FreeBSD, Linux, NetBSD or OSX coreclr build" + echo " containing the FreeBSD, Linux, NetBSD, OSX or SunOS coreclr build" echo " default: /bin/obj/.x64. Location of root of the directory" echo " containing the coreclr source files" @@ -81,6 +81,10 @@ case $OSName in OS=NetBSD ;; + SunOS) + OS=SunOS + ;; + *) echo "Unsupported OS $OSName detected, configuring as if for Linux" OS=Linux @@ -342,7 +346,7 @@ run_test() coreclr_code_coverage() { - if [ ! "$OS" == "FreeBSD" ] && [ ! "$OS" == "Linux" ] && [ ! "$OS" == "NetBSD" ] && [ ! "$OS" == "OSX" ] ; then + if [ "$OS" != "FreeBSD" ] && [ "$OS" != "Linux" ] && [ "$OS" != "NetBSD" ] && [ "$OS" != "OSX" ] && [ "$OS" != "SunOS" ] ; then echo "error: Code Coverage not supported on $OS" exit 1 fi @@ -501,9 +505,9 @@ then exit 1 fi -if [ ! "$OS" == "FreeBSD" ] && [ ! "$OS" == "Linux" ] && [ ! "$OS" == "NetBSD" ] && [ ! "$OS" == "OSX" ] +if [ "$OS" != "FreeBSD" ] && [ "$OS" != "Linux" ] && [ "$OS" != "NetBSD" ] && [ "$OS" != "OSX" ] && [ "$OS" != "SunOS" ] then - echo "error: OS should be FreeBSD, Linux, NetBSD or OSX" + echo "error: OS should be FreeBSD, Linux, NetBSD, OSX or SunOS" exit 1 fi diff --git a/src/coreclr/tests/scripts/run-gc-reliability-framework.sh b/src/coreclr/tests/scripts/run-gc-reliability-framework.sh index 8f8886a1bc84d..c136c1561ec9c 100755 --- a/src/coreclr/tests/scripts/run-gc-reliability-framework.sh +++ b/src/coreclr/tests/scripts/run-gc-reliability-framework.sh @@ -18,6 +18,9 @@ case $OSName in OS=NetBSD ;; + SunOS) + OS=SunOS + ;; *) echo "Unsupported OS $OSName detected, configuring as if for Linux" OS=Linux diff --git a/src/coreclr/tests/setup-stress-dependencies.sh b/src/coreclr/tests/setup-stress-dependencies.sh index 400a78003f6d5..a81c8fff7b2a7 100755 --- a/src/coreclr/tests/setup-stress-dependencies.sh +++ b/src/coreclr/tests/setup-stress-dependencies.sh @@ -82,7 +82,7 @@ if [ -z "$libInstallDir" ]; then exit_with_error 1 fi -if [ "$__BuildArch" == "arm64" ] || [ "$__BuildArch" == "arm" ]; then +if [ "$__BuildArch" = "arm64" ] || [ "$__BuildArch" = "arm" ]; then echo "No runtime dependencies for arm32/arm64" exit $EXIT_CODE_SUCCESS fi diff --git a/src/coreclr/tests/src/CLRTest.CrossGen.targets b/src/coreclr/tests/src/CLRTest.CrossGen.targets index 00c9990b19d27..0dcc732202f75 100644 --- a/src/coreclr/tests/src/CLRTest.CrossGen.targets +++ b/src/coreclr/tests/src/CLRTest.CrossGen.targets @@ -83,7 +83,12 @@ if [ ! -z ${RunCrossGen2+x} ]%3B then rm $__ResponseFile __Command=$_DebuggerFullPath - __Command+=" $CORE_ROOT/corerun" + # Tests run locally need __TestDotNetCmd (set by runtest.py) or a compatible 5.0 dotnet runtime in the path + if [ ! -z ${__TestDotNetCmd+x} ] %3B then + __Command+=" $__TestDotNetCmd" + else + __Command+=" dotnet" + fi __Command+=" $CORE_ROOT/crossgen2/crossgen2.dll" __Command+=" @$__ResponseFile" __Command+=" $ExtraCrossGen2Args" @@ -178,7 +183,12 @@ if defined RunCrossGen2 ( del /Q !__ResponseFile! set __Command=!_DebuggerFullPath! - set __Command=!__Command! "!CORE_ROOT!\CoreRun.exe" + REM Tests run locally need __TestDotNetCmd (set by runtest.py) or a compatible 5.0 dotnet runtime in the path + if defined __TestDotNetCmd ( + set __Command=!__Command! "!__TestDotNetCmd!" + ) else ( + set __Command=!__Command! "dotnet" + ) set __Command=!__Command! "!CORE_ROOT!\crossgen2\crossgen2.dll" set __Command=!__Command! @"!__ResponseFile!" set __Command=!__Command! !ExtraCrossGen2Args! diff --git a/src/coreclr/tests/src/Common/Directory.Build.targets b/src/coreclr/tests/src/Common/Directory.Build.targets index c4e3b79c5eddb..65ff6bd275946 100644 --- a/src/coreclr/tests/src/Common/Directory.Build.targets +++ b/src/coreclr/tests/src/Common/Directory.Build.targets @@ -58,26 +58,37 @@ - + + True + - + + True + + + ubuntu.14.04-$(TargetArchitecture) + + + true + true + ubuntu.14.04-$(TargetArchitecture) + + + + + true + true + ubuntu.14.04-$(TargetArchitecture) + + @@ -116,7 +130,7 @@ - true + true C# IL diff --git a/src/coreclr/tests/src/GC/API/GC/AddMemoryPressureTest.cs b/src/coreclr/tests/src/GC/API/GC/AddMemoryPressureTest.cs deleted file mode 100644 index 52b98eb7f0d21..0000000000000 --- a/src/coreclr/tests/src/GC/API/GC/AddMemoryPressureTest.cs +++ /dev/null @@ -1,210 +0,0 @@ -// 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. - -/* AddMemoryPressureTest - * - * Tests GC.AddMemoryPressure by passing it values that are too small (<=0) and - * values that are too large (>Int32.MaxValue on 32-bit). - * The stress test doubles the pressure (2xInt32.MaxValue), and verifies - * valid behaviour. - */ - - - - -using System; -using System.Diagnostics; -using System.Security; -using System.Runtime.InteropServices; - -public class Dummy -{ - private long _pressure = 0; - private int _numTimes = 0; - - public Dummy(bool heavy) - { - if (heavy) - { - _pressure = Int32.MaxValue; - _numTimes = 2; - for (int i = 0; i < _numTimes; i++) - GC.AddMemoryPressure(_pressure); - } - } - - ~Dummy() - { - for (int i = 0; i < _numTimes; i++) - GC.RemoveMemoryPressure(_pressure); - } -} - -public class AddMemoryPressureTest -{ - public int TestCount = 0; - - private long[] _negValues = { 0, -1, Int32.MinValue - (long)1, Int64.MinValue / (long)2, Int64.MinValue }; - private long[] _largeValues = { Int32.MaxValue + (long)1, Int64.MaxValue }; - - - private AddMemoryPressureTest() - { - } - - - public bool TooSmallTest() - { - TestCount++; - bool retVal = true; - - foreach (long i in _negValues) - { - try - { - GC.AddMemoryPressure(i); - Console.WriteLine("Failure at TooSmallTest: {0}", i); - retVal = false; - break; - } - catch (ArgumentOutOfRangeException) - { - } - catch (Exception e) - { - Console.WriteLine(e.Message); - Console.WriteLine("Failure at TooSmallTest: {0}", i); - retVal = false; - break; - } - } - - if (retVal) - Console.WriteLine("TooSmallTest Passed"); - return retVal; - } - - - public bool TooLargeTest() - { - TestCount++; - - bool retVal = true; - - foreach (long i in _largeValues) - { - try - { - GC.AddMemoryPressure(i); - // this should not throw exception on 64-bit - if (IntPtr.Size == Marshal.SizeOf(new Int32())) - { - Console.WriteLine("Failure at LargeValueTest: {0}", i); - retVal = false; - break; - } - else - { - GC.RemoveMemoryPressure(i); - } - } - catch (ArgumentOutOfRangeException) - { - // this should not throw exception on 64-bit - if (IntPtr.Size == Marshal.SizeOf(new Int64())) - { - Console.WriteLine("Failure at LargeValueTest: {0}", i); - retVal = false; - break; - } - } - catch (Exception e) - { - Console.WriteLine(e.Message); - retVal = false; - break; - } - } - - if (retVal) - Console.WriteLine("TooLargeTest Passed"); - return retVal; - } - - - public bool StressTest() - { - TestCount++; - - Console.WriteLine("StressTest Started..."); - - int gcCount1 = createDummies(true); - - - int gcCount2 = createDummies(false); - - Console.WriteLine("{0} {1}", gcCount1, gcCount2); - if (gcCount1 > gcCount2) - { - Console.WriteLine("StressTest Passed"); - Console.WriteLine(); - return true; - } - - Console.WriteLine("StressTest Failed"); - - Console.WriteLine(); - return false; - } - - - private int createDummies(bool heavy) - { - int gcCount = GC.CollectionCount(0); - - for (int i = 0; i < 100; i++) - { - Dummy dummy = new Dummy(heavy); - int gen = GC.GetGeneration(dummy); - if (gen != 0) - { - Console.WriteLine("Warning: newly-allocated dummy ended up in gen {0}", gen); - } - } - - return GC.CollectionCount(0) - gcCount; - } - - - public bool RunTest() - { - int passCount = 0; - - if (TooSmallTest()) - passCount++; - - if (TooLargeTest()) - passCount++; - - if (StressTest()) - passCount++; - - return (passCount == TestCount); - } - - - public static int Main() - { - AddMemoryPressureTest test = new AddMemoryPressureTest(); - - if (test.RunTest()) - { - Console.WriteLine("Test Passed"); - return 100; - } - - Console.WriteLine("Test Failed"); - return 1; - } -} diff --git a/src/coreclr/tests/src/GC/API/GC/AddMemoryPressureTest.csproj b/src/coreclr/tests/src/GC/API/GC/AddMemoryPressureTest.csproj deleted file mode 100644 index 108d33023306e..0000000000000 --- a/src/coreclr/tests/src/GC/API/GC/AddMemoryPressureTest.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - Exe - - - - PdbOnly - true - - - - - diff --git a/src/coreclr/tests/src/GC/API/GC/RemoveMemoryPressureTest.cs b/src/coreclr/tests/src/GC/API/GC/RemoveMemoryPressureTest.cs deleted file mode 100644 index e288efb6f8c07..0000000000000 --- a/src/coreclr/tests/src/GC/API/GC/RemoveMemoryPressureTest.cs +++ /dev/null @@ -1,132 +0,0 @@ -// 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. - -/* RemoveMemoryPressureTest - * - * Tests GC.RemoveMemoryPressure by passing it values that are too small (<=0) and - * values that are too large (>Int32.MaxValue on 32-bit). - */ - - -using System; -using System.Diagnostics; -using System.Security; -using System.Runtime.InteropServices; - -public class RemoveMemoryPressureTest -{ - public int TestCount = 0; - - private long[] _negValues = { 0, -1, Int32.MinValue - (long)1, Int64.MinValue / (long)2, Int64.MinValue }; - private long[] _largeValues = { Int32.MaxValue + (long)1, Int64.MaxValue }; - - - private RemoveMemoryPressureTest() - { - } - - - public bool TooSmallTest() - { - TestCount++; - bool retVal = true; - - foreach (long i in _negValues) - { - try - { - GC.RemoveMemoryPressure(i); - Console.WriteLine("Failure at TooSmallTest: {0}", i); - retVal = false; - break; - } - catch (ArgumentOutOfRangeException) - { - } - catch (Exception e) - { - Console.WriteLine(e.Message); - Console.WriteLine("Failure at TooSmallTest: {0}", i); - retVal = false; - break; - } - } - - if (retVal) - Console.WriteLine("TooSmallTest Passed"); - return retVal; - } - - - public bool TooLargeTest() - { - TestCount++; - - bool retVal = true; - - foreach (long i in _largeValues) - { - try - { - GC.RemoveMemoryPressure(i); - // this should throw exception on 32-bit - if (IntPtr.Size == Marshal.SizeOf(new Int32())) - { - Console.WriteLine("Failure at LargeValueTest: {0}", i); - retVal = false; - break; - } - } - catch (ArgumentOutOfRangeException) - { - // this should not throw exception on 64-bit - if (IntPtr.Size == Marshal.SizeOf(new Int64())) - { - Console.WriteLine("Failure at LargeValueTest: {0}", i); - retVal = false; - break; - } - } - catch (Exception e) - { - Console.WriteLine(e.Message); - retVal = false; - break; - } - } - - if (retVal) - Console.WriteLine("TooLargeTest Passed"); - return retVal; - } - - - public bool RunTest() - { - int passCount = 0; - - if (TooSmallTest()) - passCount++; - - if (TooLargeTest()) - passCount++; - - return (passCount == TestCount); - } - - - public static int Main() - { - RemoveMemoryPressureTest test = new RemoveMemoryPressureTest(); - - if (test.RunTest()) - { - Console.WriteLine("Test Passed"); - return 100; - } - - Console.WriteLine("Test Failed"); - return 1; - } -} diff --git a/src/coreclr/tests/src/GC/API/GC/RemoveMemoryPressureTest.csproj b/src/coreclr/tests/src/GC/API/GC/RemoveMemoryPressureTest.csproj deleted file mode 100644 index bb01dcdf950c7..0000000000000 --- a/src/coreclr/tests/src/GC/API/GC/RemoveMemoryPressureTest.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - Exe - - - - PdbOnly - - - - - diff --git a/src/coreclr/tests/src/Interop/CMakeLists.txt b/src/coreclr/tests/src/Interop/CMakeLists.txt index 8a39e97624f93..778d9ab3bded8 100644 --- a/src/coreclr/tests/src/Interop/CMakeLists.txt +++ b/src/coreclr/tests/src/Interop/CMakeLists.txt @@ -81,6 +81,7 @@ if(CLR_CMAKE_TARGET_WIN32) add_subdirectory(COM/NativeClients/Dispatch) add_subdirectory(COM/NativeClients/Events) add_subdirectory(COM/ComWrappers/MockReferenceTrackerRuntime) + add_subdirectory(COM/ComWrappers/WeakReference) add_subdirectory(WinRT/NativeComponent) # IJW isn't supported on ARM64 diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/Common.cs b/src/coreclr/tests/src/Interop/COM/ComWrappers/Common.cs index 2f322018f0f80..0e75049200c9b 100644 --- a/src/coreclr/tests/src/Interop/COM/ComWrappers/Common.cs +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/Common.cs @@ -11,6 +11,7 @@ namespace ComWrappersTests.Common // Managed object with native wrapper definition. // [Guid("447BB9ED-DA48-4ABC-8963-5BB5C3E0AA09")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ITest { void SetValue(int i); diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs b/src/coreclr/tests/src/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs index ef9870b08672d..b362bc641b037 100644 --- a/src/coreclr/tests/src/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs @@ -48,9 +48,9 @@ struct MarshalInterface [DllImport(nameof(MockReferenceTrackerRuntime))] extern public static int UpdateTestObjectAsInterface( - [MarshalAs(UnmanagedType.Interface)] Test testObj, + [MarshalAs(UnmanagedType.Interface)] ITest testObj, int i, - [Out, MarshalAs(UnmanagedType.Interface)] out Test ret); + [Out, MarshalAs(UnmanagedType.Interface)] out ITest ret); } private const string ManagedServerTypeName = "ConsumeNETServerTesting"; @@ -298,6 +298,11 @@ private static void ValidateMarshalAPIs(bool validateUseRegistered) IntPtr dispatchWrapper = Marshal.GetIDispatchForObject(dispatchObj); Assert.AreNotEqual(IntPtr.Zero, dispatchWrapper); Assert.AreEqual(dispatchObj, registeredWrapper.LastComputeVtablesObject, "Registered ComWrappers instance should have been called"); + + Console.WriteLine($" -- Validate Marshal.GetIDispatchForObject != Marshal.GetIUnknownForObject..."); + IntPtr unknownWrapper = Marshal.GetIUnknownForObject(dispatchObj); + Assert.AreNotEqual(IntPtr.Zero, unknownWrapper); + Assert.AreNotEqual(unknownWrapper, dispatchWrapper); } Console.WriteLine($" -- Validate Marshal.GetObjectForIUnknown..."); @@ -326,33 +331,33 @@ private static void ValidatePInvokes(bool validateUseRegistered) GlobalComWrappers.Instance.ReturnInvalid = !validateUseRegistered; Console.WriteLine($" -- Validate MarshalAs IUnknown..."); - ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsIUnknown, validateUseRegistered); + ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsIUnknown, shouldSucceed: validateUseRegistered); object obj = MarshalInterface.CreateTrackerObjectAsIUnknown(); Assert.AreEqual(validateUseRegistered, obj is FakeWrapper, $"Should{(validateUseRegistered ? string.Empty : "not")} have returned {nameof(FakeWrapper)} instance"); if (validateUseRegistered) { Console.WriteLine($" -- Validate MarshalAs IDispatch..."); - ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsIDispatch, validateUseRegistered, new TestEx(IID_IDISPATCH)); + ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsIDispatch, shouldSucceed: true, new TestEx(IID_IDISPATCH)); Console.WriteLine($" -- Validate MarshalAs IInspectable..."); - ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsIInspectable, validateUseRegistered, new TestEx(IID_IINSPECTABLE)); + ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsIInspectable, shouldSucceed: true, new TestEx(IID_IINSPECTABLE)); } Console.WriteLine($" -- Validate MarshalAs Interface..."); - ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsInterface, validateUseRegistered); + ValidateInterfaceMarshaler(MarshalInterface.UpdateTestObjectAsInterface, shouldSucceed: true); if (validateUseRegistered) { Assert.Throws(() => MarshalInterface.CreateTrackerObjectWrongType()); FakeWrapper wrapper = MarshalInterface.CreateTrackerObjectAsInterface(); - Assert.IsNotNull(obj, $"Should have returned {nameof(FakeWrapper)} instance"); + Assert.IsNotNull(wrapper, $"Should have returned {nameof(FakeWrapper)} instance"); } } private delegate int UpdateTestObject(T testObj, int i, out T ret) where T : class; - private static void ValidateInterfaceMarshaler(UpdateTestObject func, bool validateUseRegistered, Test testObj = null) where T : class + private static void ValidateInterfaceMarshaler(UpdateTestObject func, bool shouldSucceed, Test testObj = null) where T : class { const int E_NOINTERFACE = unchecked((int)0x80004002); int value = 10; @@ -363,7 +368,7 @@ private static void ValidatePInvokes(bool validateUseRegistered) T retObj; int hr = func(testObj as T, value, out retObj); Assert.AreEqual(testObj, GlobalComWrappers.Instance.LastComputeVtablesObject, "Registered ComWrappers instance should have been called"); - if (validateUseRegistered) + if (shouldSucceed) { Assert.IsTrue(retObj is Test); Assert.AreEqual(value, testObj.GetValue()); diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp b/src/coreclr/tests/src/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp index 867efa01866e4..54cf0bb31f14b 100644 --- a/src/coreclr/tests/src/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp @@ -374,5 +374,10 @@ extern "C" DLL_EXPORT int STDMETHODCALLTYPE UpdateTestObjectAsInterface(ITest *o if (obj == nullptr) return E_POINTER; - return UpdateTestObjectAsIUnknown(obj, i, (IUnknown**)out); + HRESULT hr; + RETURN_IF_FAILED(obj->SetValue(i)); + + obj->AddRef(); + *out = obj; + return S_OK; } diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/CMakeLists.txt b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/CMakeLists.txt new file mode 100644 index 0000000000000..8166db2186574 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/CMakeLists.txt @@ -0,0 +1,10 @@ +project (WeakReferenceNative) +include_directories( ${INC_PLATFORM_DIR} ) +set(SOURCES WeakReferenceNative.cpp) + +# add the shared library +add_library (WeakReferenceNative SHARED ${SOURCES}) +target_link_libraries(WeakReferenceNative ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS WeakReferenceNative DESTINATION bin) diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp new file mode 100644 index 0000000000000..5617b11767981 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp @@ -0,0 +1,124 @@ +// 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. + +#include +#include +#include +#include + +namespace +{ + struct WeakReference : public IWeakReference, public UnknownImpl + { + IInspectable* _reference; + std::atomic _strongRefCount; + + WeakReference(IInspectable* reference, ULONG strongRefCount) + : _reference(reference), + _strongRefCount(strongRefCount) + {} + + ULONG AddStrongRef() + { + assert(_strongRefCount > 0); + return (++_strongRefCount); + } + + ULONG ReleaseStrongRef() + { + assert(_strongRefCount > 0); + return --_strongRefCount; + } + + STDMETHOD(Resolve)(REFIID riid, IInspectable** ppvObject) + { + if (_strongRefCount > 0) + { + void* pObject; + HRESULT hr = _reference->QueryInterface(riid, &pObject); + *ppvObject = reinterpret_cast(pObject); + return hr; + } + return E_NOINTERFACE; + } + + STDMETHOD(QueryInterface)( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) + { + return DoQueryInterface(riid, ppvObject, static_cast(this)); + } + + DEFINE_REF_COUNTING() + }; + + struct WeakReferencableObject : public IWeakReferenceSource, public IInspectable, public UnknownImpl + { + ComSmartPtr _weakReference; + STDMETHOD(GetWeakReference)(_COM_Outptr_ IWeakReference** ppWeakReference) + { + if (!_weakReference) + { + ULONG refCount = UnknownImpl::GetRefCount(); + _weakReference = new WeakReference(this, refCount); + } + _weakReference->AddRef(); + *ppWeakReference = _weakReference; + return S_OK; + } + + STDMETHOD(GetRuntimeClassName)(HSTRING* pRuntimeClassName) + { + return E_NOTIMPL; + } + + STDMETHOD(GetIids)( + ULONG *iidCount, + IID **iids) + { + return E_NOTIMPL; + } + + STDMETHOD(GetTrustLevel)(TrustLevel *trustLevel) + { + *trustLevel = FullTrust; + return S_OK; + } + + STDMETHOD(QueryInterface)( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) + { + HRESULT hr = DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this), static_cast(this)); + if (SUCCEEDED(hr) && _weakReference) + { + _weakReference->AddStrongRef(); + } + return hr; + } + STDMETHOD_(ULONG, AddRef)(void) + { + if (_weakReference) + { + return _weakReference->AddStrongRef(); + } + return UnknownImpl::DoAddRef(); + } + STDMETHOD_(ULONG, Release)(void) + { + if (_weakReference) + { + ULONG c = _weakReference->ReleaseStrongRef(); + if (c == 0) + delete this; + return c; + } + return UnknownImpl::DoRelease(); + } + }; +} +extern "C" DLL_EXPORT WeakReferencableObject* STDMETHODCALLTYPE CreateWeakReferencableObject() +{ + return new WeakReferencableObject(); +} diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs new file mode 100644 index 0000000000000..f85138f72c1da --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs @@ -0,0 +1,133 @@ +// 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. + +namespace ComWrappersTests +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using TestLibrary; + + static class WeakReferenceNative + { + [DllImport(nameof(WeakReferenceNative))] + public static extern IntPtr CreateWeakReferencableObject(); + } + + public struct VtblPtr + { + public IntPtr Vtbl; + } + + public class WeakReferencableWrapper + { + private struct Vtbl + { + public IntPtr QueryInterface; + public _AddRef AddRef; + public _Release Release; + } + + private delegate int _AddRef(IntPtr This); + private delegate int _Release(IntPtr This); + + private readonly IntPtr instance; + private readonly Vtbl vtable; + + public WeakReferencableWrapper(IntPtr instance) + { + var inst = Marshal.PtrToStructure(instance); + this.vtable = Marshal.PtrToStructure(inst.Vtbl); + this.instance = instance; + } + + ~WeakReferencableWrapper() + { + if (this.instance != IntPtr.Zero) + { + this.vtable.Release(this.instance); + } + } + } + + class Program + { + class TestComWrappers : ComWrappers + { + protected unsafe override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + count = 0; + return null; + } + + protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flag) + { + Marshal.AddRef(externalComObject); + return new WeakReferencableWrapper(externalComObject); + } + + protected override void ReleaseObjects(IEnumerable objects) + { + } + + public static readonly ComWrappers Instance = new TestComWrappers(); + } + + static void ValidateNativeWeakReference() + { + Console.WriteLine($"Running {nameof(ValidateNativeWeakReference)}..."); + + static (WeakReference, IntPtr) GetWeakReference() + { + var cw = new TestComWrappers(); + + IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject(); + + var obj = (WeakReferencableWrapper)cw.GetOrCreateObjectForComInstance(objRaw, CreateObjectFlags.None); + + return (new WeakReference(obj), objRaw); + } + + static bool CheckIfWeakReferenceIsAlive(WeakReference wr) + { + return wr.TryGetTarget(out _); + } + + var (weakRef, nativeRef) = GetWeakReference(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + // A weak reference to an RCW wrapping an IWeakReference should stay alive even after the RCW dies + Assert.IsTrue(CheckIfWeakReferenceIsAlive(weakRef)); + + // Release the last native reference. + Marshal.Release(nativeRef); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + + // After all native references die and the RCW is collected, the weak reference should be dead and stay dead. + Assert.IsFalse(CheckIfWeakReferenceIsAlive(weakRef)); + + } + + static int Main(string[] doNotUse) + { + try + { + ComWrappers.RegisterForTrackerSupport(TestComWrappers.Instance); + ValidateNativeWeakReference(); + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } + } +} + diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj new file mode 100644 index 0000000000000..97dd973ac5472 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj @@ -0,0 +1,23 @@ + + + Exe + + true + + true + true + true + + + + + + + + + 1 + + + + + diff --git a/src/coreclr/tests/src/Interop/common/ComHelpers.h b/src/coreclr/tests/src/Interop/common/ComHelpers.h index c90ff7a773a2e..673f19063647d 100644 --- a/src/coreclr/tests/src/Interop/common/ComHelpers.h +++ b/src/coreclr/tests/src/Interop/common/ComHelpers.h @@ -105,6 +105,12 @@ class UnknownImpl return c; } +protected: + ULONG GetRefCount() + { + return _refCount; + } + private: std::atomic _refCount = 1; }; diff --git a/src/coreclr/tests/src/JIT/Directed/StructABI/StructABI.csproj b/src/coreclr/tests/src/JIT/Directed/StructABI/StructABI.csproj index cf56275343e57..6ea166cef9a44 100644 --- a/src/coreclr/tests/src/JIT/Directed/StructABI/StructABI.csproj +++ b/src/coreclr/tests/src/JIT/Directed/StructABI/StructABI.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/coreclr/tests/src/JIT/Directed/StructABI/structreturn.cs b/src/coreclr/tests/src/JIT/Directed/StructABI/structreturn.cs index e63b9b27f843f..226818941c806 100644 --- a/src/coreclr/tests/src/JIT/Directed/StructABI/structreturn.cs +++ b/src/coreclr/tests/src/JIT/Directed/StructABI/structreturn.cs @@ -927,6 +927,406 @@ public static void Test() } #endregion +class TestHFA +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static float ReturnFloat() + { + return 1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static double ReturnDouble() + { + return 1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector2 ReturnVector2() + { + return new Vector2(1); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector3 ReturnVector3() + { + return new Vector3(1); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector4 ReturnVector4() + { + return new Vector4(1); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector4 ReturnVector4UsingCall() + { + return ReturnVector4(); + } + + struct FloatWrapper + { + public float f; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static FloatWrapper ReturnFloatWrapper() + { + return new FloatWrapper(); + } + + struct DoubleWrapper + { + public double f; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static DoubleWrapper ReturnDoubleWrapper() + { + return new DoubleWrapper(); + } + + struct Floats2Wrapper + { + public float f1; + public float f2; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Floats2Wrapper ReturnFloats2Wrapper() + { + return new Floats2Wrapper(); + } + + struct Doubles2Wrapper + { + public double f1; + public double f2; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Doubles2Wrapper ReturnDoubles2Wrapper() + { + return new Doubles2Wrapper(); + } + struct Floats3Wrapper + { + public float f1; + public float f2; + public float f3; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Floats3Wrapper ReturnFloats3Wrapper() + { + return new Floats3Wrapper(); + } + + struct Doubles3Wrapper + { + public double f1; + public double f2; + public double f3; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Doubles3Wrapper ReturnDoubles3Wrapper() + { + return new Doubles3Wrapper(); + } + + struct Floats4Wrapper + { + public float f1; + public float f2; + public float f3; + public float f4; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Floats4Wrapper ReturnFloats4Wrapper() + { + return new Floats4Wrapper(); + } + + struct Doubles4Wrapper + { + public double f1; + public double f2; + public double f3; + public double f4; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Doubles4Wrapper ReturnDoubles4Wrapper() + { + return new Doubles4Wrapper(); + } + + struct Vector2Wrapper + { + Vector2 f1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector2Wrapper ReturnVector2Wrapper() + { + return new Vector2Wrapper(); + } + + struct Vector3Wrapper + { + Vector3 f1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector3Wrapper ReturnVector3Wrapper() + { + return new Vector3Wrapper(); + } + + struct Vector4Wrapper + { + Vector4 f1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector4Wrapper ReturnVector4Wrapper() + { + return new Vector4Wrapper(); + } + + struct Vector2x2Wrapper + { + Vector2 f1; + Vector2 f2; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector2x2Wrapper ReturnVector2x2Wrapper() + { + return new Vector2x2Wrapper(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Test() + { + ReturnFloat(); + ReturnDouble(); + ReturnVector2(); + ReturnVector3(); + ReturnVector4(); + ReturnVector4UsingCall(); + ReturnFloatWrapper(); + ReturnDoubleWrapper(); + ReturnFloats2Wrapper(); + ReturnDoubles2Wrapper(); + ReturnFloats3Wrapper(); + ReturnDoubles3Wrapper(); + ReturnFloats4Wrapper(); + ReturnDoubles4Wrapper(); + ReturnVector2Wrapper(); + ReturnVector3Wrapper(); + ReturnVector4Wrapper(); + ReturnVector2x2Wrapper(); + } +} + +class TestNon2PowerStructs +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Byte3Struct + { + public byte f1; + public byte f2; + public byte f3; + + [MethodImpl(MethodImplOptions.NoInlining)] + public Byte3Struct(int v) + { + f1 = 1; + f2 = 2; + f3 = 3; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Byte5Struct + { + public byte f1; + public byte f2; + public byte f3; + public byte f4; + public byte f5; + + [MethodImpl(MethodImplOptions.NoInlining)] + public Byte5Struct(int v) + { + f1 = 4; + f2 = 5; + f3 = 6; + f4 = 7; + f5 = 8; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Byte6Struct + { + public byte f1; + public byte f2; + public byte f3; + public byte f4; + public byte f5; + public byte f6; + + [MethodImpl(MethodImplOptions.NoInlining)] + public Byte6Struct(int v) + { + f1 = 9; + f2 = 10; + f3 = 11; + f4 = 12; + f5 = 13; + f6 = 14; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Byte7Struct + { + public byte f1; + public byte f2; + public byte f3; + public byte f4; + public byte f5; + public byte f6; + public byte f7; + + [MethodImpl(MethodImplOptions.NoInlining)] + public Byte7Struct(int v) + { + f1 = 15; + f2 = 16; + f3 = 17; + f4 = 18; + f5 = 19; + f6 = 20; + f7 = 21; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CompositeOfOddStructs + { + public Byte3Struct a; + public Byte5Struct b; + public Byte6Struct c; + public Byte7Struct d; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Byte3Struct Return3() + { + return new Byte3Struct(0); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Byte5Struct Return5() + { + return new Byte5Struct(0); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Byte6Struct Return6() + { + return new Byte6Struct(0); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Byte7Struct Return7() + { + return new Byte7Struct(0); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static CompositeOfOddStructs CreateComposite() + { + CompositeOfOddStructs c = new CompositeOfOddStructs(); + c.a = Return3(); + c.b = Return5(); + c.c = Return6(); + c.d = Return7(); + return c; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void TestComposite() + { + var c = CreateComposite(); + Debug.Assert(c.a.f1 == 1); + Debug.Assert(c.a.f2 == 2); + Debug.Assert(c.a.f3 == 3); + Debug.Assert(c.b.f1 == 4); + Debug.Assert(c.b.f2 == 5); + Debug.Assert(c.b.f3 == 6); + Debug.Assert(c.b.f4 == 7); + Debug.Assert(c.b.f5 == 8); + Debug.Assert(c.c.f1 == 9); + Debug.Assert(c.c.f2 == 10); + Debug.Assert(c.c.f3 == 11); + Debug.Assert(c.c.f4 == 12); + Debug.Assert(c.c.f5 == 13); + Debug.Assert(c.c.f6 == 14); + Debug.Assert(c.d.f1 == 15); + Debug.Assert(c.d.f2 == 16); + Debug.Assert(c.d.f3 == 17); + Debug.Assert(c.d.f4 == 18); + Debug.Assert(c.d.f5 == 19); + Debug.Assert(c.d.f6 == 20); + Debug.Assert(c.d.f7 == 21); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static byte TestLocals(int v) + { + var a = Return3(); + var a1 = a; + a1.f1 = 0; + var b = Return5(); + var c = Return6(); + var d = Return7(); + if (v == 0) + { + return a.f1; + } + else if (v == 1) + { + return b.f1; + } + else if (v == 3) + { + return c.f1; + } + else if (v == 4) + { + return d.f1; + } + else + { + return a1.f1; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Test() + { + TestComposite(); + TestLocals(0); + } +} + class TestStructs { public static int Main() @@ -934,6 +1334,8 @@ public static int Main() TestStructReturns.Test(); TestUnsafeCasts.Test(); TestMergeReturnBlocks.Test(); + TestHFA.Test(); + TestNon2PowerStructs.Test(); return 100; } } diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_r.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_r.csproj index 3981b99a07c19..ce448a4678881 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_r.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_r.csproj @@ -101,6 +101,15 @@ + + + + + + + + + @@ -192,6 +201,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_ro.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_ro.csproj index 7b44b6ca06304..89c0b55761949 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_ro.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/AdvSimd.Arm64_ro.csproj @@ -101,6 +101,15 @@ + + + + + + + + + @@ -192,6 +201,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.Double.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.Double.1.cs new file mode 100644 index 0000000000000..b169f5ce0e6b1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.Double.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_Double_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] inArray, Double[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1 testClass) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Double*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Double); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + private static readonly byte Imm = 1; + + private static Double[] _data = new Double[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetDouble(); } + _dataTable = new DataTable(_data, new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Double*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Double*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Double*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Double*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Double_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Double*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Double*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Double*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Double[] inArray = new Double[Op1ElementCount]; + Double[] outArray = new Double[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.Int64.1.cs new file mode 100644 index 0000000000000..aa7692084ecd1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_Int64_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1 testClass) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.UInt64.1.cs new file mode 100644 index 0000000000000..c958bf8e36de1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateSelectedScalarToVector128.V128.UInt64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_UInt64_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1 testClass) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateSelectedScalarToVector128)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Double.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Double.31.cs new file mode 100644 index 0000000000000..25a9c6fb883a3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Double.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Double_31() + { + var test = new ImmOpTest__DuplicateToVector128_Double_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_Double_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_Double_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + (Double)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateToVector128), new Type[] { typeof(Double) }) + .Invoke(null, new object[] { + (Double)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Double[] outArray = new Double[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Double.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Double.cs new file mode 100644 index 0000000000000..f500029f5dafe --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Double.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Double() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Double(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_Double + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Double[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Double _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetDouble(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_Double testClass) + { + var result = AdvSimd.Arm64.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Double); + + private static Double _data; + + private static Double _clsVar; + + private Double _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_Double() + { + _clsVar = TestLibrary.Generator.GetDouble(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_Double() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetDouble(); + _data = TestLibrary.Generator.GetDouble(); + + _dataTable = new DataTable(new Double[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateToVector128), new Type[] { typeof(Double) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.Arm64.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Double(); + var result = AdvSimd.Arm64.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Double data, void* result, [CallerMemberName] string method = "") + { + Double[] outArray = new Double[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Double data, Double[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateToVector128)}(Double): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Int64.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Int64.31.cs new file mode 100644 index 0000000000000..cc3b5e8168d0c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Int64.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Int64_31() + { + var test = new ImmOpTest__DuplicateToVector128_Int64_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_Int64_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_Int64_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + (Int64)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateToVector128), new Type[] { typeof(Int64) }) + .Invoke(null, new object[] { + (Int64)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Int64[] outArray = new Int64[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Int64.cs new file mode 100644 index 0000000000000..11dd759214131 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.Int64.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Int64() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_Int64 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Int64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetInt64(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_Int64 testClass) + { + var result = AdvSimd.Arm64.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64 _data; + + private static Int64 _clsVar; + + private Int64 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_Int64() + { + _clsVar = TestLibrary.Generator.GetInt64(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_Int64() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetInt64(); + _data = TestLibrary.Generator.GetInt64(); + + _dataTable = new DataTable(new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateToVector128), new Type[] { typeof(Int64) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.Arm64.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Int64(); + var result = AdvSimd.Arm64.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Int64 data, void* result, [CallerMemberName] string method = "") + { + Int64[] outArray = new Int64[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Int64 data, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateToVector128)}(Int64): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.UInt64.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.UInt64.31.cs new file mode 100644 index 0000000000000..d1ebd0dd1ae65 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.UInt64.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_UInt64_31() + { + var test = new ImmOpTest__DuplicateToVector128_UInt64_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_UInt64_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_UInt64_31() + { + Succeeded = true; + + _dataTable = new DataTable(new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + (UInt64)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateToVector128), new Type[] { typeof(UInt64) }) + .Invoke(null, new object[] { + (UInt64)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + UInt64[] outArray = new UInt64[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.UInt64.cs new file mode 100644 index 0000000000000..58788479dbfd7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/DuplicateToVector128.UInt64.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_UInt64() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_UInt64 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public UInt64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetUInt64(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_UInt64 testClass) + { + var result = AdvSimd.Arm64.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64 _data; + + private static UInt64 _clsVar; + + private UInt64 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_UInt64() + { + _clsVar = TestLibrary.Generator.GetUInt64(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_UInt64() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetUInt64(); + _data = TestLibrary.Generator.GetUInt64(); + + _dataTable = new DataTable(new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.DuplicateToVector128), new Type[] { typeof(UInt64) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.Arm64.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_UInt64(); + var result = AdvSimd.Arm64.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt64 data, void* result, [CallerMemberName] string method = "") + { + UInt64[] outArray = new UInt64[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(UInt64 data, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.DuplicateToVector128)}(UInt64): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64.cs index 0b0f843a2b45c..b77756ecac2d5 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/Program.AdvSimd.Arm64.cs @@ -105,6 +105,15 @@ static Program() ["Divide.Vector64.Single"] = Divide_Vector64_Single, ["Divide.Vector128.Double"] = Divide_Vector128_Double, ["Divide.Vector128.Single"] = Divide_Vector128_Single, + ["DuplicateSelectedScalarToVector128.V128.Double.1"] = DuplicateSelectedScalarToVector128_V128_Double_1, + ["DuplicateSelectedScalarToVector128.V128.Int64.1"] = DuplicateSelectedScalarToVector128_V128_Int64_1, + ["DuplicateSelectedScalarToVector128.V128.UInt64.1"] = DuplicateSelectedScalarToVector128_V128_UInt64_1, + ["DuplicateToVector128.Double"] = DuplicateToVector128_Double, + ["DuplicateToVector128.Double.31"] = DuplicateToVector128_Double_31, + ["DuplicateToVector128.Int64"] = DuplicateToVector128_Int64, + ["DuplicateToVector128.Int64.31"] = DuplicateToVector128_Int64_31, + ["DuplicateToVector128.UInt64"] = DuplicateToVector128_UInt64, + ["DuplicateToVector128.UInt64.31"] = DuplicateToVector128_UInt64_31, ["FusedMultiplyAdd.Vector128.Double"] = FusedMultiplyAdd_Vector128_Double, ["FusedMultiplySubtract.Vector128.Double"] = FusedMultiplySubtract_Vector128_Double, ["Max.Vector128.Double"] = Max_Vector128_Double, @@ -196,6 +205,57 @@ static Program() ["ReverseElementBits.Vector128.SByte"] = ReverseElementBits_Vector128_SByte, ["ReverseElementBits.Vector64.Byte"] = ReverseElementBits_Vector64_Byte, ["ReverseElementBits.Vector64.SByte"] = ReverseElementBits_Vector64_SByte, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int16"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int16, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int32"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int32, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.SByte"] = ShiftArithmeticRoundedSaturateScalar_Vector64_SByte, + ["ShiftArithmeticSaturateScalar.Vector64.Int16"] = ShiftArithmeticSaturateScalar_Vector64_Int16, + ["ShiftArithmeticSaturateScalar.Vector64.Int32"] = ShiftArithmeticSaturateScalar_Vector64_Int32, + ["ShiftArithmeticSaturateScalar.Vector64.SByte"] = ShiftArithmeticSaturateScalar_Vector64_SByte, + ["ShiftLeftLogicalSaturateScalar.Vector64.Byte.7"] = ShiftLeftLogicalSaturateScalar_Vector64_Byte_7, + ["ShiftLeftLogicalSaturateScalar.Vector64.Int16.15"] = ShiftLeftLogicalSaturateScalar_Vector64_Int16_15, + ["ShiftLeftLogicalSaturateScalar.Vector64.Int32.31"] = ShiftLeftLogicalSaturateScalar_Vector64_Int32_31, + ["ShiftLeftLogicalSaturateScalar.Vector64.SByte.1"] = ShiftLeftLogicalSaturateScalar_Vector64_SByte_1, + ["ShiftLeftLogicalSaturateScalar.Vector64.UInt16.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1, + ["ShiftLeftLogicalSaturateScalar.Vector64.UInt32.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int16.5"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int32.7"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.SByte.3"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Byte"] = ShiftLogicalRoundedSaturateScalar_Vector64_Byte, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Int16"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int16, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Int32"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int32, + ["ShiftLogicalRoundedSaturateScalar.Vector64.SByte"] = ShiftLogicalRoundedSaturateScalar_Vector64_SByte, + ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt16"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt16, + ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt32"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt32, + ["ShiftLogicalSaturateScalar.Vector64.Byte"] = ShiftLogicalSaturateScalar_Vector64_Byte, + ["ShiftLogicalSaturateScalar.Vector64.Int16"] = ShiftLogicalSaturateScalar_Vector64_Int16, + ["ShiftLogicalSaturateScalar.Vector64.Int32"] = ShiftLogicalSaturateScalar_Vector64_Int32, + ["ShiftLogicalSaturateScalar.Vector64.SByte"] = ShiftLogicalSaturateScalar_Vector64_SByte, + ["ShiftLogicalSaturateScalar.Vector64.UInt16"] = ShiftLogicalSaturateScalar_Vector64_UInt16, + ["ShiftLogicalSaturateScalar.Vector64.UInt32"] = ShiftLogicalSaturateScalar_Vector64_UInt32, + ["ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int16.16"] = ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16, + ["ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int32.32"] = ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32, + ["ShiftRightArithmeticNarrowingSaturateScalar.Vector64.SByte.8"] = ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8, + ["ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.Byte.3"] = ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3, + ["ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt16.5"] = ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5, + ["ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt32.7"] = ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7, + ["ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int16.32"] = ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32, + ["ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int32.64"] = ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64, + ["ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.SByte.16"] = ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.Byte.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt16.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt32.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1, + ["ShiftRightLogicalNarrowingSaturateScalar.Vector64.Byte.5"] = ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5, + ["ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int16.7"] = ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7, + ["ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int32.11"] = ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11, + ["ShiftRightLogicalNarrowingSaturateScalar.Vector64.SByte.3"] = ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3, + ["ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt16.5"] = ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5, + ["ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt32.7"] = ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7, + ["ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Byte.1"] = ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1, + ["ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int16.1"] = ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1, + ["ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int32.1"] = ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1, + ["ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.SByte.1"] = ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1, + ["ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt16.1"] = ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1, + ["ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt32.1"] = ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1, ["Sqrt.Vector64.Single"] = Sqrt_Vector64_Single, ["Sqrt.Vector128.Double"] = Sqrt_Vector128_Double, ["Sqrt.Vector128.Single"] = Sqrt_Vector128_Single, diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.Int16.cs new file mode 100644 index 0000000000000..e51ebd01974e7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.Int16.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturateScalar_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16 testClass) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.Int32.cs new file mode 100644 index 0000000000000..9f6ad9c149212 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.Int32.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturateScalar_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32 testClass) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.SByte.cs new file mode 100644 index 0000000000000..39f57a814afe8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticRoundedSaturateScalar.Vector64.SByte.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturateScalar_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte testClass) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftArithmeticRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.Int16.cs new file mode 100644 index 0000000000000..d81b16d685d5f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.Int16.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturateScalar_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16 testClass) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.Int32.cs new file mode 100644 index 0000000000000..3d7ce320d0d36 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.Int32.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturateScalar_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32 testClass) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.SByte.cs new file mode 100644 index 0000000000000..1d9646ea270ef --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftArithmeticSaturateScalar.Vector64.SByte.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturateScalar_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte testClass) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftArithmeticSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Byte.7.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Byte.7.cs new file mode 100644 index 0000000000000..9898c2ed2f7a6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Byte.7.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_Byte_7() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 7; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Byte_7(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Int16.15.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Int16.15.cs new file mode 100644 index 0000000000000..0dfb9d9d160bc --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Int16.15.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_Int16_15() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 15); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 15 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 15; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + _clsVar, + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int16_15(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar)}(Vector64, 15): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Int32.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Int32.31.cs new file mode 100644 index 0000000000000..27a1c7f270356 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.Int32.31.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_Int32_31() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 31); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 31 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 31; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + _clsVar, + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int32_31(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar)}(Vector64, 31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..0f49096fe10e9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.SByte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..200e3b5ad23b0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.UInt16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..bff709b139225 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateScalar.Vector64.UInt32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int16.5.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int16.5.cs new file mode 100644 index 0000000000000..552b63a5892a3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int16.5.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 5); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 5 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 5; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + _clsVar, + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar)}(Vector64, 5): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int32.7.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int32.7.cs new file mode 100644 index 0000000000000..187916162c85f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int32.7.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 7; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.SByte.3.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.SByte.3.cs new file mode 100644 index 0000000000000..a8d31f1d364ea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.SByte.3.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3 testClass) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((SByte*)(pFld)), + 3 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 3; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + _clsVar, + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((SByte*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((SByte*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLeftLogicalSaturateUnsignedScalar)}(Vector64, 3): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Byte.cs new file mode 100644 index 0000000000000..ad9f8e72d368c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Byte.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Int16.cs new file mode 100644 index 0000000000000..20143758c29f9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Int16.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Int32.cs new file mode 100644 index 0000000000000..92071ffef73ea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.Int32.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.SByte.cs new file mode 100644 index 0000000000000..e8511d443045c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.SByte.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.UInt16.cs new file mode 100644 index 0000000000000..0663f9fddee97 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.UInt16.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.UInt32.cs new file mode 100644 index 0000000000000..12b7c1f1b565a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalRoundedSaturateScalar.Vector64.UInt32.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Byte.cs new file mode 100644 index 0000000000000..cfa1bcea9697a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Byte.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Int16.cs new file mode 100644 index 0000000000000..db01153ab4159 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Int16.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Int32.cs new file mode 100644 index 0000000000000..6ffcf55329a5d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.Int32.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.SByte.cs new file mode 100644 index 0000000000000..2e618dfaec8d4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.SByte.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.UInt16.cs new file mode 100644 index 0000000000000..d0a505b457d59 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.UInt16.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.UInt32.cs new file mode 100644 index 0000000000000..1c64baf6e8d1e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftLogicalSaturateScalar.Vector64.UInt32.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32 testClass) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int16.16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int16.16.cs new file mode 100644 index 0000000000000..5eb798d368167 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int16.16.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(_fld, 16); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 16 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 16; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)16 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)16 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + _clsVar, + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(firstOp, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(firstOp, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(test._fld, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(_fld, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(test._fld, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar)}(Vector64, 16): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int32.32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int32.32.cs new file mode 100644 index 0000000000000..5d8f85004073a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.Int32.32.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(_fld, 32); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 32 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 32; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)32 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)32 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + _clsVar, + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(firstOp, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(firstOp, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(test._fld, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(_fld, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(test._fld, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar)}(Vector64, 32): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.SByte.8.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.SByte.8.cs new file mode 100644 index 0000000000000..daab20f1b12de --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateScalar.Vector64.SByte.8.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(_fld, 8); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 8 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 8; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + _clsVar, + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(_fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateScalar)}(Vector64, 8): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.Byte.3.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.Byte.3.cs new file mode 100644 index 0000000000000..9f5359e268095 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.Byte.3.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(_fld, 3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 3 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 3; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + _clsVar, + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(_fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar)}(Vector64, 3): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt16.5.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt16.5.cs new file mode 100644 index 0000000000000..434cea9dcaf7c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt16.5.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(_fld, 5); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 5 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 5; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + _clsVar, + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(_fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar)}(Vector64, 5): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt32.7.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt32.7.cs new file mode 100644 index 0000000000000..86c7c041a9525 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticNarrowingSaturateUnsignedScalar.Vector64.UInt32.7.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 7; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticNarrowingSaturateUnsignedScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int16.32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int16.32.cs new file mode 100644 index 0000000000000..98b04fbbce92a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int16.32.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(_fld, 16); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 16 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 16; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)16 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)16 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + _clsVar, + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(firstOp, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(firstOp, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(test._fld, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(_fld, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(test._fld, 16); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 16 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar)}(Vector64, 16): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int32.64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int32.64.cs new file mode 100644 index 0000000000000..bf7f10cda4efb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.Int32.64.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(_fld, 32); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 32 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 32; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)32 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)32 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + _clsVar, + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(firstOp, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(firstOp, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(test._fld, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(_fld, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(test._fld, 32); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 32 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar)}(Vector64, 32): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.SByte.16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.SByte.16.cs new file mode 100644 index 0000000000000..837dda2f3dad6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateScalar.Vector64.SByte.16.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(_fld, 8); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 8 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 8; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + _clsVar, + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(_fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateScalar)}(Vector64, 8): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..2a46e7220c734 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.Byte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 7; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..20d8e9468a086 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(_fld, 15); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 15 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 15; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + _clsVar, + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(_fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar)}(Vector64, 15): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..a8d369928b0b3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar.Vector64.UInt32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(_fld, 31); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 31 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 31; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + _clsVar, + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(_fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar)}(Vector64, 31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Byte.5.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Byte.5.cs new file mode 100644 index 0000000000000..d93c5c41e333c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Byte.5.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 7; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int16.7.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int16.7.cs new file mode 100644 index 0000000000000..bbed7640cf233 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int16.7.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 15); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 15 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 15; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + _clsVar, + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar)}(Vector64, 15): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int32.11.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int32.11.cs new file mode 100644 index 0000000000000..f723d24d6e8a6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.Int32.11.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 31); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 31 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 31; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + _clsVar, + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar)}(Vector64, 31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.SByte.3.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.SByte.3.cs new file mode 100644 index 0000000000000..26b8eef08c981 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.SByte.3.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 7; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt16.5.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt16.5.cs new file mode 100644 index 0000000000000..e0f63f4958e09 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt16.5.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 15); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 15 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 15; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)15 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + _clsVar, + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 15); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 15 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar)}(Vector64, 15): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt32.7.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt32.7.cs new file mode 100644 index 0000000000000..7aad4513eee3b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalNarrowingSaturateScalar.Vector64.UInt32.7.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 31); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 31 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 31; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + (byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + _clsVar, + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(firstOp, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(_fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar(test._fld, 31); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld)), + 31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalNarrowingSaturateScalar)}(Vector64, 31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..d20fc959a862e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Byte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 3 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 3; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + _clsVar, + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar)}(Vector64, 3): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..3d6e9e01ea4a9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 5); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 5 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 5; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + _clsVar, + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar)}(Vector64, 5): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..c888b3177953c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.Int32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 7; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..d2b9d58955666 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.SByte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 3 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 3; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)3 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + _clsVar, + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(pFld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 3 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar)}(Vector64, 3): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..ed3f2d6b72439 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 5); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 5 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 5; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)5 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + _clsVar, + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 5); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 5 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar)}(Vector64, 5): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..6c650928ce485 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd.Arm64/ShiftRightLogicalRoundedNarrowingSaturateScalar.Vector64.UInt32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 7 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 7; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.Arm64.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + (byte)7 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + _clsVar, + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(firstOp, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(_fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar(test._fld, 7); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld)), + 7 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.ShiftRightLogicalRoundedNarrowingSaturateScalar)}(Vector64, 7): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Byte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Byte.cs index 2e8bf9f87d7ec..5468c6e2326db 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowLower_Vector64_Byte() + private static void AddHighNarrowingLower_Vector64_Byte() { - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowLower_Vector64_Byte() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte + public sealed unsafe class SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte testClass) { - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrow private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte() + static SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte() + public SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte(); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Byte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Int16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Int16.cs index 491b2bb6b8c6d..aef7a1a9f85ee 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowLower_Vector64_Int16() + private static void AddHighNarrowingLower_Vector64_Int16() { - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowLower_Vector64_Int16() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16 + public sealed unsafe class SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16 testClass) { - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrow private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16() + static SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16() + public SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16(); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Int32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Int32.cs index af0e0e56953ac..c8bed51ae70bb 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowLower_Vector64_Int32() + private static void AddHighNarrowingLower_Vector64_Int32() { - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowLower_Vector64_Int32() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32 + public sealed unsafe class SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32 testClass) { - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrow private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32() + static SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32() + public SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32(); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_Int32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.SByte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.SByte.cs index b0774c25a3f8e..024712d6f9545 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowLower_Vector64_SByte() + private static void AddHighNarrowingLower_Vector64_SByte() { - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowLower_Vector64_SByte() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte + public sealed unsafe class SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte testClass) { - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrow private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte() + static SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte() + public SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte(); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_SByte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.UInt16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.UInt16.cs index c6d49f3fdd5de..6d9318b1f6931 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowLower_Vector64_UInt16() + private static void AddHighNarrowingLower_Vector64_UInt16() { - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowLower_Vector64_UInt16() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16 + public sealed unsafe class SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16 testClass) { - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrow private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16() + static SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16() + public SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16(); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.UInt32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.UInt32.cs index b2171fbb91d30..bb587e95effa5 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowLower.Vector64.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingLower.Vector64.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowLower_Vector64_UInt32() + private static void AddHighNarrowingLower_Vector64_UInt32() { - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowLower_Vector64_UInt32() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32 + public sealed unsafe class SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32 testClass) { - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningHighNarrow private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32() + static SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32() + public SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32(); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__AddHighNarrowingLower_Vector64_UInt32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowLower( + var result = AdvSimd.AddHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Byte.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Byte.cs index 1415f01db140c..400ff583a4a95 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowUpper_Vector128_Byte() + private static void AddHighNarrowingUpper_Vector128_Byte() { - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowUpper_Vector128_Byte() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte + public sealed unsafe class SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte testClass) { - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarro private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte() + static SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte() + public SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)), AdvSimd.LoadVector128((UInt16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte(); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Byte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)), AdvSimd.LoadVector128((UInt16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Int16.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Int16.cs index dadff1b0f9c60..1ed95b9057f43 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowUpper_Vector128_Int16() + private static void AddHighNarrowingUpper_Vector128_Int16() { - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowUpper_Vector128_Int16() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16 + public sealed unsafe class SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16 testClass) { - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarro private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16() + static SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16() + public SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)), AdvSimd.LoadVector128((Int32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16(); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)), AdvSimd.LoadVector128((Int32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Int32.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Int32.cs index 20f1ac3dd78b0..ba16eab980ede 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowUpper_Vector128_Int32() + private static void AddHighNarrowingUpper_Vector128_Int32() { - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowUpper_Vector128_Int32() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32 + public sealed unsafe class SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32 testClass) { - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarro private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32() + static SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32() + public SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)), AdvSimd.LoadVector128((Int64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32(); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_Int32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)), AdvSimd.LoadVector128((Int64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.SByte.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.SByte.cs index c4c9e278bfe8e..93fcc6036ab16 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowUpper_Vector128_SByte() + private static void AddHighNarrowingUpper_Vector128_SByte() { - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowUpper_Vector128_SByte() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte + public sealed unsafe class SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte testClass) { - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarro private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte() + static SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte() + public SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)), AdvSimd.LoadVector128((Int16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte(); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_SByte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)), AdvSimd.LoadVector128((Int16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.UInt16.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.UInt16.cs index 54bf48bb0e2b5..2ab6d94fdcb95 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowUpper_Vector128_UInt16() + private static void AddHighNarrowingUpper_Vector128_UInt16() { - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowUpper_Vector128_UInt16() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16 + public sealed unsafe class SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16 testClass) { - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarro private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16() + static SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16() + public SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)), AdvSimd.LoadVector128((UInt32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16(); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)), AdvSimd.LoadVector128((UInt32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.UInt32.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.UInt32.cs index 602ac9643592e..c09986aa72125 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningHighNarrowUpper.Vector128.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddHighNarrowingUpper.Vector128.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningHighNarrowUpper_Vector128_UInt32() + private static void AddHighNarrowingUpper_Vector128_UInt32() { - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningHighNarrowUpper_Vector128_UInt32() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32 + public sealed unsafe class SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32 testClass) { - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningHighNarro private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32() + static SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32() + public SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)), AdvSimd.LoadVector128((UInt64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32(); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__AddHighNarrowingUpper_Vector128_UInt32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningHighNarrowUpper( + var result = AdvSimd.AddHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)), AdvSimd.LoadVector128((UInt64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Byte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Byte.cs index dd37156add5ab..1724511cd47f6 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowLower_Vector64_Byte() + private static void AddRoundedHighNarrowingLower_Vector64_Byte() { - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowLower_Vector64_Byte() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte + public sealed unsafe class SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte testClass) { - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighN private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte() + static SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte() + public SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte(); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Byte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Int16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Int16.cs index c5e972fa4694b..21fc2ac668e35 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowLower_Vector64_Int16() + private static void AddRoundedHighNarrowingLower_Vector64_Int16() { - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowLower_Vector64_Int16() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16 + public sealed unsafe class SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighN private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16() + static SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16() + public SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16(); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Int32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Int32.cs index 3595251d62901..8812d14278392 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowLower_Vector64_Int32() + private static void AddRoundedHighNarrowingLower_Vector64_Int32() { - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowLower_Vector64_Int32() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32 + public sealed unsafe class SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighN private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32() + static SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32() + public SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32(); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_Int32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.SByte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.SByte.cs index f0a908558b14a..0d3355f2bb446 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowLower_Vector64_SByte() + private static void AddRoundedHighNarrowingLower_Vector64_SByte() { - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowLower_Vector64_SByte() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte + public sealed unsafe class SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte testClass) { - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighN private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte() + static SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte() + public SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte(); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_SByte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.UInt16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.UInt16.cs index eca511d7675be..09a517e548465 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowLower_Vector64_UInt16() + private static void AddRoundedHighNarrowingLower_Vector64_UInt16() { - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowLower_Vector64_UInt16() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16 + public sealed unsafe class SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighN private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16() + static SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16() + public SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16(); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.UInt32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.UInt32.cs index 84e08fc67ec36..bd51ff2b4af55 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowLower.Vector64.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingLower.Vector64.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowLower_Vector64_UInt32() + private static void AddRoundedHighNarrowingLower_Vector64_UInt32() { - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowLower_Vector64_UInt32() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32 + public sealed unsafe class SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningHighN private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32() + static SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32() + public SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowLower(op1, op2); + var result = AdvSimd.AddRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32(); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__AddRoundedHighNarrowingLower_Vector64_UInt32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.AddRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowLower( + var result = AdvSimd.AddRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Byte.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Byte.cs index 062f43f5629bb..f62db16fae2ed 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowUpper_Vector128_Byte() + private static void AddRoundedHighNarrowingUpper_Vector128_Byte() { - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowUpper_Vector128_Byte() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte + public sealed unsafe class SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte testClass) { - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHigh private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte() + static SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte() + public SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)), AdvSimd.LoadVector128((UInt16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte(); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Byte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)), AdvSimd.LoadVector128((UInt16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Int16.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Int16.cs index 0edd0a17b47e8..b2e8e80e0de3d 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowUpper_Vector128_Int16() + private static void AddRoundedHighNarrowingUpper_Vector128_Int16() { - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowUpper_Vector128_Int16() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16 + public sealed unsafe class SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHigh private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16() + static SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16() + public SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)), AdvSimd.LoadVector128((Int32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16(); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)), AdvSimd.LoadVector128((Int32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Int32.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Int32.cs index 3d342d4bfb5b4..f73507f28f3ea 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowUpper_Vector128_Int32() + private static void AddRoundedHighNarrowingUpper_Vector128_Int32() { - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowUpper_Vector128_Int32() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32 + public sealed unsafe class SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHigh private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32() + static SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32() + public SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)), AdvSimd.LoadVector128((Int64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32(); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_Int32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)), AdvSimd.LoadVector128((Int64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.SByte.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.SByte.cs index 5cbea75ba11c5..b12db4a90614b 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowUpper_Vector128_SByte() + private static void AddRoundedHighNarrowingUpper_Vector128_SByte() { - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowUpper_Vector128_SByte() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte + public sealed unsafe class SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte testClass) { - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHigh private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte() + static SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte() + public SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)), AdvSimd.LoadVector128((Int16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte(); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_SByte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)), AdvSimd.LoadVector128((Int16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.UInt16.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.UInt16.cs index 8d2aeb28ff964..0e96972f6db9c 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowUpper_Vector128_UInt16() + private static void AddRoundedHighNarrowingUpper_Vector128_UInt16() { - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowUpper_Vector128_UInt16() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16 + public sealed unsafe class SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHigh private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16() + static SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16() + public SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)), AdvSimd.LoadVector128((UInt32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16(); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)), AdvSimd.LoadVector128((UInt32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.UInt32.cs similarity index 91% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.UInt32.cs index 858e3db611b20..03f2f544b4323 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningHighNarrowUpper.Vector128.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddRoundedHighNarrowingUpper.Vector128.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningHighNarrowUpper_Vector128_UInt32() + private static void AddRoundedHighNarrowingUpper_Vector128_UInt32() { - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningHighNarrowUpper_Vector128_UInt32() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32 + public sealed unsafe class SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32 testClass) { - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningHigh private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32() + static SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32() + public SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)), AdvSimd.LoadVector128((UInt64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32(); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__AddRoundedHighNarrowingUpper_Vector128_UInt32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.AddRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningHighNarrowUpper( + var result = AdvSimd.AddRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)), AdvSimd.LoadVector128((UInt64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj index 1d218c9af69eb..7f2d981717c87 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_r.csproj @@ -92,6 +92,18 @@ + + + + + + + + + + + + @@ -123,30 +135,18 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + @@ -337,6 +337,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -354,18 +410,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + @@ -686,6 +742,10 @@ + + + + @@ -702,6 +762,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -740,30 +1121,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -832,6 +1213,18 @@ + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj index 67094c63b5267..a6abd34f4f1ea 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AdvSimd_ro.csproj @@ -92,6 +92,18 @@ + + + + + + + + + + + + @@ -123,30 +135,18 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + @@ -337,6 +337,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -354,18 +410,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + @@ -686,6 +742,10 @@ + + + + @@ -702,6 +762,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -740,30 +1121,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -832,6 +1213,18 @@ + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Byte.8.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Byte.8.cs new file mode 100644 index 0000000000000..cf9cd8e290ceb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Byte.8.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_Byte_8() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 8); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Byte*)(pFld)), + 8 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 8; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Byte_8(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Byte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Byte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[8]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[8]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 8): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Int16.4.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Int16.4.cs new file mode 100644 index 0000000000000..a1fa2b1b9b09e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Int16.4.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_Int16_4() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 4); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int16*)(pFld)), + 4 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 4; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int16_4(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[4]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[4]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 4): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Int32.2.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Int32.2.cs new file mode 100644 index 0000000000000..60a88d0d8dcd8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Int32.2.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_Int32_2() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int32*)(pFld)), + 2 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 2; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Int32_2(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[2]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[2]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 2): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.SByte.8.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.SByte.8.cs new file mode 100644 index 0000000000000..a57c8b9184bf3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.SByte.8.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_SByte_8() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 8); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((SByte*)(pFld)), + 8 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 8; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_SByte_8(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((SByte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((SByte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[8]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[8]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 8): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Single.2.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Single.2.cs new file mode 100644 index 0000000000000..e6378b48f8972 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.Single.2.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_Single_2() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Single*)(pFld)), + 2 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly byte Imm = 2; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Single*)(_dataTable.inArrayPtr)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Single*)(pClsVar)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Single*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_Single_2(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Single*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Single*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((Single*)(&test._fld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[2]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[2]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 2): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.UInt16.4.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.UInt16.4.cs new file mode 100644 index 0000000000000..e88f362ef45ba --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.UInt16.4.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_UInt16_4() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 4); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 4 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 4; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt16_4(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[4]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[4]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 4): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.UInt32.2.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.UInt32.2.cs new file mode 100644 index 0000000000000..b41fc8315838c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V128.UInt32.2.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V128_UInt32_2() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 2 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 2; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V128_UInt32_2(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[2]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[2]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector128, 2): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Byte.1.cs new file mode 100644 index 0000000000000..bf906543afbc0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Byte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_Byte_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Int16.1.cs new file mode 100644 index 0000000000000..0719e0b733efd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Int16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_Int16_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Int32.1.cs new file mode 100644 index 0000000000000..1ec386a4d2669 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Int32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_Int32_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.SByte.1.cs new file mode 100644 index 0000000000000..6f4e005cd56fb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.SByte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_SByte_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Single.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Single.1.cs new file mode 100644 index 0000000000000..f4868930b7b4e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.Single.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_Single_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Single*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly byte Imm = 1; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Single*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Single*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_Single_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Single*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Single*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((Single*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.UInt16.1.cs new file mode 100644 index 0000000000000..e961e091b660c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.UInt16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_UInt16_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.UInt32.1.cs new file mode 100644 index 0000000000000..b68310f9d6225 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector128.V64.UInt32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector128_V64_UInt32_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector128), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector128(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector128_V64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector128(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector128( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector128)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Byte.8.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Byte.8.cs new file mode 100644 index 0000000000000..fecce603592ff --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Byte.8.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_Byte_8() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 8); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Byte*)(pFld)), + 8 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 8; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Byte_8(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Byte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Byte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[8]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[8]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 8): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Int16.4.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Int16.4.cs new file mode 100644 index 0000000000000..3215c5acbba28 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Int16.4.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_Int16_4() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 4); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int16*)(pFld)), + 4 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 4; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int16_4(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[4]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[4]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 4): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Int32.2.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Int32.2.cs new file mode 100644 index 0000000000000..07b58d8aee742 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Int32.2.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_Int32_2() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int32*)(pFld)), + 2 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 2; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Int32_2(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[2]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[2]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 2): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.SByte.8.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.SByte.8.cs new file mode 100644 index 0000000000000..0e795bdf5716e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.SByte.8.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_SByte_8() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 8); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((SByte*)(pFld)), + 8 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 8; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)8 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_SByte_8(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((SByte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((SByte*)(pFld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 8); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 8 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[8]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[8]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 8): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Single.2.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Single.2.cs new file mode 100644 index 0000000000000..aab9d496e1439 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.Single.2.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_Single_2() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Single*)(pFld)), + 2 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly byte Imm = 2; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Single*)(_dataTable.inArrayPtr)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Single*)(_dataTable.inArrayPtr)), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Single*)(pClsVar)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Single*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_Single_2(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Single*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Single*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((Single*)(&test._fld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[2]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[2]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 2): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.UInt16.4.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.UInt16.4.cs new file mode 100644 index 0000000000000..afa70cf115708 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.UInt16.4.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_UInt16_4() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 4); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 4 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 4; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)4 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt16_4(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 4); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 4 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[4]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[4]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 4): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.UInt32.2.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.UInt32.2.cs new file mode 100644 index 0000000000000..c6c51495eb00f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V128.UInt32.2.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V128_UInt32_2() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 2 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 2; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)2 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V128_UInt32_2(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[2]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[2]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector128, 2): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Byte.1.cs new file mode 100644 index 0000000000000..e3cfeffb5da8a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Byte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_Byte_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Int16.1.cs new file mode 100644 index 0000000000000..3d41d9be238ef --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Int16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_Int16_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Int32.1.cs new file mode 100644 index 0000000000000..711584eb3964e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Int32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_Int32_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.SByte.1.cs new file mode 100644 index 0000000000000..7d8c97b4f785b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.SByte.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_SByte_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Single.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Single.1.cs new file mode 100644 index 0000000000000..4afa6ce2cddf6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.Single.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_Single_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] inArray, Single[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Single*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + private static readonly byte Imm = 1; + + private static Single[] _data = new Single[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSingle(); } + _dataTable = new DataTable(_data, new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Single*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Single*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Single*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Single*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_Single_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Single*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Single*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((Single*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Single[] inArray = new Single[Op1ElementCount]; + Single[] outArray = new Single[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.UInt16.1.cs new file mode 100644 index 0000000000000..3323e524af933 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.UInt16.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_UInt16_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.UInt32.1.cs new file mode 100644 index 0000000000000..cbbca5b59655d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateSelectedScalarToVector64.V64.UInt32.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateSelectedScalarToVector64_V64_UInt32_1() + { + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1 testClass) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateSelectedScalarToVector64), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.DuplicateSelectedScalarToVector64(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__DuplicateSelectedScalarToVector64_V64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateSelectedScalarToVector64(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateSelectedScalarToVector64( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != firstOp[1]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != firstOp[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateSelectedScalarToVector64)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Byte.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Byte.31.cs new file mode 100644 index 0000000000000..aa12893fa2fb7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Byte.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Byte_31() + { + var test = new ImmOpTest__DuplicateToVector128_Byte_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_Byte_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_Byte_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (Byte)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Byte) }) + .Invoke(null, new object[] { + (Byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Byte[] outArray = new Byte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Byte.cs new file mode 100644 index 0000000000000..5c60e82afd1e2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Byte.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Byte() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_Byte + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Byte _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetByte(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_Byte testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte _data; + + private static Byte _clsVar; + + private Byte _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_Byte() + { + _clsVar = TestLibrary.Generator.GetByte(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_Byte() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetByte(); + _data = TestLibrary.Generator.GetByte(); + + _dataTable = new DataTable(new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Byte(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Byte data, void* result, [CallerMemberName] string method = "") + { + Byte[] outArray = new Byte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Byte data, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(Byte): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int16.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int16.31.cs new file mode 100644 index 0000000000000..7173c618131ea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int16.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Int16_31() + { + var test = new ImmOpTest__DuplicateToVector128_Int16_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_Int16_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_Int16_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (Int16)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Int16) }) + .Invoke(null, new object[] { + (Int16)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Int16[] outArray = new Int16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int16.cs new file mode 100644 index 0000000000000..510d61858ff05 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int16.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Int16() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_Int16 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Int16 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetInt16(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_Int16 testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16 _data; + + private static Int16 _clsVar; + + private Int16 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_Int16() + { + _clsVar = TestLibrary.Generator.GetInt16(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_Int16() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetInt16(); + _data = TestLibrary.Generator.GetInt16(); + + _dataTable = new DataTable(new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Int16) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Int16(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Int16 data, void* result, [CallerMemberName] string method = "") + { + Int16[] outArray = new Int16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Int16 data, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(Int16): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int32.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int32.31.cs new file mode 100644 index 0000000000000..b12495ff11aed --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int32.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Int32_31() + { + var test = new ImmOpTest__DuplicateToVector128_Int32_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_Int32_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_Int32_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (Int32)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Int32) }) + .Invoke(null, new object[] { + (Int32)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Int32[] outArray = new Int32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int32.cs new file mode 100644 index 0000000000000..77967e2777f32 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Int32.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Int32() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_Int32 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Int32 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetInt32(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_Int32 testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32 _data; + + private static Int32 _clsVar; + + private Int32 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_Int32() + { + _clsVar = TestLibrary.Generator.GetInt32(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_Int32() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetInt32(); + _data = TestLibrary.Generator.GetInt32(); + + _dataTable = new DataTable(new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Int32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Int32(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Int32 data, void* result, [CallerMemberName] string method = "") + { + Int32[] outArray = new Int32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Int32 data, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(Int32): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.SByte.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.SByte.31.cs new file mode 100644 index 0000000000000..824cd8968dd8c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.SByte.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_SByte_31() + { + var test = new ImmOpTest__DuplicateToVector128_SByte_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_SByte_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_SByte_31() + { + Succeeded = true; + + _dataTable = new DataTable(new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (SByte)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(SByte) }) + .Invoke(null, new object[] { + (SByte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + SByte[] outArray = new SByte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.SByte.cs new file mode 100644 index 0000000000000..183ad0bc2041c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.SByte.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_SByte() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_SByte + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public SByte _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetSByte(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_SByte testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte _data; + + private static SByte _clsVar; + + private SByte _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_SByte() + { + _clsVar = TestLibrary.Generator.GetSByte(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_SByte() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetSByte(); + _data = TestLibrary.Generator.GetSByte(); + + _dataTable = new DataTable(new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(SByte) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_SByte(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(SByte data, void* result, [CallerMemberName] string method = "") + { + SByte[] outArray = new SByte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(SByte data, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(SByte): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Single.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Single.31.cs new file mode 100644 index 0000000000000..9685545397d5d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Single.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Single_31() + { + var test = new ImmOpTest__DuplicateToVector128_Single_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_Single_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_Single_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (Single)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Single) }) + .Invoke(null, new object[] { + (Single)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Single[] outArray = new Single[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Single.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Single.cs new file mode 100644 index 0000000000000..caad761f6f97d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.Single.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_Single() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_Single + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Single _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetSingle(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_Single testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Single _data; + + private static Single _clsVar; + + private Single _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_Single() + { + _clsVar = TestLibrary.Generator.GetSingle(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_Single() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetSingle(); + _data = TestLibrary.Generator.GetSingle(); + + _dataTable = new DataTable(new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(Single) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_Single(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Single data, void* result, [CallerMemberName] string method = "") + { + Single[] outArray = new Single[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Single data, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(Single): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt16.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt16.31.cs new file mode 100644 index 0000000000000..2bfa725584af9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt16.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_UInt16_31() + { + var test = new ImmOpTest__DuplicateToVector128_UInt16_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_UInt16_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_UInt16_31() + { + Succeeded = true; + + _dataTable = new DataTable(new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (UInt16)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(UInt16) }) + .Invoke(null, new object[] { + (UInt16)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + UInt16[] outArray = new UInt16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt16.cs new file mode 100644 index 0000000000000..5f4e3097fc90a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt16.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_UInt16() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_UInt16 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public UInt16 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetUInt16(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_UInt16 testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16 _data; + + private static UInt16 _clsVar; + + private UInt16 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_UInt16() + { + _clsVar = TestLibrary.Generator.GetUInt16(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_UInt16() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetUInt16(); + _data = TestLibrary.Generator.GetUInt16(); + + _dataTable = new DataTable(new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_UInt16(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt16 data, void* result, [CallerMemberName] string method = "") + { + UInt16[] outArray = new UInt16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(UInt16 data, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(UInt16): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt32.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt32.31.cs new file mode 100644 index 0000000000000..c3ade1c04fd54 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt32.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_UInt32_31() + { + var test = new ImmOpTest__DuplicateToVector128_UInt32_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector128_UInt32_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector128_UInt32_31() + { + Succeeded = true; + + _dataTable = new DataTable(new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector128( + (UInt32)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(UInt32) }) + .Invoke(null, new object[] { + (UInt32)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + UInt32[] outArray = new UInt32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt32.cs new file mode 100644 index 0000000000000..2d58f8f2e3fcb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector128.UInt32.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector128_UInt32() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector128_UInt32 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public UInt32 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetUInt32(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector128_UInt32 testClass) + { + var result = AdvSimd.DuplicateToVector128(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32 _data; + + private static UInt32 _clsVar; + + private UInt32 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector128_UInt32() + { + _clsVar = TestLibrary.Generator.GetUInt32(); + } + + public DuplicateUnaryOpTest__DuplicateToVector128_UInt32() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetUInt32(); + _data = TestLibrary.Generator.GetUInt32(); + + _dataTable = new DataTable(new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector128( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector128), new Type[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector128( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector128(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector128_UInt32(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector128(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector128(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 data, void* result, [CallerMemberName] string method = "") + { + UInt32[] outArray = new UInt32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(UInt32 data, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector128)}(UInt32): DuplicateToVector128 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Byte.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Byte.31.cs new file mode 100644 index 0000000000000..44c3abb84eb06 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Byte.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Byte_31() + { + var test = new ImmOpTest__DuplicateToVector64_Byte_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_Byte_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_Byte_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (Byte)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Byte) }) + .Invoke(null, new object[] { + (Byte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Byte[] outArray = new Byte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Byte.cs new file mode 100644 index 0000000000000..c519918584cce --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Byte.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Byte() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_Byte + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Byte _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetByte(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_Byte testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte _data; + + private static Byte _clsVar; + + private Byte _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_Byte() + { + _clsVar = TestLibrary.Generator.GetByte(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_Byte() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetByte(); + _data = TestLibrary.Generator.GetByte(); + + _dataTable = new DataTable(new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Byte) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Byte(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Byte data, void* result, [CallerMemberName] string method = "") + { + Byte[] outArray = new Byte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Byte data, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(Byte): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int16.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int16.31.cs new file mode 100644 index 0000000000000..7a84cc8afac97 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int16.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Int16_31() + { + var test = new ImmOpTest__DuplicateToVector64_Int16_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_Int16_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_Int16_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (Int16)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Int16) }) + .Invoke(null, new object[] { + (Int16)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Int16[] outArray = new Int16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int16.cs new file mode 100644 index 0000000000000..c5e95a8ee07f1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int16.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Int16() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_Int16 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Int16 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetInt16(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_Int16 testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16 _data; + + private static Int16 _clsVar; + + private Int16 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_Int16() + { + _clsVar = TestLibrary.Generator.GetInt16(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_Int16() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetInt16(); + _data = TestLibrary.Generator.GetInt16(); + + _dataTable = new DataTable(new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Int16) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Int16(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Int16 data, void* result, [CallerMemberName] string method = "") + { + Int16[] outArray = new Int16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Int16 data, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(Int16): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int32.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int32.31.cs new file mode 100644 index 0000000000000..beb6d1b62ac6b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int32.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Int32_31() + { + var test = new ImmOpTest__DuplicateToVector64_Int32_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_Int32_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_Int32_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (Int32)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Int32) }) + .Invoke(null, new object[] { + (Int32)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Int32[] outArray = new Int32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int32.cs new file mode 100644 index 0000000000000..4045059208899 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Int32.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Int32() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_Int32 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Int32 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetInt32(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_Int32 testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32 _data; + + private static Int32 _clsVar; + + private Int32 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_Int32() + { + _clsVar = TestLibrary.Generator.GetInt32(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_Int32() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetInt32(); + _data = TestLibrary.Generator.GetInt32(); + + _dataTable = new DataTable(new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Int32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Int32(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Int32 data, void* result, [CallerMemberName] string method = "") + { + Int32[] outArray = new Int32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Int32 data, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(Int32): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.SByte.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.SByte.31.cs new file mode 100644 index 0000000000000..1d0a5e7dcac31 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.SByte.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_SByte_31() + { + var test = new ImmOpTest__DuplicateToVector64_SByte_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_SByte_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_SByte_31() + { + Succeeded = true; + + _dataTable = new DataTable(new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (SByte)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(SByte) }) + .Invoke(null, new object[] { + (SByte)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + SByte[] outArray = new SByte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.SByte.cs new file mode 100644 index 0000000000000..98f2458c5a9cd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.SByte.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_SByte() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_SByte + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public SByte _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetSByte(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_SByte testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte _data; + + private static SByte _clsVar; + + private SByte _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_SByte() + { + _clsVar = TestLibrary.Generator.GetSByte(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_SByte() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetSByte(); + _data = TestLibrary.Generator.GetSByte(); + + _dataTable = new DataTable(new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(SByte) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_SByte(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(SByte data, void* result, [CallerMemberName] string method = "") + { + SByte[] outArray = new SByte[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(SByte data, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(SByte): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Single.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Single.31.cs new file mode 100644 index 0000000000000..cbfbf0c11ee5a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Single.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Single_31() + { + var test = new ImmOpTest__DuplicateToVector64_Single_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_Single_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_Single_31() + { + Succeeded = true; + + _dataTable = new DataTable(new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (Single)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Single) }) + .Invoke(null, new object[] { + (Single)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + Single[] outArray = new Single[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Single.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Single.cs new file mode 100644 index 0000000000000..44bd66c494854 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.Single.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_Single() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Single(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_Single + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Single[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Single _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetSingle(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_Single testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Single); + + private static Single _data; + + private static Single _clsVar; + + private Single _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_Single() + { + _clsVar = TestLibrary.Generator.GetSingle(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_Single() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetSingle(); + _data = TestLibrary.Generator.GetSingle(); + + _dataTable = new DataTable(new Single[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(Single) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_Single(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Single data, void* result, [CallerMemberName] string method = "") + { + Single[] outArray = new Single[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(Single data, Single[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(Single): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt16.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt16.31.cs new file mode 100644 index 0000000000000..cf0b6de370ba5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt16.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_UInt16_31() + { + var test = new ImmOpTest__DuplicateToVector64_UInt16_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_UInt16_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_UInt16_31() + { + Succeeded = true; + + _dataTable = new DataTable(new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (UInt16)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(UInt16) }) + .Invoke(null, new object[] { + (UInt16)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + UInt16[] outArray = new UInt16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt16.cs new file mode 100644 index 0000000000000..e533f462f7466 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt16.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_UInt16() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_UInt16 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public UInt16 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetUInt16(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_UInt16 testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16 _data; + + private static UInt16 _clsVar; + + private UInt16 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_UInt16() + { + _clsVar = TestLibrary.Generator.GetUInt16(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_UInt16() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetUInt16(); + _data = TestLibrary.Generator.GetUInt16(); + + _dataTable = new DataTable(new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(UInt16) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_UInt16(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt16 data, void* result, [CallerMemberName] string method = "") + { + UInt16[] outArray = new UInt16[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(UInt16 data, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(UInt16): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt32.31.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt32.31.cs new file mode 100644 index 0000000000000..5e4d079535d7a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt32.31.cs @@ -0,0 +1,185 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_UInt32_31() + { + var test = new ImmOpTest__DuplicateToVector64_UInt32_31(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmOpTest__DuplicateToVector64_UInt32_31 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private DataTable _dataTable; + + public ImmOpTest__DuplicateToVector64_UInt32_31() + { + Succeeded = true; + + _dataTable = new DataTable(new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = AdvSimd.DuplicateToVector64( + (UInt32)31 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(UInt32) }) + .Invoke(null, new object[] { + (UInt32)31 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + UInt32[] outArray = new UInt32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(outArray, method); + } + + private void ValidateResult(UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != 31) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 31) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(31): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt32.cs new file mode 100644 index 0000000000000..402384cf4b01c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/DuplicateToVector64.UInt32.cs @@ -0,0 +1,300 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void DuplicateToVector64_UInt32() + { + var test = new DuplicateUnaryOpTest__DuplicateToVector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class DuplicateUnaryOpTest__DuplicateToVector64_UInt32 + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public UInt32 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = TestLibrary.Generator.GetUInt32(); + return testStruct; + } + + public void RunStructFldScenario(DuplicateUnaryOpTest__DuplicateToVector64_UInt32 testClass) + { + var result = AdvSimd.DuplicateToVector64(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32 _data; + + private static UInt32 _clsVar; + + private UInt32 _fld; + + private DataTable _dataTable; + + static DuplicateUnaryOpTest__DuplicateToVector64_UInt32() + { + _clsVar = TestLibrary.Generator.GetUInt32(); + } + + public DuplicateUnaryOpTest__DuplicateToVector64_UInt32() + { + Succeeded = true; + + _fld = TestLibrary.Generator.GetUInt32(); + _data = TestLibrary.Generator.GetUInt32(); + + _dataTable = new DataTable(new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.DuplicateToVector64( + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.DuplicateToVector64), new Type[] { typeof(UInt32) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.DuplicateToVector64( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned(ref Unsafe.As(ref _data)); + var result = AdvSimd.DuplicateToVector64(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new DuplicateUnaryOpTest__DuplicateToVector64_UInt32(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.DuplicateToVector64(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.DuplicateToVector64(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(UInt32 data, void* result, [CallerMemberName] string method = "") + { + UInt32[] outArray = new UInt32[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult(UInt32 data, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (result[0] != data) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != data) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DuplicateToVector64)}(UInt32): DuplicateToVector64 failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int16.cs index 86ebd70207fda..c6bc0bca5bec5 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowLow_Vector128_Int16() + private static void ExtractNarrowingLower_Vector128_Int16() { - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowLow_Vector128_Int16() } } - public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16 + public sealed unsafe class SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16 { private struct DataTable { @@ -171,19 +171,19 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16 testClass) + public void RunStructFldScenario(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16 testClass) { - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16 testClass) + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16 testClass) { fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)) ); @@ -206,13 +206,13 @@ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vec private DataTable _dataTable; - static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16() + static SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16() + public SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16() { Succeeded = true; @@ -231,7 +231,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr) ); @@ -243,7 +243,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) ); @@ -255,7 +255,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr) }); @@ -268,7 +268,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) }); @@ -281,7 +281,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( _clsVar1 ); @@ -295,7 +295,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int16*)(pClsVar1)) ); @@ -309,7 +309,7 @@ public void RunLclVarScenario_UnsafeRead() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -320,7 +320,7 @@ public void RunLclVarScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -330,8 +330,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16(); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -341,11 +341,11 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int16(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int16(); fixed (Vector128* pFld1 = &test._fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)) ); @@ -358,7 +358,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _dataTable.outArrayPtr); @@ -370,7 +370,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)) ); @@ -384,7 +384,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -395,7 +395,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int16*)(&test._fld1)) ); @@ -468,7 +468,7 @@ private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] for (var i = 0; i < RetElementCount; i++) { - if (((SByte)firstOp[i]) != result[i]) + if (Helpers.ExtractNarrowing(firstOp[i]) != result[i]) { succeeded = false; break; @@ -477,7 +477,7 @@ private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingLower)}(Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); TestLibrary.TestFramework.LogInformation(string.Empty); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int32.cs index b7184d0e1edfc..5f7391b3d1655 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowLow_Vector128_Int32() + private static void ExtractNarrowingLower_Vector128_Int32() { - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowLow_Vector128_Int32() } } - public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32 + public sealed unsafe class SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32 { private struct DataTable { @@ -171,19 +171,19 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32 testClass) + public void RunStructFldScenario(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32 testClass) { - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32 testClass) + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32 testClass) { fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)) ); @@ -206,13 +206,13 @@ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vec private DataTable _dataTable; - static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32() + static SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32() + public SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32() { Succeeded = true; @@ -231,7 +231,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr) ); @@ -243,7 +243,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) ); @@ -255,7 +255,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr) }); @@ -268,7 +268,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) }); @@ -281,7 +281,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( _clsVar1 ); @@ -295,7 +295,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int32*)(pClsVar1)) ); @@ -309,7 +309,7 @@ public void RunLclVarScenario_UnsafeRead() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -320,7 +320,7 @@ public void RunLclVarScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -330,8 +330,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32(); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -341,11 +341,11 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int32(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int32(); fixed (Vector128* pFld1 = &test._fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)) ); @@ -358,7 +358,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _dataTable.outArrayPtr); @@ -370,7 +370,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)) ); @@ -384,7 +384,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -395,7 +395,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int32*)(&test._fld1)) ); @@ -468,7 +468,7 @@ private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] for (var i = 0; i < RetElementCount; i++) { - if (((Int16)firstOp[i]) != result[i]) + if (Helpers.ExtractNarrowing(firstOp[i]) != result[i]) { succeeded = false; break; @@ -477,7 +477,7 @@ private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingLower)}(Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); TestLibrary.TestFramework.LogInformation(string.Empty); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int64.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int64.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int64.cs index 3e74619f8c4a2..b409826445084 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.Int64.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.Int64.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowLow_Vector128_Int64() + private static void ExtractNarrowingLower_Vector128_Int64() { - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowLow_Vector128_Int64() } } - public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64 + public sealed unsafe class SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64 { private struct DataTable { @@ -171,19 +171,19 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64 testClass) + public void RunStructFldScenario(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64 testClass) { - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64 testClass) + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64 testClass) { fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)) ); @@ -206,13 +206,13 @@ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vec private DataTable _dataTable; - static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64() + static SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64() + public SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64() { Succeeded = true; @@ -231,7 +231,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr) ); @@ -243,7 +243,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)) ); @@ -255,7 +255,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr) }); @@ -268,7 +268,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)) }); @@ -281,7 +281,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( _clsVar1 ); @@ -295,7 +295,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int64*)(pClsVar1)) ); @@ -309,7 +309,7 @@ public void RunLclVarScenario_UnsafeRead() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -320,7 +320,7 @@ public void RunLclVarScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -330,8 +330,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64(); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -341,11 +341,11 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_Int64(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_Int64(); fixed (Vector128* pFld1 = &test._fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)) ); @@ -358,7 +358,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _dataTable.outArrayPtr); @@ -370,7 +370,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)) ); @@ -384,7 +384,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -395,7 +395,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((Int64*)(&test._fld1)) ); @@ -468,7 +468,7 @@ private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] for (var i = 0; i < RetElementCount; i++) { - if (((Int32)firstOp[i]) != result[i]) + if (Helpers.ExtractNarrowing(firstOp[i]) != result[i]) { succeeded = false; break; @@ -477,7 +477,7 @@ private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingLower)}(Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); TestLibrary.TestFramework.LogInformation(string.Empty); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt16.cs index b57d6294cbd88..5c739b97a9941 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowLow_Vector128_UInt16() + private static void ExtractNarrowingLower_Vector128_UInt16() { - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowLow_Vector128_UInt16() } } - public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16 + public sealed unsafe class SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16 { private struct DataTable { @@ -171,19 +171,19 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16 testClass) + public void RunStructFldScenario(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16 testClass) { - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16 testClass) { fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)) ); @@ -206,13 +206,13 @@ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vec private DataTable _dataTable; - static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16() + static SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16() + public SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16() { Succeeded = true; @@ -231,7 +231,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr) ); @@ -243,7 +243,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)) ); @@ -255,7 +255,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr) }); @@ -268,7 +268,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)) }); @@ -281,7 +281,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( _clsVar1 ); @@ -295,7 +295,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pClsVar1)) ); @@ -309,7 +309,7 @@ public void RunLclVarScenario_UnsafeRead() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -320,7 +320,7 @@ public void RunLclVarScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -330,8 +330,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16(); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -341,11 +341,11 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt16(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt16(); fixed (Vector128* pFld1 = &test._fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)) ); @@ -358,7 +358,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _dataTable.outArrayPtr); @@ -370,7 +370,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)) ); @@ -384,7 +384,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -395,7 +395,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt16*)(&test._fld1)) ); @@ -468,7 +468,7 @@ private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] for (var i = 0; i < RetElementCount; i++) { - if (((Byte)firstOp[i]) != result[i]) + if (Helpers.ExtractNarrowing(firstOp[i]) != result[i]) { succeeded = false; break; @@ -477,7 +477,7 @@ private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingLower)}(Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); TestLibrary.TestFramework.LogInformation(string.Empty); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt32.cs index a5cce409add8c..8630a333377e4 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowLow_Vector128_UInt32() + private static void ExtractNarrowingLower_Vector128_UInt32() { - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowLow_Vector128_UInt32() } } - public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32 + public sealed unsafe class SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32 { private struct DataTable { @@ -171,19 +171,19 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32 testClass) + public void RunStructFldScenario(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32 testClass) { - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32 testClass) { fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)) ); @@ -206,13 +206,13 @@ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vec private DataTable _dataTable; - static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32() + static SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32() + public SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32() { Succeeded = true; @@ -231,7 +231,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr) ); @@ -243,7 +243,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)) ); @@ -255,7 +255,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr) }); @@ -268,7 +268,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)) }); @@ -281,7 +281,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( _clsVar1 ); @@ -295,7 +295,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pClsVar1)) ); @@ -309,7 +309,7 @@ public void RunLclVarScenario_UnsafeRead() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -320,7 +320,7 @@ public void RunLclVarScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -330,8 +330,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32(); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -341,11 +341,11 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt32(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt32(); fixed (Vector128* pFld1 = &test._fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)) ); @@ -358,7 +358,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _dataTable.outArrayPtr); @@ -370,7 +370,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)) ); @@ -384,7 +384,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -395,7 +395,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt32*)(&test._fld1)) ); @@ -468,7 +468,7 @@ private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName for (var i = 0; i < RetElementCount; i++) { - if (((UInt16)firstOp[i]) != result[i]) + if (Helpers.ExtractNarrowing(firstOp[i]) != result[i]) { succeeded = false; break; @@ -477,7 +477,7 @@ private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingLower)}(Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); TestLibrary.TestFramework.LogInformation(string.Empty); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt64.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt64.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt64.cs index 8ff6d29b34c78..84abecc879988 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowLow.Vector128.UInt64.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingLower.Vector128.UInt64.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowLow_Vector128_UInt64() + private static void ExtractNarrowingLower_Vector128_UInt64() { - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowLow_Vector128_UInt64() } } - public sealed unsafe class SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64 + public sealed unsafe class SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64 { private struct DataTable { @@ -171,19 +171,19 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64 testClass) + public void RunStructFldScenario(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64 testClass) { - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64 testClass) + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64 testClass) { fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)) ); @@ -206,13 +206,13 @@ public void RunStructFldScenario_Load(SimpleUnaryOpTest__ExtractAndNarrowLow_Vec private DataTable _dataTable; - static SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64() + static SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); } - public SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64() + public SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64() { Succeeded = true; @@ -231,7 +231,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr) ); @@ -243,7 +243,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)) ); @@ -255,7 +255,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr) }); @@ -268,7 +268,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowLow), new Type[] { typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingLower), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)) }); @@ -281,7 +281,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( _clsVar1 ); @@ -295,7 +295,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pClsVar1)) ); @@ -309,7 +309,7 @@ public void RunLclVarScenario_UnsafeRead() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -320,7 +320,7 @@ public void RunLclVarScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); - var result = AdvSimd.ExtractAndNarrowLow(op1); + var result = AdvSimd.ExtractNarrowingLower(op1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, _dataTable.outArrayPtr); @@ -330,8 +330,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64(); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -341,11 +341,11 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleUnaryOpTest__ExtractAndNarrowLow_Vector128_UInt64(); + var test = new SimpleUnaryOpTest__ExtractNarrowingLower_Vector128_UInt64(); fixed (Vector128* pFld1 = &test._fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)) ); @@ -358,7 +358,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowLow(_fld1); + var result = AdvSimd.ExtractNarrowingLower(_fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _dataTable.outArrayPtr); @@ -370,7 +370,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) { - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)) ); @@ -384,7 +384,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow(test._fld1); + var result = AdvSimd.ExtractNarrowingLower(test._fld1); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, _dataTable.outArrayPtr); @@ -395,7 +395,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowLow( + var result = AdvSimd.ExtractNarrowingLower( AdvSimd.LoadVector128((UInt64*)(&test._fld1)) ); @@ -468,7 +468,7 @@ private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName for (var i = 0; i < RetElementCount; i++) { - if (((UInt32)firstOp[i]) != result[i]) + if (Helpers.ExtractNarrowing(firstOp[i]) != result[i]) { succeeded = false; break; @@ -477,7 +477,7 @@ private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowLow)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingLower)}(Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); TestLibrary.TestFramework.LogInformation(string.Empty); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int16.cs index 7443842e0e970..cc960def9015c 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowHigh_Vector128_Int16() + private static void ExtractNarrowingUpper_Vector128_Int16() { - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowHigh_Vector128_Int16() } } - public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16 + public sealed unsafe class SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16 testClass) { - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_V private DataTable _dataTable; - static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16() + static SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16() + public SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector64* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16(); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int16(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((SByte*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)) ); @@ -506,25 +506,18 @@ private void ValidateResult(SByte[] left, Int16[] right, SByte[] result, [Caller { bool succeeded = true; - if (Helpers.ExtractAndNarrowHigh(0, left, right, result)) + for (var i = 0; i < RetElementCount; i++) { - succeeded = false; - } - else - { - for (var i = 1; i < RetElementCount; i++) + if (Helpers.ExtractNarrowingUpper(left, right, i) != result[i]) { - if (Helpers.ExtractAndNarrowHigh(i, left, right, result)) - { - succeeded = false; - break; - } + succeeded = false; + break; } } if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}(Vector64, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingUpper)}(Vector64, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int32.cs index 87d362dd9f5d3..a2add3e285969 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowHigh_Vector128_Int32() + private static void ExtractNarrowingUpper_Vector128_Int32() { - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowHigh_Vector128_Int32() } } - public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32 + public sealed unsafe class SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32 testClass) { - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_V private DataTable _dataTable; - static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32() + static SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32() + public SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector64* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32(); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int32(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)) ); @@ -506,25 +506,18 @@ private void ValidateResult(Int16[] left, Int32[] right, Int16[] result, [Caller { bool succeeded = true; - if (Helpers.ExtractAndNarrowHigh(0, left, right, result)) + for (var i = 0; i < RetElementCount; i++) { - succeeded = false; - } - else - { - for (var i = 1; i < RetElementCount; i++) + if (Helpers.ExtractNarrowingUpper(left, right, i) != result[i]) { - if (Helpers.ExtractAndNarrowHigh(i, left, right, result)) - { - succeeded = false; - break; - } + succeeded = false; + break; } } if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}(Vector64, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingUpper)}(Vector64, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int64.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int64.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int64.cs index a8cf88a417fc4..b5316d0d700de 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.Int64.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.Int64.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowHigh_Vector128_Int64() + private static void ExtractNarrowingUpper_Vector128_Int64() { - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowHigh_Vector128_Int64() } } - public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64 + public sealed unsafe class SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64 testClass) { - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_V private DataTable _dataTable; - static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64() + static SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64() + public SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector64* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64(); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_Int64(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_Int64(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)) ); @@ -506,25 +506,18 @@ private void ValidateResult(Int32[] left, Int64[] right, Int32[] result, [Caller { bool succeeded = true; - if (Helpers.ExtractAndNarrowHigh(0, left, right, result)) + for (var i = 0; i < RetElementCount; i++) { - succeeded = false; - } - else - { - for (var i = 1; i < RetElementCount; i++) + if (Helpers.ExtractNarrowingUpper(left, right, i) != result[i]) { - if (Helpers.ExtractAndNarrowHigh(i, left, right, result)) - { - succeeded = false; - break; - } + succeeded = false; + break; } } if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}(Vector64, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingUpper)}(Vector64, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt16.cs index e8a9d0f6127b4..6d0facc3ea7be 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowHigh_Vector128_UInt16() + private static void ExtractNarrowingUpper_Vector128_UInt16() { - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowHigh_Vector128_UInt16() } } - public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16 + public sealed unsafe class SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16 testClass) { - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_V private DataTable _dataTable; - static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16() + static SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16() + public SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector64* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16(); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt16(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((Byte*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)) ); @@ -506,25 +506,18 @@ private void ValidateResult(Byte[] left, UInt16[] right, Byte[] result, [CallerM { bool succeeded = true; - if (Helpers.ExtractAndNarrowHigh(0, left, right, result)) + for (var i = 0; i < RetElementCount; i++) { - succeeded = false; - } - else - { - for (var i = 1; i < RetElementCount; i++) + if (Helpers.ExtractNarrowingUpper(left, right, i) != result[i]) { - if (Helpers.ExtractAndNarrowHigh(i, left, right, result)) - { - succeeded = false; - break; - } + succeeded = false; + break; } } if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}(Vector64, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingUpper)}(Vector64, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt32.cs index b82668cbb447e..85e46e6aaa8ab 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowHigh_Vector128_UInt32() + private static void ExtractNarrowingUpper_Vector128_UInt32() { - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowHigh_Vector128_UInt32() } } - public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32 + public sealed unsafe class SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32 testClass) { - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_V private DataTable _dataTable; - static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32() + static SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32() + public SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector64* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32(); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt32(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)) ); @@ -506,25 +506,18 @@ private void ValidateResult(UInt16[] left, UInt32[] right, UInt16[] result, [Cal { bool succeeded = true; - if (Helpers.ExtractAndNarrowHigh(0, left, right, result)) + for (var i = 0; i < RetElementCount; i++) { - succeeded = false; - } - else - { - for (var i = 1; i < RetElementCount; i++) + if (Helpers.ExtractNarrowingUpper(left, right, i) != result[i]) { - if (Helpers.ExtractAndNarrowHigh(i, left, right, result)) - { - succeeded = false; - break; - } + succeeded = false; + break; } } if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}(Vector64, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingUpper)}(Vector64, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt64.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt64.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt64.cs index 08834020a778f..e1606c139aa8b 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractAndNarrowHigh.Vector128.UInt64.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ExtractNarrowingUpper.Vector128.UInt64.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void ExtractAndNarrowHigh_Vector128_UInt64() + private static void ExtractNarrowingUpper_Vector128_UInt64() { - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void ExtractAndNarrowHigh_Vector128_UInt64() } } - public sealed unsafe class SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64 + public sealed unsafe class SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64 testClass) { - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__ExtractAndNarrowHigh_V private DataTable _dataTable; - static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64() + static SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64() + public SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractAndNarrowHigh), new Type[] { typeof(Vector64), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ExtractNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector64* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.ExtractAndNarrowHigh(op1, op2); + var result = AdvSimd.ExtractNarrowingUpper(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64(); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__ExtractAndNarrowHigh_Vector128_UInt64(); + var test = new SimpleBinaryOpTest__ExtractNarrowingUpper_Vector128_UInt64(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.ExtractAndNarrowHigh(_fld1, _fld2); + var result = AdvSimd.ExtractNarrowingUpper(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh(test._fld1, test._fld2); + var result = AdvSimd.ExtractNarrowingUpper(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.ExtractAndNarrowHigh( + var result = AdvSimd.ExtractNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)) ); @@ -506,25 +506,18 @@ private void ValidateResult(UInt32[] left, UInt64[] right, UInt32[] result, [Cal { bool succeeded = true; - if (Helpers.ExtractAndNarrowHigh(0, left, right, result)) + for (var i = 0; i < RetElementCount; i++) { - succeeded = false; - } - else - { - for (var i = 1; i < RetElementCount; i++) + if (Helpers.ExtractNarrowingUpper(left, right, i) != result[i]) { - if (Helpers.ExtractAndNarrowHigh(i, left, right, result)) - { - succeeded = false; - break; - } + succeeded = false; + break; } } if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractAndNarrowHigh)}(Vector64, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ExtractNarrowingUpper)}(Vector64, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningLower.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningLower.Vector64.Byte.cs new file mode 100644 index 0000000000000..729db2ea0559d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningLower.Vector64.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningLower_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte testClass) + { + var result = AdvSimd.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.PolynomialMultiplyWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningLower( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((Byte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte(); + var result = AdvSimd.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((Byte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((Byte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWidening(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.PolynomialMultiplyWideningLower)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningLower.Vector64.SByte.cs new file mode 100644 index 0000000000000..995f417e47501 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningLower.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningLower_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte testClass) + { + var result = AdvSimd.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.PolynomialMultiplyWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningLower( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte(); + var result = AdvSimd.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWidening(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.PolynomialMultiplyWideningLower)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningUpper.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningUpper.Vector128.Byte.cs new file mode 100644 index 0000000000000..dfd07f4ab3260 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningUpper.Vector128.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningUpper_Vector128_Byte() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte testClass) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((Byte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte(); + var result = AdvSimd.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((Byte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((Byte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, Byte[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWideningUpper(left, right, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.PolynomialMultiplyWideningUpper)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningUpper.Vector128.SByte.cs new file mode 100644 index 0000000000000..32780778dbdd0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/PolynomialMultiplyWideningUpper.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningUpper_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte testClass) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte(); + var result = AdvSimd.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWideningUpper(left, right, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.PolynomialMultiplyWideningUpper)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs index 47caf74ea0e22..636a26238b564 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/Program.AdvSimd.cs @@ -96,6 +96,18 @@ static Program() ["Add.Vector128.UInt16"] = Add_Vector128_UInt16, ["Add.Vector128.UInt32"] = Add_Vector128_UInt32, ["Add.Vector128.UInt64"] = Add_Vector128_UInt64, + ["AddHighNarrowingLower.Vector64.Byte"] = AddHighNarrowingLower_Vector64_Byte, + ["AddHighNarrowingLower.Vector64.Int16"] = AddHighNarrowingLower_Vector64_Int16, + ["AddHighNarrowingLower.Vector64.Int32"] = AddHighNarrowingLower_Vector64_Int32, + ["AddHighNarrowingLower.Vector64.SByte"] = AddHighNarrowingLower_Vector64_SByte, + ["AddHighNarrowingLower.Vector64.UInt16"] = AddHighNarrowingLower_Vector64_UInt16, + ["AddHighNarrowingLower.Vector64.UInt32"] = AddHighNarrowingLower_Vector64_UInt32, + ["AddHighNarrowingUpper.Vector128.Byte"] = AddHighNarrowingUpper_Vector128_Byte, + ["AddHighNarrowingUpper.Vector128.Int16"] = AddHighNarrowingUpper_Vector128_Int16, + ["AddHighNarrowingUpper.Vector128.Int32"] = AddHighNarrowingUpper_Vector128_Int32, + ["AddHighNarrowingUpper.Vector128.SByte"] = AddHighNarrowingUpper_Vector128_SByte, + ["AddHighNarrowingUpper.Vector128.UInt16"] = AddHighNarrowingUpper_Vector128_UInt16, + ["AddHighNarrowingUpper.Vector128.UInt32"] = AddHighNarrowingUpper_Vector128_UInt32, ["AddPairwise.Vector64.Byte"] = AddPairwise_Vector64_Byte, ["AddPairwise.Vector64.Int16"] = AddPairwise_Vector64_Int16, ["AddPairwise.Vector64.Int32"] = AddPairwise_Vector64_Int32, @@ -127,30 +139,18 @@ static Program() ["AddPairwiseWideningAndAddScalar.Vector64.UInt32"] = AddPairwiseWideningAndAddScalar_Vector64_UInt32, ["AddPairwiseWideningScalar.Vector64.Int32"] = AddPairwiseWideningScalar_Vector64_Int32, ["AddPairwiseWideningScalar.Vector64.UInt32"] = AddPairwiseWideningScalar_Vector64_UInt32, - ["AddReturningHighNarrowLower.Vector64.Byte"] = AddReturningHighNarrowLower_Vector64_Byte, - ["AddReturningHighNarrowLower.Vector64.Int16"] = AddReturningHighNarrowLower_Vector64_Int16, - ["AddReturningHighNarrowLower.Vector64.Int32"] = AddReturningHighNarrowLower_Vector64_Int32, - ["AddReturningHighNarrowLower.Vector64.SByte"] = AddReturningHighNarrowLower_Vector64_SByte, - ["AddReturningHighNarrowLower.Vector64.UInt16"] = AddReturningHighNarrowLower_Vector64_UInt16, - ["AddReturningHighNarrowLower.Vector64.UInt32"] = AddReturningHighNarrowLower_Vector64_UInt32, - ["AddReturningHighNarrowUpper.Vector128.Byte"] = AddReturningHighNarrowUpper_Vector128_Byte, - ["AddReturningHighNarrowUpper.Vector128.Int16"] = AddReturningHighNarrowUpper_Vector128_Int16, - ["AddReturningHighNarrowUpper.Vector128.Int32"] = AddReturningHighNarrowUpper_Vector128_Int32, - ["AddReturningHighNarrowUpper.Vector128.SByte"] = AddReturningHighNarrowUpper_Vector128_SByte, - ["AddReturningHighNarrowUpper.Vector128.UInt16"] = AddReturningHighNarrowUpper_Vector128_UInt16, - ["AddReturningHighNarrowUpper.Vector128.UInt32"] = AddReturningHighNarrowUpper_Vector128_UInt32, - ["AddReturningRoundedHighNarrowLower.Vector64.Byte"] = AddReturningRoundedHighNarrowLower_Vector64_Byte, - ["AddReturningRoundedHighNarrowLower.Vector64.Int16"] = AddReturningRoundedHighNarrowLower_Vector64_Int16, - ["AddReturningRoundedHighNarrowLower.Vector64.Int32"] = AddReturningRoundedHighNarrowLower_Vector64_Int32, - ["AddReturningRoundedHighNarrowLower.Vector64.SByte"] = AddReturningRoundedHighNarrowLower_Vector64_SByte, - ["AddReturningRoundedHighNarrowLower.Vector64.UInt16"] = AddReturningRoundedHighNarrowLower_Vector64_UInt16, - ["AddReturningRoundedHighNarrowLower.Vector64.UInt32"] = AddReturningRoundedHighNarrowLower_Vector64_UInt32, - ["AddReturningRoundedHighNarrowUpper.Vector128.Byte"] = AddReturningRoundedHighNarrowUpper_Vector128_Byte, - ["AddReturningRoundedHighNarrowUpper.Vector128.Int16"] = AddReturningRoundedHighNarrowUpper_Vector128_Int16, - ["AddReturningRoundedHighNarrowUpper.Vector128.Int32"] = AddReturningRoundedHighNarrowUpper_Vector128_Int32, - ["AddReturningRoundedHighNarrowUpper.Vector128.SByte"] = AddReturningRoundedHighNarrowUpper_Vector128_SByte, - ["AddReturningRoundedHighNarrowUpper.Vector128.UInt16"] = AddReturningRoundedHighNarrowUpper_Vector128_UInt16, - ["AddReturningRoundedHighNarrowUpper.Vector128.UInt32"] = AddReturningRoundedHighNarrowUpper_Vector128_UInt32, + ["AddRoundedHighNarrowingLower.Vector64.Byte"] = AddRoundedHighNarrowingLower_Vector64_Byte, + ["AddRoundedHighNarrowingLower.Vector64.Int16"] = AddRoundedHighNarrowingLower_Vector64_Int16, + ["AddRoundedHighNarrowingLower.Vector64.Int32"] = AddRoundedHighNarrowingLower_Vector64_Int32, + ["AddRoundedHighNarrowingLower.Vector64.SByte"] = AddRoundedHighNarrowingLower_Vector64_SByte, + ["AddRoundedHighNarrowingLower.Vector64.UInt16"] = AddRoundedHighNarrowingLower_Vector64_UInt16, + ["AddRoundedHighNarrowingLower.Vector64.UInt32"] = AddRoundedHighNarrowingLower_Vector64_UInt32, + ["AddRoundedHighNarrowingUpper.Vector128.Byte"] = AddRoundedHighNarrowingUpper_Vector128_Byte, + ["AddRoundedHighNarrowingUpper.Vector128.Int16"] = AddRoundedHighNarrowingUpper_Vector128_Int16, + ["AddRoundedHighNarrowingUpper.Vector128.Int32"] = AddRoundedHighNarrowingUpper_Vector128_Int32, + ["AddRoundedHighNarrowingUpper.Vector128.SByte"] = AddRoundedHighNarrowingUpper_Vector128_SByte, + ["AddRoundedHighNarrowingUpper.Vector128.UInt16"] = AddRoundedHighNarrowingUpper_Vector128_UInt16, + ["AddRoundedHighNarrowingUpper.Vector128.UInt32"] = AddRoundedHighNarrowingUpper_Vector128_UInt32, ["AddSaturate.Vector64.Byte"] = AddSaturate_Vector64_Byte, ["AddSaturate.Vector64.Int16"] = AddSaturate_Vector64_Int16, ["AddSaturate.Vector64.Int32"] = AddSaturate_Vector64_Int32, @@ -341,6 +341,62 @@ static Program() ["CompareTest.Vector128.UInt32"] = CompareTest_Vector128_UInt32, ["DivideScalar.Vector64.Double"] = DivideScalar_Vector64_Double, ["DivideScalar.Vector64.Single"] = DivideScalar_Vector64_Single, + ["DuplicateSelectedScalarToVector64.V64.Byte.1"] = DuplicateSelectedScalarToVector64_V64_Byte_1, + ["DuplicateSelectedScalarToVector64.V64.Int16.1"] = DuplicateSelectedScalarToVector64_V64_Int16_1, + ["DuplicateSelectedScalarToVector64.V64.Int32.1"] = DuplicateSelectedScalarToVector64_V64_Int32_1, + ["DuplicateSelectedScalarToVector64.V64.SByte.1"] = DuplicateSelectedScalarToVector64_V64_SByte_1, + ["DuplicateSelectedScalarToVector64.V64.Single.1"] = DuplicateSelectedScalarToVector64_V64_Single_1, + ["DuplicateSelectedScalarToVector64.V64.UInt16.1"] = DuplicateSelectedScalarToVector64_V64_UInt16_1, + ["DuplicateSelectedScalarToVector64.V64.UInt32.1"] = DuplicateSelectedScalarToVector64_V64_UInt32_1, + ["DuplicateSelectedScalarToVector64.V128.Byte.8"] = DuplicateSelectedScalarToVector64_V128_Byte_8, + ["DuplicateSelectedScalarToVector64.V128.Int16.4"] = DuplicateSelectedScalarToVector64_V128_Int16_4, + ["DuplicateSelectedScalarToVector64.V128.Int32.2"] = DuplicateSelectedScalarToVector64_V128_Int32_2, + ["DuplicateSelectedScalarToVector64.V128.SByte.8"] = DuplicateSelectedScalarToVector64_V128_SByte_8, + ["DuplicateSelectedScalarToVector64.V128.Single.2"] = DuplicateSelectedScalarToVector64_V128_Single_2, + ["DuplicateSelectedScalarToVector64.V128.UInt16.4"] = DuplicateSelectedScalarToVector64_V128_UInt16_4, + ["DuplicateSelectedScalarToVector64.V128.UInt32.2"] = DuplicateSelectedScalarToVector64_V128_UInt32_2, + ["DuplicateSelectedScalarToVector128.V64.Byte.1"] = DuplicateSelectedScalarToVector128_V64_Byte_1, + ["DuplicateSelectedScalarToVector128.V64.Int16.1"] = DuplicateSelectedScalarToVector128_V64_Int16_1, + ["DuplicateSelectedScalarToVector128.V64.Int32.1"] = DuplicateSelectedScalarToVector128_V64_Int32_1, + ["DuplicateSelectedScalarToVector128.V64.SByte.1"] = DuplicateSelectedScalarToVector128_V64_SByte_1, + ["DuplicateSelectedScalarToVector128.V64.Single.1"] = DuplicateSelectedScalarToVector128_V64_Single_1, + ["DuplicateSelectedScalarToVector128.V64.UInt16.1"] = DuplicateSelectedScalarToVector128_V64_UInt16_1, + ["DuplicateSelectedScalarToVector128.V64.UInt32.1"] = DuplicateSelectedScalarToVector128_V64_UInt32_1, + ["DuplicateSelectedScalarToVector128.V128.Byte.8"] = DuplicateSelectedScalarToVector128_V128_Byte_8, + ["DuplicateSelectedScalarToVector128.V128.Int16.4"] = DuplicateSelectedScalarToVector128_V128_Int16_4, + ["DuplicateSelectedScalarToVector128.V128.Int32.2"] = DuplicateSelectedScalarToVector128_V128_Int32_2, + ["DuplicateSelectedScalarToVector128.V128.SByte.8"] = DuplicateSelectedScalarToVector128_V128_SByte_8, + ["DuplicateSelectedScalarToVector128.V128.Single.2"] = DuplicateSelectedScalarToVector128_V128_Single_2, + ["DuplicateSelectedScalarToVector128.V128.UInt16.4"] = DuplicateSelectedScalarToVector128_V128_UInt16_4, + ["DuplicateSelectedScalarToVector128.V128.UInt32.2"] = DuplicateSelectedScalarToVector128_V128_UInt32_2, + ["DuplicateToVector64.Byte"] = DuplicateToVector64_Byte, + ["DuplicateToVector64.Byte.31"] = DuplicateToVector64_Byte_31, + ["DuplicateToVector64.Int16"] = DuplicateToVector64_Int16, + ["DuplicateToVector64.Int16.31"] = DuplicateToVector64_Int16_31, + ["DuplicateToVector64.Int32"] = DuplicateToVector64_Int32, + ["DuplicateToVector64.Int32.31"] = DuplicateToVector64_Int32_31, + ["DuplicateToVector64.SByte"] = DuplicateToVector64_SByte, + ["DuplicateToVector64.SByte.31"] = DuplicateToVector64_SByte_31, + ["DuplicateToVector64.Single"] = DuplicateToVector64_Single, + ["DuplicateToVector64.Single.31"] = DuplicateToVector64_Single_31, + ["DuplicateToVector64.UInt16"] = DuplicateToVector64_UInt16, + ["DuplicateToVector64.UInt16.31"] = DuplicateToVector64_UInt16_31, + ["DuplicateToVector64.UInt32"] = DuplicateToVector64_UInt32, + ["DuplicateToVector64.UInt32.31"] = DuplicateToVector64_UInt32_31, + ["DuplicateToVector128.Byte"] = DuplicateToVector128_Byte, + ["DuplicateToVector128.Byte.31"] = DuplicateToVector128_Byte_31, + ["DuplicateToVector128.Int16"] = DuplicateToVector128_Int16, + ["DuplicateToVector128.Int16.31"] = DuplicateToVector128_Int16_31, + ["DuplicateToVector128.Int32"] = DuplicateToVector128_Int32, + ["DuplicateToVector128.Int32.31"] = DuplicateToVector128_Int32_31, + ["DuplicateToVector128.SByte"] = DuplicateToVector128_SByte, + ["DuplicateToVector128.SByte.31"] = DuplicateToVector128_SByte_31, + ["DuplicateToVector128.Single"] = DuplicateToVector128_Single, + ["DuplicateToVector128.Single.31"] = DuplicateToVector128_Single_31, + ["DuplicateToVector128.UInt16"] = DuplicateToVector128_UInt16, + ["DuplicateToVector128.UInt16.31"] = DuplicateToVector128_UInt16_31, + ["DuplicateToVector128.UInt32"] = DuplicateToVector128_UInt32, + ["DuplicateToVector128.UInt32.31"] = DuplicateToVector128_UInt32_31, ["Extract.Vector64.Byte.1"] = Extract_Vector64_Byte_1, ["Extract.Vector64.Int16.1"] = Extract_Vector64_Int16_1, ["Extract.Vector64.Int32.1"] = Extract_Vector64_Int32_1, @@ -358,18 +414,18 @@ static Program() ["Extract.Vector128.UInt16.1"] = Extract_Vector128_UInt16_1, ["Extract.Vector128.UInt32.1"] = Extract_Vector128_UInt32_1, ["Extract.Vector128.UInt64.1"] = Extract_Vector128_UInt64_1, - ["ExtractAndNarrowHigh.Vector128.Int16"] = ExtractAndNarrowHigh_Vector128_Int16, - ["ExtractAndNarrowHigh.Vector128.Int32"] = ExtractAndNarrowHigh_Vector128_Int32, - ["ExtractAndNarrowHigh.Vector128.Int64"] = ExtractAndNarrowHigh_Vector128_Int64, - ["ExtractAndNarrowHigh.Vector128.UInt16"] = ExtractAndNarrowHigh_Vector128_UInt16, - ["ExtractAndNarrowHigh.Vector128.UInt32"] = ExtractAndNarrowHigh_Vector128_UInt32, - ["ExtractAndNarrowHigh.Vector128.UInt64"] = ExtractAndNarrowHigh_Vector128_UInt64, - ["ExtractAndNarrowLow.Vector128.Int16"] = ExtractAndNarrowLow_Vector128_Int16, - ["ExtractAndNarrowLow.Vector128.Int32"] = ExtractAndNarrowLow_Vector128_Int32, - ["ExtractAndNarrowLow.Vector128.Int64"] = ExtractAndNarrowLow_Vector128_Int64, - ["ExtractAndNarrowLow.Vector128.UInt16"] = ExtractAndNarrowLow_Vector128_UInt16, - ["ExtractAndNarrowLow.Vector128.UInt32"] = ExtractAndNarrowLow_Vector128_UInt32, - ["ExtractAndNarrowLow.Vector128.UInt64"] = ExtractAndNarrowLow_Vector128_UInt64, + ["ExtractNarrowingUpper.Vector128.Int16"] = ExtractNarrowingUpper_Vector128_Int16, + ["ExtractNarrowingUpper.Vector128.Int32"] = ExtractNarrowingUpper_Vector128_Int32, + ["ExtractNarrowingUpper.Vector128.Int64"] = ExtractNarrowingUpper_Vector128_Int64, + ["ExtractNarrowingUpper.Vector128.UInt16"] = ExtractNarrowingUpper_Vector128_UInt16, + ["ExtractNarrowingUpper.Vector128.UInt32"] = ExtractNarrowingUpper_Vector128_UInt32, + ["ExtractNarrowingUpper.Vector128.UInt64"] = ExtractNarrowingUpper_Vector128_UInt64, + ["ExtractNarrowingLower.Vector128.Int16"] = ExtractNarrowingLower_Vector128_Int16, + ["ExtractNarrowingLower.Vector128.Int32"] = ExtractNarrowingLower_Vector128_Int32, + ["ExtractNarrowingLower.Vector128.Int64"] = ExtractNarrowingLower_Vector128_Int64, + ["ExtractNarrowingLower.Vector128.UInt16"] = ExtractNarrowingLower_Vector128_UInt16, + ["ExtractNarrowingLower.Vector128.UInt32"] = ExtractNarrowingLower_Vector128_UInt32, + ["ExtractNarrowingLower.Vector128.UInt64"] = ExtractNarrowingLower_Vector128_UInt64, ["ExtractVector64.Byte.1"] = ExtractVector64_Byte_1, ["ExtractVector64.Int16.1"] = ExtractVector64_Int16_1, ["ExtractVector64.Int32.1"] = ExtractVector64_Int32_1, @@ -690,6 +746,10 @@ static Program() ["PolynomialMultiply.Vector64.SByte"] = PolynomialMultiply_Vector64_SByte, ["PolynomialMultiply.Vector128.Byte"] = PolynomialMultiply_Vector128_Byte, ["PolynomialMultiply.Vector128.SByte"] = PolynomialMultiply_Vector128_SByte, + ["PolynomialMultiplyWideningLower.Vector64.Byte"] = PolynomialMultiplyWideningLower_Vector64_Byte, + ["PolynomialMultiplyWideningLower.Vector64.SByte"] = PolynomialMultiplyWideningLower_Vector64_SByte, + ["PolynomialMultiplyWideningUpper.Vector128.Byte"] = PolynomialMultiplyWideningUpper_Vector128_Byte, + ["PolynomialMultiplyWideningUpper.Vector128.SByte"] = PolynomialMultiplyWideningUpper_Vector128_SByte, ["PopCount.Vector64.Byte"] = PopCount_Vector64_Byte, ["PopCount.Vector64.SByte"] = PopCount_Vector64_SByte, ["PopCount.Vector128.Byte"] = PopCount_Vector128_Byte, @@ -706,6 +766,327 @@ static Program() ["ReciprocalSquareRootStep.Vector128.Single"] = ReciprocalSquareRootStep_Vector128_Single, ["ReciprocalStep.Vector64.Single"] = ReciprocalStep_Vector64_Single, ["ReciprocalStep.Vector128.Single"] = ReciprocalStep_Vector128_Single, + ["ShiftArithmetic.Vector64.Int16"] = ShiftArithmetic_Vector64_Int16, + ["ShiftArithmetic.Vector64.Int32"] = ShiftArithmetic_Vector64_Int32, + ["ShiftArithmetic.Vector64.SByte"] = ShiftArithmetic_Vector64_SByte, + ["ShiftArithmetic.Vector128.Int16"] = ShiftArithmetic_Vector128_Int16, + ["ShiftArithmetic.Vector128.Int32"] = ShiftArithmetic_Vector128_Int32, + ["ShiftArithmetic.Vector128.Int64"] = ShiftArithmetic_Vector128_Int64, + ["ShiftArithmetic.Vector128.SByte"] = ShiftArithmetic_Vector128_SByte, + ["ShiftArithmeticRounded.Vector64.Int16"] = ShiftArithmeticRounded_Vector64_Int16, + ["ShiftArithmeticRounded.Vector64.Int32"] = ShiftArithmeticRounded_Vector64_Int32, + ["ShiftArithmeticRounded.Vector64.SByte"] = ShiftArithmeticRounded_Vector64_SByte, + ["ShiftArithmeticRounded.Vector128.Int16"] = ShiftArithmeticRounded_Vector128_Int16, + ["ShiftArithmeticRounded.Vector128.Int32"] = ShiftArithmeticRounded_Vector128_Int32, + ["ShiftArithmeticRounded.Vector128.Int64"] = ShiftArithmeticRounded_Vector128_Int64, + ["ShiftArithmeticRounded.Vector128.SByte"] = ShiftArithmeticRounded_Vector128_SByte, + ["ShiftArithmeticRoundedSaturate.Vector64.Int16"] = ShiftArithmeticRoundedSaturate_Vector64_Int16, + ["ShiftArithmeticRoundedSaturate.Vector64.Int32"] = ShiftArithmeticRoundedSaturate_Vector64_Int32, + ["ShiftArithmeticRoundedSaturate.Vector64.SByte"] = ShiftArithmeticRoundedSaturate_Vector64_SByte, + ["ShiftArithmeticRoundedSaturate.Vector128.Int16"] = ShiftArithmeticRoundedSaturate_Vector128_Int16, + ["ShiftArithmeticRoundedSaturate.Vector128.Int32"] = ShiftArithmeticRoundedSaturate_Vector128_Int32, + ["ShiftArithmeticRoundedSaturate.Vector128.Int64"] = ShiftArithmeticRoundedSaturate_Vector128_Int64, + ["ShiftArithmeticRoundedSaturate.Vector128.SByte"] = ShiftArithmeticRoundedSaturate_Vector128_SByte, + ["ShiftArithmeticRoundedSaturateScalar.Vector64.Int64"] = ShiftArithmeticRoundedSaturateScalar_Vector64_Int64, + ["ShiftArithmeticRoundedScalar.Vector64.Int64"] = ShiftArithmeticRoundedScalar_Vector64_Int64, + ["ShiftArithmeticSaturate.Vector64.Int16"] = ShiftArithmeticSaturate_Vector64_Int16, + ["ShiftArithmeticSaturate.Vector64.Int32"] = ShiftArithmeticSaturate_Vector64_Int32, + ["ShiftArithmeticSaturate.Vector64.SByte"] = ShiftArithmeticSaturate_Vector64_SByte, + ["ShiftArithmeticSaturate.Vector128.Int16"] = ShiftArithmeticSaturate_Vector128_Int16, + ["ShiftArithmeticSaturate.Vector128.Int32"] = ShiftArithmeticSaturate_Vector128_Int32, + ["ShiftArithmeticSaturate.Vector128.Int64"] = ShiftArithmeticSaturate_Vector128_Int64, + ["ShiftArithmeticSaturate.Vector128.SByte"] = ShiftArithmeticSaturate_Vector128_SByte, + ["ShiftArithmeticSaturateScalar.Vector64.Int64"] = ShiftArithmeticSaturateScalar_Vector64_Int64, + ["ShiftArithmeticScalar.Vector64.Int64"] = ShiftArithmeticScalar_Vector64_Int64, + ["ShiftLeftLogical.Vector64.Byte.1"] = ShiftLeftLogical_Vector64_Byte_1, + ["ShiftLeftLogical.Vector64.Int16.1"] = ShiftLeftLogical_Vector64_Int16_1, + ["ShiftLeftLogical.Vector64.Int32.1"] = ShiftLeftLogical_Vector64_Int32_1, + ["ShiftLeftLogical.Vector64.SByte.1"] = ShiftLeftLogical_Vector64_SByte_1, + ["ShiftLeftLogical.Vector64.UInt16.1"] = ShiftLeftLogical_Vector64_UInt16_1, + ["ShiftLeftLogical.Vector64.UInt32.1"] = ShiftLeftLogical_Vector64_UInt32_1, + ["ShiftLeftLogical.Vector128.Byte.1"] = ShiftLeftLogical_Vector128_Byte_1, + ["ShiftLeftLogical.Vector128.Int16.1"] = ShiftLeftLogical_Vector128_Int16_1, + ["ShiftLeftLogical.Vector128.Int64.1"] = ShiftLeftLogical_Vector128_Int64_1, + ["ShiftLeftLogical.Vector128.SByte.1"] = ShiftLeftLogical_Vector128_SByte_1, + ["ShiftLeftLogical.Vector128.UInt16.1"] = ShiftLeftLogical_Vector128_UInt16_1, + ["ShiftLeftLogical.Vector128.UInt32.1"] = ShiftLeftLogical_Vector128_UInt32_1, + ["ShiftLeftLogical.Vector128.UInt64.1"] = ShiftLeftLogical_Vector128_UInt64_1, + ["ShiftLeftLogicalSaturate.Vector64.Byte.1"] = ShiftLeftLogicalSaturate_Vector64_Byte_1, + ["ShiftLeftLogicalSaturate.Vector64.Int16.1"] = ShiftLeftLogicalSaturate_Vector64_Int16_1, + ["ShiftLeftLogicalSaturate.Vector64.Int32.1"] = ShiftLeftLogicalSaturate_Vector64_Int32_1, + ["ShiftLeftLogicalSaturate.Vector64.SByte.1"] = ShiftLeftLogicalSaturate_Vector64_SByte_1, + ["ShiftLeftLogicalSaturate.Vector64.UInt16.1"] = ShiftLeftLogicalSaturate_Vector64_UInt16_1, + ["ShiftLeftLogicalSaturate.Vector64.UInt32.1"] = ShiftLeftLogicalSaturate_Vector64_UInt32_1, + ["ShiftLeftLogicalSaturate.Vector128.Byte.1"] = ShiftLeftLogicalSaturate_Vector128_Byte_1, + ["ShiftLeftLogicalSaturate.Vector128.Int16.1"] = ShiftLeftLogicalSaturate_Vector128_Int16_1, + ["ShiftLeftLogicalSaturate.Vector128.Int32.1"] = ShiftLeftLogicalSaturate_Vector128_Int32_1, + ["ShiftLeftLogicalSaturate.Vector128.Int64.1"] = ShiftLeftLogicalSaturate_Vector128_Int64_1, + ["ShiftLeftLogicalSaturate.Vector128.SByte.1"] = ShiftLeftLogicalSaturate_Vector128_SByte_1, + ["ShiftLeftLogicalSaturate.Vector128.UInt16.1"] = ShiftLeftLogicalSaturate_Vector128_UInt16_1, + ["ShiftLeftLogicalSaturate.Vector128.UInt32.1"] = ShiftLeftLogicalSaturate_Vector128_UInt32_1, + ["ShiftLeftLogicalSaturate.Vector128.UInt64.1"] = ShiftLeftLogicalSaturate_Vector128_UInt64_1, + ["ShiftLeftLogicalSaturateScalar.Vector64.Int64.1"] = ShiftLeftLogicalSaturateScalar_Vector64_Int64_1, + ["ShiftLeftLogicalSaturateScalar.Vector64.UInt64.1"] = ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector64.Int16.1"] = ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector64.Int32.1"] = ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector64.SByte.1"] = ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector128.Int16.1"] = ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector128.Int32.1"] = ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector128.Int64.1"] = ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1, + ["ShiftLeftLogicalSaturateUnsigned.Vector128.SByte.1"] = ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1, + ["ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int64.1"] = ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1, + ["ShiftLeftLogicalScalar.Vector64.Int64.1"] = ShiftLeftLogicalScalar_Vector64_Int64_1, + ["ShiftLeftLogicalScalar.Vector64.UInt64.1"] = ShiftLeftLogicalScalar_Vector64_UInt64_1, + ["ShiftLeftLogicalWideningLower.Vector64.Byte.1"] = ShiftLeftLogicalWideningLower_Vector64_Byte_1, + ["ShiftLeftLogicalWideningLower.Vector64.Int16.1"] = ShiftLeftLogicalWideningLower_Vector64_Int16_1, + ["ShiftLeftLogicalWideningLower.Vector64.Int32.1"] = ShiftLeftLogicalWideningLower_Vector64_Int32_1, + ["ShiftLeftLogicalWideningLower.Vector64.SByte.1"] = ShiftLeftLogicalWideningLower_Vector64_SByte_1, + ["ShiftLeftLogicalWideningLower.Vector64.UInt16.1"] = ShiftLeftLogicalWideningLower_Vector64_UInt16_1, + ["ShiftLeftLogicalWideningLower.Vector64.UInt32.1"] = ShiftLeftLogicalWideningLower_Vector64_UInt32_1, + ["ShiftLeftLogicalWideningUpper.Vector128.Byte.1"] = ShiftLeftLogicalWideningUpper_Vector128_Byte_1, + ["ShiftLeftLogicalWideningUpper.Vector128.Int16.1"] = ShiftLeftLogicalWideningUpper_Vector128_Int16_1, + ["ShiftLeftLogicalWideningUpper.Vector128.Int32.1"] = ShiftLeftLogicalWideningUpper_Vector128_Int32_1, + ["ShiftLeftLogicalWideningUpper.Vector128.SByte.1"] = ShiftLeftLogicalWideningUpper_Vector128_SByte_1, + ["ShiftLeftLogicalWideningUpper.Vector128.UInt16.1"] = ShiftLeftLogicalWideningUpper_Vector128_UInt16_1, + ["ShiftLeftLogicalWideningUpper.Vector128.UInt32.1"] = ShiftLeftLogicalWideningUpper_Vector128_UInt32_1, + ["ShiftLogical.Vector64.Byte"] = ShiftLogical_Vector64_Byte, + ["ShiftLogical.Vector64.Int16"] = ShiftLogical_Vector64_Int16, + ["ShiftLogical.Vector64.Int32"] = ShiftLogical_Vector64_Int32, + ["ShiftLogical.Vector64.SByte"] = ShiftLogical_Vector64_SByte, + ["ShiftLogical.Vector64.UInt16"] = ShiftLogical_Vector64_UInt16, + ["ShiftLogical.Vector64.UInt32"] = ShiftLogical_Vector64_UInt32, + ["ShiftLogical.Vector128.Byte"] = ShiftLogical_Vector128_Byte, + ["ShiftLogical.Vector128.Int16"] = ShiftLogical_Vector128_Int16, + ["ShiftLogical.Vector128.Int32"] = ShiftLogical_Vector128_Int32, + ["ShiftLogical.Vector128.Int64"] = ShiftLogical_Vector128_Int64, + ["ShiftLogical.Vector128.SByte"] = ShiftLogical_Vector128_SByte, + ["ShiftLogical.Vector128.UInt16"] = ShiftLogical_Vector128_UInt16, + ["ShiftLogical.Vector128.UInt32"] = ShiftLogical_Vector128_UInt32, + ["ShiftLogical.Vector128.UInt64"] = ShiftLogical_Vector128_UInt64, + ["ShiftLogicalRounded.Vector64.Byte"] = ShiftLogicalRounded_Vector64_Byte, + ["ShiftLogicalRounded.Vector64.Int16"] = ShiftLogicalRounded_Vector64_Int16, + ["ShiftLogicalRounded.Vector64.Int32"] = ShiftLogicalRounded_Vector64_Int32, + ["ShiftLogicalRounded.Vector64.SByte"] = ShiftLogicalRounded_Vector64_SByte, + ["ShiftLogicalRounded.Vector64.UInt16"] = ShiftLogicalRounded_Vector64_UInt16, + ["ShiftLogicalRounded.Vector64.UInt32"] = ShiftLogicalRounded_Vector64_UInt32, + ["ShiftLogicalRounded.Vector128.Byte"] = ShiftLogicalRounded_Vector128_Byte, + ["ShiftLogicalRounded.Vector128.Int16"] = ShiftLogicalRounded_Vector128_Int16, + ["ShiftLogicalRounded.Vector128.Int32"] = ShiftLogicalRounded_Vector128_Int32, + ["ShiftLogicalRounded.Vector128.Int64"] = ShiftLogicalRounded_Vector128_Int64, + ["ShiftLogicalRounded.Vector128.SByte"] = ShiftLogicalRounded_Vector128_SByte, + ["ShiftLogicalRounded.Vector128.UInt16"] = ShiftLogicalRounded_Vector128_UInt16, + ["ShiftLogicalRounded.Vector128.UInt32"] = ShiftLogicalRounded_Vector128_UInt32, + ["ShiftLogicalRounded.Vector128.UInt64"] = ShiftLogicalRounded_Vector128_UInt64, + ["ShiftLogicalRoundedSaturate.Vector64.Byte"] = ShiftLogicalRoundedSaturate_Vector64_Byte, + ["ShiftLogicalRoundedSaturate.Vector64.Int16"] = ShiftLogicalRoundedSaturate_Vector64_Int16, + ["ShiftLogicalRoundedSaturate.Vector64.Int32"] = ShiftLogicalRoundedSaturate_Vector64_Int32, + ["ShiftLogicalRoundedSaturate.Vector64.SByte"] = ShiftLogicalRoundedSaturate_Vector64_SByte, + ["ShiftLogicalRoundedSaturate.Vector64.UInt16"] = ShiftLogicalRoundedSaturate_Vector64_UInt16, + ["ShiftLogicalRoundedSaturate.Vector64.UInt32"] = ShiftLogicalRoundedSaturate_Vector64_UInt32, + ["ShiftLogicalRoundedSaturate.Vector128.Byte"] = ShiftLogicalRoundedSaturate_Vector128_Byte, + ["ShiftLogicalRoundedSaturate.Vector128.Int16"] = ShiftLogicalRoundedSaturate_Vector128_Int16, + ["ShiftLogicalRoundedSaturate.Vector128.Int32"] = ShiftLogicalRoundedSaturate_Vector128_Int32, + ["ShiftLogicalRoundedSaturate.Vector128.Int64"] = ShiftLogicalRoundedSaturate_Vector128_Int64, + ["ShiftLogicalRoundedSaturate.Vector128.SByte"] = ShiftLogicalRoundedSaturate_Vector128_SByte, + ["ShiftLogicalRoundedSaturate.Vector128.UInt16"] = ShiftLogicalRoundedSaturate_Vector128_UInt16, + ["ShiftLogicalRoundedSaturate.Vector128.UInt32"] = ShiftLogicalRoundedSaturate_Vector128_UInt32, + ["ShiftLogicalRoundedSaturate.Vector128.UInt64"] = ShiftLogicalRoundedSaturate_Vector128_UInt64, + ["ShiftLogicalRoundedSaturateScalar.Vector64.Int64"] = ShiftLogicalRoundedSaturateScalar_Vector64_Int64, + ["ShiftLogicalRoundedSaturateScalar.Vector64.UInt64"] = ShiftLogicalRoundedSaturateScalar_Vector64_UInt64, + ["ShiftLogicalRoundedScalar.Vector64.Int64"] = ShiftLogicalRoundedScalar_Vector64_Int64, + ["ShiftLogicalRoundedScalar.Vector64.UInt64"] = ShiftLogicalRoundedScalar_Vector64_UInt64, + ["ShiftLogicalSaturate.Vector64.Byte"] = ShiftLogicalSaturate_Vector64_Byte, + ["ShiftLogicalSaturate.Vector64.Int16"] = ShiftLogicalSaturate_Vector64_Int16, + ["ShiftLogicalSaturate.Vector64.Int32"] = ShiftLogicalSaturate_Vector64_Int32, + ["ShiftLogicalSaturate.Vector64.SByte"] = ShiftLogicalSaturate_Vector64_SByte, + ["ShiftLogicalSaturate.Vector64.UInt16"] = ShiftLogicalSaturate_Vector64_UInt16, + ["ShiftLogicalSaturate.Vector64.UInt32"] = ShiftLogicalSaturate_Vector64_UInt32, + ["ShiftLogicalSaturate.Vector128.Byte"] = ShiftLogicalSaturate_Vector128_Byte, + ["ShiftLogicalSaturate.Vector128.Int16"] = ShiftLogicalSaturate_Vector128_Int16, + ["ShiftLogicalSaturate.Vector128.Int32"] = ShiftLogicalSaturate_Vector128_Int32, + ["ShiftLogicalSaturate.Vector128.Int64"] = ShiftLogicalSaturate_Vector128_Int64, + ["ShiftLogicalSaturate.Vector128.SByte"] = ShiftLogicalSaturate_Vector128_SByte, + ["ShiftLogicalSaturate.Vector128.UInt16"] = ShiftLogicalSaturate_Vector128_UInt16, + ["ShiftLogicalSaturate.Vector128.UInt32"] = ShiftLogicalSaturate_Vector128_UInt32, + ["ShiftLogicalSaturate.Vector128.UInt64"] = ShiftLogicalSaturate_Vector128_UInt64, + ["ShiftLogicalSaturateScalar.Vector64.Int64"] = ShiftLogicalSaturateScalar_Vector64_Int64, + ["ShiftLogicalSaturateScalar.Vector64.UInt64"] = ShiftLogicalSaturateScalar_Vector64_UInt64, + ["ShiftLogicalScalar.Vector64.Int64"] = ShiftLogicalScalar_Vector64_Int64, + ["ShiftLogicalScalar.Vector64.UInt64"] = ShiftLogicalScalar_Vector64_UInt64, + ["ShiftRightArithmetic.Vector64.Int16.1"] = ShiftRightArithmetic_Vector64_Int16_1, + ["ShiftRightArithmetic.Vector64.Int32.1"] = ShiftRightArithmetic_Vector64_Int32_1, + ["ShiftRightArithmetic.Vector64.SByte.1"] = ShiftRightArithmetic_Vector64_SByte_1, + ["ShiftRightArithmetic.Vector128.Int16.1"] = ShiftRightArithmetic_Vector128_Int16_1, + ["ShiftRightArithmetic.Vector128.Int32.1"] = ShiftRightArithmetic_Vector128_Int32_1, + ["ShiftRightArithmetic.Vector128.Int64.1"] = ShiftRightArithmetic_Vector128_Int64_1, + ["ShiftRightArithmetic.Vector128.SByte.1"] = ShiftRightArithmetic_Vector128_SByte_1, + ["ShiftRightArithmeticAdd.Vector64.Int16.1"] = ShiftRightArithmeticAdd_Vector64_Int16_1, + ["ShiftRightArithmeticAdd.Vector64.Int32.1"] = ShiftRightArithmeticAdd_Vector64_Int32_1, + ["ShiftRightArithmeticAdd.Vector64.SByte.1"] = ShiftRightArithmeticAdd_Vector64_SByte_1, + ["ShiftRightArithmeticAdd.Vector128.Int16.1"] = ShiftRightArithmeticAdd_Vector128_Int16_1, + ["ShiftRightArithmeticAdd.Vector128.Int32.1"] = ShiftRightArithmeticAdd_Vector128_Int32_1, + ["ShiftRightArithmeticAdd.Vector128.Int64.1"] = ShiftRightArithmeticAdd_Vector128_Int64_1, + ["ShiftRightArithmeticAdd.Vector128.SByte.1"] = ShiftRightArithmeticAdd_Vector128_SByte_1, + ["ShiftRightArithmeticAddScalar.Vector64.Int64.1"] = ShiftRightArithmeticAddScalar_Vector64_Int64_1, + ["ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int16.1"] = ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1, + ["ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int32.1"] = ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1, + ["ShiftRightArithmeticNarrowingSaturateLower.Vector64.SByte.1"] = ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1, + ["ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.Byte.1"] = ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1, + ["ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt16.1"] = ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1, + ["ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt32.1"] = ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1, + ["ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.Byte.1"] = ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1, + ["ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt16.1"] = ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1, + ["ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt32.1"] = ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1, + ["ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int16.1"] = ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1, + ["ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int32.1"] = ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1, + ["ShiftRightArithmeticNarrowingSaturateUpper.Vector128.SByte.1"] = ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1, + ["ShiftRightArithmeticRounded.Vector64.Int16.1"] = ShiftRightArithmeticRounded_Vector64_Int16_1, + ["ShiftRightArithmeticRounded.Vector64.Int32.1"] = ShiftRightArithmeticRounded_Vector64_Int32_1, + ["ShiftRightArithmeticRounded.Vector64.SByte.1"] = ShiftRightArithmeticRounded_Vector64_SByte_1, + ["ShiftRightArithmeticRounded.Vector128.Int16.1"] = ShiftRightArithmeticRounded_Vector128_Int16_1, + ["ShiftRightArithmeticRounded.Vector128.Int32.1"] = ShiftRightArithmeticRounded_Vector128_Int32_1, + ["ShiftRightArithmeticRounded.Vector128.Int64.1"] = ShiftRightArithmeticRounded_Vector128_Int64_1, + ["ShiftRightArithmeticRounded.Vector128.SByte.1"] = ShiftRightArithmeticRounded_Vector128_SByte_1, + ["ShiftRightArithmeticRoundedAdd.Vector64.Int16.1"] = ShiftRightArithmeticRoundedAdd_Vector64_Int16_1, + ["ShiftRightArithmeticRoundedAdd.Vector64.Int32.1"] = ShiftRightArithmeticRoundedAdd_Vector64_Int32_1, + ["ShiftRightArithmeticRoundedAdd.Vector64.SByte.1"] = ShiftRightArithmeticRoundedAdd_Vector64_SByte_1, + ["ShiftRightArithmeticRoundedAdd.Vector128.Int16.1"] = ShiftRightArithmeticRoundedAdd_Vector128_Int16_1, + ["ShiftRightArithmeticRoundedAdd.Vector128.Int32.1"] = ShiftRightArithmeticRoundedAdd_Vector128_Int32_1, + ["ShiftRightArithmeticRoundedAdd.Vector128.Int64.1"] = ShiftRightArithmeticRoundedAdd_Vector128_Int64_1, + ["ShiftRightArithmeticRoundedAdd.Vector128.SByte.1"] = ShiftRightArithmeticRoundedAdd_Vector128_SByte_1, + ["ShiftRightArithmeticRoundedAddScalar.Vector64.Int64.1"] = ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int16.1"] = ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int32.1"] = ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.SByte.1"] = ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.Byte.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt16.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt32.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.Byte.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt16.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt32.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int16.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int32.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1, + ["ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.SByte.1"] = ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1, + ["ShiftRightArithmeticRoundedScalar.Vector64.Int64.1"] = ShiftRightArithmeticRoundedScalar_Vector64_Int64_1, + ["ShiftRightArithmeticScalar.Vector64.Int64.1"] = ShiftRightArithmeticScalar_Vector64_Int64_1, + ["ShiftRightLogical.Vector64.Byte.1"] = ShiftRightLogical_Vector64_Byte_1, + ["ShiftRightLogical.Vector64.Int16.1"] = ShiftRightLogical_Vector64_Int16_1, + ["ShiftRightLogical.Vector64.Int32.1"] = ShiftRightLogical_Vector64_Int32_1, + ["ShiftRightLogical.Vector64.SByte.1"] = ShiftRightLogical_Vector64_SByte_1, + ["ShiftRightLogical.Vector64.UInt16.1"] = ShiftRightLogical_Vector64_UInt16_1, + ["ShiftRightLogical.Vector64.UInt32.1"] = ShiftRightLogical_Vector64_UInt32_1, + ["ShiftRightLogical.Vector128.Byte.1"] = ShiftRightLogical_Vector128_Byte_1, + ["ShiftRightLogical.Vector128.Int16.1"] = ShiftRightLogical_Vector128_Int16_1, + ["ShiftRightLogical.Vector128.Int32.1"] = ShiftRightLogical_Vector128_Int32_1, + ["ShiftRightLogical.Vector128.Int64.1"] = ShiftRightLogical_Vector128_Int64_1, + ["ShiftRightLogical.Vector128.SByte.1"] = ShiftRightLogical_Vector128_SByte_1, + ["ShiftRightLogical.Vector128.UInt16.1"] = ShiftRightLogical_Vector128_UInt16_1, + ["ShiftRightLogical.Vector128.UInt32.1"] = ShiftRightLogical_Vector128_UInt32_1, + ["ShiftRightLogical.Vector128.UInt64.1"] = ShiftRightLogical_Vector128_UInt64_1, + ["ShiftRightLogicalAdd.Vector64.Byte.1"] = ShiftRightLogicalAdd_Vector64_Byte_1, + ["ShiftRightLogicalAdd.Vector64.Int16.1"] = ShiftRightLogicalAdd_Vector64_Int16_1, + ["ShiftRightLogicalAdd.Vector64.Int32.1"] = ShiftRightLogicalAdd_Vector64_Int32_1, + ["ShiftRightLogicalAdd.Vector64.SByte.1"] = ShiftRightLogicalAdd_Vector64_SByte_1, + ["ShiftRightLogicalAdd.Vector64.UInt16.1"] = ShiftRightLogicalAdd_Vector64_UInt16_1, + ["ShiftRightLogicalAdd.Vector64.UInt32.1"] = ShiftRightLogicalAdd_Vector64_UInt32_1, + ["ShiftRightLogicalAdd.Vector128.Byte.1"] = ShiftRightLogicalAdd_Vector128_Byte_1, + ["ShiftRightLogicalAdd.Vector128.Int16.1"] = ShiftRightLogicalAdd_Vector128_Int16_1, + ["ShiftRightLogicalAdd.Vector128.Int32.1"] = ShiftRightLogicalAdd_Vector128_Int32_1, + ["ShiftRightLogicalAdd.Vector128.Int64.1"] = ShiftRightLogicalAdd_Vector128_Int64_1, + ["ShiftRightLogicalAdd.Vector128.SByte.1"] = ShiftRightLogicalAdd_Vector128_SByte_1, + ["ShiftRightLogicalAdd.Vector128.UInt16.1"] = ShiftRightLogicalAdd_Vector128_UInt16_1, + ["ShiftRightLogicalAdd.Vector128.UInt32.1"] = ShiftRightLogicalAdd_Vector128_UInt32_1, + ["ShiftRightLogicalAdd.Vector128.UInt64.1"] = ShiftRightLogicalAdd_Vector128_UInt64_1, + ["ShiftRightLogicalAddScalar.Vector64.Int64.1"] = ShiftRightLogicalAddScalar_Vector64_Int64_1, + ["ShiftRightLogicalAddScalar.Vector64.UInt64.1"] = ShiftRightLogicalAddScalar_Vector64_UInt64_1, + ["ShiftRightLogicalNarrowingLower.Vector64.Byte.1"] = ShiftRightLogicalNarrowingLower_Vector64_Byte_1, + ["ShiftRightLogicalNarrowingLower.Vector64.Int16.1"] = ShiftRightLogicalNarrowingLower_Vector64_Int16_1, + ["ShiftRightLogicalNarrowingLower.Vector64.Int32.1"] = ShiftRightLogicalNarrowingLower_Vector64_Int32_1, + ["ShiftRightLogicalNarrowingLower.Vector64.SByte.1"] = ShiftRightLogicalNarrowingLower_Vector64_SByte_1, + ["ShiftRightLogicalNarrowingLower.Vector64.UInt16.1"] = ShiftRightLogicalNarrowingLower_Vector64_UInt16_1, + ["ShiftRightLogicalNarrowingLower.Vector64.UInt32.1"] = ShiftRightLogicalNarrowingLower_Vector64_UInt32_1, + ["ShiftRightLogicalNarrowingSaturateLower.Vector64.Byte.1"] = ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1, + ["ShiftRightLogicalNarrowingSaturateLower.Vector64.Int16.1"] = ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1, + ["ShiftRightLogicalNarrowingSaturateLower.Vector64.Int32.1"] = ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1, + ["ShiftRightLogicalNarrowingSaturateLower.Vector64.SByte.1"] = ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1, + ["ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt16.1"] = ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1, + ["ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt32.1"] = ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1, + ["ShiftRightLogicalNarrowingSaturateUpper.Vector128.Byte.1"] = ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1, + ["ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int16.1"] = ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1, + ["ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int32.1"] = ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1, + ["ShiftRightLogicalNarrowingSaturateUpper.Vector128.SByte.1"] = ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1, + ["ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt16.1"] = ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1, + ["ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt32.1"] = ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1, + ["ShiftRightLogicalNarrowingUpper.Vector128.Byte.1"] = ShiftRightLogicalNarrowingUpper_Vector128_Byte_1, + ["ShiftRightLogicalNarrowingUpper.Vector128.Int16.1"] = ShiftRightLogicalNarrowingUpper_Vector128_Int16_1, + ["ShiftRightLogicalNarrowingUpper.Vector128.Int32.1"] = ShiftRightLogicalNarrowingUpper_Vector128_Int32_1, + ["ShiftRightLogicalNarrowingUpper.Vector128.SByte.1"] = ShiftRightLogicalNarrowingUpper_Vector128_SByte_1, + ["ShiftRightLogicalNarrowingUpper.Vector128.UInt16.1"] = ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1, + ["ShiftRightLogicalNarrowingUpper.Vector128.UInt32.1"] = ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1, + ["ShiftRightLogicalRounded.Vector64.Byte.1"] = ShiftRightLogicalRounded_Vector64_Byte_1, + ["ShiftRightLogicalRounded.Vector64.Int16.1"] = ShiftRightLogicalRounded_Vector64_Int16_1, + ["ShiftRightLogicalRounded.Vector64.Int32.1"] = ShiftRightLogicalRounded_Vector64_Int32_1, + ["ShiftRightLogicalRounded.Vector64.SByte.1"] = ShiftRightLogicalRounded_Vector64_SByte_1, + ["ShiftRightLogicalRounded.Vector64.UInt16.1"] = ShiftRightLogicalRounded_Vector64_UInt16_1, + ["ShiftRightLogicalRounded.Vector64.UInt32.1"] = ShiftRightLogicalRounded_Vector64_UInt32_1, + ["ShiftRightLogicalRounded.Vector128.Byte.1"] = ShiftRightLogicalRounded_Vector128_Byte_1, + ["ShiftRightLogicalRounded.Vector128.Int16.1"] = ShiftRightLogicalRounded_Vector128_Int16_1, + ["ShiftRightLogicalRounded.Vector128.Int32.1"] = ShiftRightLogicalRounded_Vector128_Int32_1, + ["ShiftRightLogicalRounded.Vector128.Int64.1"] = ShiftRightLogicalRounded_Vector128_Int64_1, + ["ShiftRightLogicalRounded.Vector128.SByte.1"] = ShiftRightLogicalRounded_Vector128_SByte_1, + ["ShiftRightLogicalRounded.Vector128.UInt16.1"] = ShiftRightLogicalRounded_Vector128_UInt16_1, + ["ShiftRightLogicalRounded.Vector128.UInt32.1"] = ShiftRightLogicalRounded_Vector128_UInt32_1, + ["ShiftRightLogicalRounded.Vector128.UInt64.1"] = ShiftRightLogicalRounded_Vector128_UInt64_1, + ["ShiftRightLogicalRoundedAdd.Vector64.Byte.1"] = ShiftRightLogicalRoundedAdd_Vector64_Byte_1, + ["ShiftRightLogicalRoundedAdd.Vector64.Int16.1"] = ShiftRightLogicalRoundedAdd_Vector64_Int16_1, + ["ShiftRightLogicalRoundedAdd.Vector64.Int32.1"] = ShiftRightLogicalRoundedAdd_Vector64_Int32_1, + ["ShiftRightLogicalRoundedAdd.Vector64.SByte.1"] = ShiftRightLogicalRoundedAdd_Vector64_SByte_1, + ["ShiftRightLogicalRoundedAdd.Vector64.UInt16.1"] = ShiftRightLogicalRoundedAdd_Vector64_UInt16_1, + ["ShiftRightLogicalRoundedAdd.Vector64.UInt32.1"] = ShiftRightLogicalRoundedAdd_Vector64_UInt32_1, + ["ShiftRightLogicalRoundedAdd.Vector128.Byte.1"] = ShiftRightLogicalRoundedAdd_Vector128_Byte_1, + ["ShiftRightLogicalRoundedAdd.Vector128.Int16.1"] = ShiftRightLogicalRoundedAdd_Vector128_Int16_1, + ["ShiftRightLogicalRoundedAdd.Vector128.Int32.1"] = ShiftRightLogicalRoundedAdd_Vector128_Int32_1, + ["ShiftRightLogicalRoundedAdd.Vector128.Int64.1"] = ShiftRightLogicalRoundedAdd_Vector128_Int64_1, + ["ShiftRightLogicalRoundedAdd.Vector128.SByte.1"] = ShiftRightLogicalRoundedAdd_Vector128_SByte_1, + ["ShiftRightLogicalRoundedAdd.Vector128.UInt16.1"] = ShiftRightLogicalRoundedAdd_Vector128_UInt16_1, + ["ShiftRightLogicalRoundedAdd.Vector128.UInt32.1"] = ShiftRightLogicalRoundedAdd_Vector128_UInt32_1, + ["ShiftRightLogicalRoundedAdd.Vector128.UInt64.1"] = ShiftRightLogicalRoundedAdd_Vector128_UInt64_1, + ["ShiftRightLogicalRoundedAddScalar.Vector64.Int64.1"] = ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1, + ["ShiftRightLogicalRoundedAddScalar.Vector64.UInt64.1"] = ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1, + ["ShiftRightLogicalRoundedNarrowingLower.Vector64.Byte.1"] = ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1, + ["ShiftRightLogicalRoundedNarrowingLower.Vector64.Int16.1"] = ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1, + ["ShiftRightLogicalRoundedNarrowingLower.Vector64.Int32.1"] = ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1, + ["ShiftRightLogicalRoundedNarrowingLower.Vector64.SByte.1"] = ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1, + ["ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt16.1"] = ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1, + ["ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt32.1"] = ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1, + ["ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Byte.1"] = ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1, + ["ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int16.1"] = ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1, + ["ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int32.1"] = ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1, + ["ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.SByte.1"] = ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1, + ["ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt16.1"] = ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1, + ["ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt32.1"] = ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1, + ["ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Byte.1"] = ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1, + ["ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int16.1"] = ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1, + ["ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int32.1"] = ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1, + ["ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.SByte.1"] = ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1, + ["ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt16.1"] = ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1, + ["ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt32.1"] = ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1, + ["ShiftRightLogicalRoundedNarrowingUpper.Vector128.Byte.1"] = ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1, + ["ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int16.1"] = ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1, + ["ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int32.1"] = ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1, + ["ShiftRightLogicalRoundedNarrowingUpper.Vector128.SByte.1"] = ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1, + ["ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt16.1"] = ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1, + ["ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt32.1"] = ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1, + ["ShiftRightLogicalRoundedScalar.Vector64.Int64.1"] = ShiftRightLogicalRoundedScalar_Vector64_Int64_1, + ["ShiftRightLogicalRoundedScalar.Vector64.UInt64.1"] = ShiftRightLogicalRoundedScalar_Vector64_UInt64_1, + ["ShiftRightLogicalScalar.Vector64.Int64.1"] = ShiftRightLogicalScalar_Vector64_Int64_1, + ["ShiftRightLogicalScalar.Vector64.UInt64.1"] = ShiftRightLogicalScalar_Vector64_UInt64_1, + ["SignExtendWideningLower.Vector64.Int16"] = SignExtendWideningLower_Vector64_Int16, + ["SignExtendWideningLower.Vector64.Int32"] = SignExtendWideningLower_Vector64_Int32, + ["SignExtendWideningLower.Vector64.SByte"] = SignExtendWideningLower_Vector64_SByte, + ["SignExtendWideningUpper.Vector128.Int16"] = SignExtendWideningUpper_Vector128_Int16, + ["SignExtendWideningUpper.Vector128.Int32"] = SignExtendWideningUpper_Vector128_Int32, + ["SignExtendWideningUpper.Vector128.SByte"] = SignExtendWideningUpper_Vector128_SByte, ["SqrtScalar.Vector64.Double"] = SqrtScalar_Vector64_Double, ["SqrtScalar.Vector64.Single"] = SqrtScalar_Vector64_Single, ["Store.Vector64.Byte"] = Store_Vector64_Byte, @@ -744,30 +1125,30 @@ static Program() ["Subtract.Vector128.UInt16"] = Subtract_Vector128_UInt16, ["Subtract.Vector128.UInt32"] = Subtract_Vector128_UInt32, ["Subtract.Vector128.UInt64"] = Subtract_Vector128_UInt64, - ["SubtractReturningHighNarrowLower.Vector64.Byte"] = SubtractReturningHighNarrowLower_Vector64_Byte, - ["SubtractReturningHighNarrowLower.Vector64.Int16"] = SubtractReturningHighNarrowLower_Vector64_Int16, - ["SubtractReturningHighNarrowLower.Vector64.Int32"] = SubtractReturningHighNarrowLower_Vector64_Int32, - ["SubtractReturningHighNarrowLower.Vector64.SByte"] = SubtractReturningHighNarrowLower_Vector64_SByte, - ["SubtractReturningHighNarrowLower.Vector64.UInt16"] = SubtractReturningHighNarrowLower_Vector64_UInt16, - ["SubtractReturningHighNarrowLower.Vector64.UInt32"] = SubtractReturningHighNarrowLower_Vector64_UInt32, - ["SubtractReturningHighNarrowUpper.Vector128.Byte"] = SubtractReturningHighNarrowUpper_Vector128_Byte, - ["SubtractReturningHighNarrowUpper.Vector128.Int16"] = SubtractReturningHighNarrowUpper_Vector128_Int16, - ["SubtractReturningHighNarrowUpper.Vector128.Int32"] = SubtractReturningHighNarrowUpper_Vector128_Int32, - ["SubtractReturningHighNarrowUpper.Vector128.SByte"] = SubtractReturningHighNarrowUpper_Vector128_SByte, - ["SubtractReturningHighNarrowUpper.Vector128.UInt16"] = SubtractReturningHighNarrowUpper_Vector128_UInt16, - ["SubtractReturningHighNarrowUpper.Vector128.UInt32"] = SubtractReturningHighNarrowUpper_Vector128_UInt32, - ["SubtractReturningRoundedHighNarrowLower.Vector64.Byte"] = SubtractReturningRoundedHighNarrowLower_Vector64_Byte, - ["SubtractReturningRoundedHighNarrowLower.Vector64.Int16"] = SubtractReturningRoundedHighNarrowLower_Vector64_Int16, - ["SubtractReturningRoundedHighNarrowLower.Vector64.Int32"] = SubtractReturningRoundedHighNarrowLower_Vector64_Int32, - ["SubtractReturningRoundedHighNarrowLower.Vector64.SByte"] = SubtractReturningRoundedHighNarrowLower_Vector64_SByte, - ["SubtractReturningRoundedHighNarrowLower.Vector64.UInt16"] = SubtractReturningRoundedHighNarrowLower_Vector64_UInt16, - ["SubtractReturningRoundedHighNarrowLower.Vector64.UInt32"] = SubtractReturningRoundedHighNarrowLower_Vector64_UInt32, - ["SubtractReturningRoundedHighNarrowUpper.Vector128.Byte"] = SubtractReturningRoundedHighNarrowUpper_Vector128_Byte, - ["SubtractReturningRoundedHighNarrowUpper.Vector128.Int16"] = SubtractReturningRoundedHighNarrowUpper_Vector128_Int16, - ["SubtractReturningRoundedHighNarrowUpper.Vector128.Int32"] = SubtractReturningRoundedHighNarrowUpper_Vector128_Int32, - ["SubtractReturningRoundedHighNarrowUpper.Vector128.SByte"] = SubtractReturningRoundedHighNarrowUpper_Vector128_SByte, - ["SubtractReturningRoundedHighNarrowUpper.Vector128.UInt16"] = SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16, - ["SubtractReturningRoundedHighNarrowUpper.Vector128.UInt32"] = SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32, + ["SubtractHighNarrowingLower.Vector64.Byte"] = SubtractHighNarrowingLower_Vector64_Byte, + ["SubtractHighNarrowingLower.Vector64.Int16"] = SubtractHighNarrowingLower_Vector64_Int16, + ["SubtractHighNarrowingLower.Vector64.Int32"] = SubtractHighNarrowingLower_Vector64_Int32, + ["SubtractHighNarrowingLower.Vector64.SByte"] = SubtractHighNarrowingLower_Vector64_SByte, + ["SubtractHighNarrowingLower.Vector64.UInt16"] = SubtractHighNarrowingLower_Vector64_UInt16, + ["SubtractHighNarrowingLower.Vector64.UInt32"] = SubtractHighNarrowingLower_Vector64_UInt32, + ["SubtractHighNarrowingUpper.Vector128.Byte"] = SubtractHighNarrowingUpper_Vector128_Byte, + ["SubtractHighNarrowingUpper.Vector128.Int16"] = SubtractHighNarrowingUpper_Vector128_Int16, + ["SubtractHighNarrowingUpper.Vector128.Int32"] = SubtractHighNarrowingUpper_Vector128_Int32, + ["SubtractHighNarrowingUpper.Vector128.SByte"] = SubtractHighNarrowingUpper_Vector128_SByte, + ["SubtractHighNarrowingUpper.Vector128.UInt16"] = SubtractHighNarrowingUpper_Vector128_UInt16, + ["SubtractHighNarrowingUpper.Vector128.UInt32"] = SubtractHighNarrowingUpper_Vector128_UInt32, + ["SubtractRoundedHighNarrowingLower.Vector64.Byte"] = SubtractRoundedHighNarrowingLower_Vector64_Byte, + ["SubtractRoundedHighNarrowingLower.Vector64.Int16"] = SubtractRoundedHighNarrowingLower_Vector64_Int16, + ["SubtractRoundedHighNarrowingLower.Vector64.Int32"] = SubtractRoundedHighNarrowingLower_Vector64_Int32, + ["SubtractRoundedHighNarrowingLower.Vector64.SByte"] = SubtractRoundedHighNarrowingLower_Vector64_SByte, + ["SubtractRoundedHighNarrowingLower.Vector64.UInt16"] = SubtractRoundedHighNarrowingLower_Vector64_UInt16, + ["SubtractRoundedHighNarrowingLower.Vector64.UInt32"] = SubtractRoundedHighNarrowingLower_Vector64_UInt32, + ["SubtractRoundedHighNarrowingUpper.Vector128.Byte"] = SubtractRoundedHighNarrowingUpper_Vector128_Byte, + ["SubtractRoundedHighNarrowingUpper.Vector128.Int16"] = SubtractRoundedHighNarrowingUpper_Vector128_Int16, + ["SubtractRoundedHighNarrowingUpper.Vector128.Int32"] = SubtractRoundedHighNarrowingUpper_Vector128_Int32, + ["SubtractRoundedHighNarrowingUpper.Vector128.SByte"] = SubtractRoundedHighNarrowingUpper_Vector128_SByte, + ["SubtractRoundedHighNarrowingUpper.Vector128.UInt16"] = SubtractRoundedHighNarrowingUpper_Vector128_UInt16, + ["SubtractRoundedHighNarrowingUpper.Vector128.UInt32"] = SubtractRoundedHighNarrowingUpper_Vector128_UInt32, ["SubtractSaturate.Vector64.Byte"] = SubtractSaturate_Vector64_Byte, ["SubtractSaturate.Vector64.Int16"] = SubtractSaturate_Vector64_Int16, ["SubtractSaturate.Vector64.Int32"] = SubtractSaturate_Vector64_Int32, @@ -836,6 +1217,18 @@ static Program() ["Xor.Vector128.UInt16"] = Xor_Vector128_UInt16, ["Xor.Vector128.UInt32"] = Xor_Vector128_UInt32, ["Xor.Vector128.UInt64"] = Xor_Vector128_UInt64, + ["ZeroExtendWideningLower.Vector64.Byte"] = ZeroExtendWideningLower_Vector64_Byte, + ["ZeroExtendWideningLower.Vector64.Int16"] = ZeroExtendWideningLower_Vector64_Int16, + ["ZeroExtendWideningLower.Vector64.Int32"] = ZeroExtendWideningLower_Vector64_Int32, + ["ZeroExtendWideningLower.Vector64.SByte"] = ZeroExtendWideningLower_Vector64_SByte, + ["ZeroExtendWideningLower.Vector64.UInt16"] = ZeroExtendWideningLower_Vector64_UInt16, + ["ZeroExtendWideningLower.Vector64.UInt32"] = ZeroExtendWideningLower_Vector64_UInt32, + ["ZeroExtendWideningUpper.Vector128.Byte"] = ZeroExtendWideningUpper_Vector128_Byte, + ["ZeroExtendWideningUpper.Vector128.Int16"] = ZeroExtendWideningUpper_Vector128_Int16, + ["ZeroExtendWideningUpper.Vector128.Int32"] = ZeroExtendWideningUpper_Vector128_Int32, + ["ZeroExtendWideningUpper.Vector128.SByte"] = ZeroExtendWideningUpper_Vector128_SByte, + ["ZeroExtendWideningUpper.Vector128.UInt16"] = ZeroExtendWideningUpper_Vector128_UInt16, + ["ZeroExtendWideningUpper.Vector128.UInt32"] = ZeroExtendWideningUpper_Vector128_UInt32, }; } } diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int16.cs new file mode 100644 index 0000000000000..004afafdffc15 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int32.cs new file mode 100644 index 0000000000000..bd0527517d4f8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int64.cs new file mode 100644 index 0000000000000..dc31a6897a276 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.SByte.cs new file mode 100644 index 0000000000000..abdadf2096690 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.Int16.cs new file mode 100644 index 0000000000000..6147ff324bc47 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.Int32.cs new file mode 100644 index 0000000000000..cea92f720d580 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.SByte.cs new file mode 100644 index 0000000000000..1df2baab309eb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmetic.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmetic_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmetic( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmetic), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmetic( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmetic(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmetic_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmetic(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmetic( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmetic(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmetic)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int16.cs new file mode 100644 index 0000000000000..65a0afda9b07b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int32.cs new file mode 100644 index 0000000000000..d43861ceb6b58 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int64.cs new file mode 100644 index 0000000000000..eb08ad535f566 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.SByte.cs new file mode 100644 index 0000000000000..36b2d0e36c32c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.Int16.cs new file mode 100644 index 0000000000000..56e2a394bddd8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.Int32.cs new file mode 100644 index 0000000000000..ecbf0dbac1d0c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.SByte.cs new file mode 100644 index 0000000000000..a0a72ba9bfa88 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRounded.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRounded_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRounded_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int16.cs new file mode 100644 index 0000000000000..7e2820aa003a3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int32.cs new file mode 100644 index 0000000000000..a70c32f1d9001 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int64.cs new file mode 100644 index 0000000000000..0ca521fe3930e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.SByte.cs new file mode 100644 index 0000000000000..92663ab176402 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.Int16.cs new file mode 100644 index 0000000000000..7854dc8a00c6c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.Int32.cs new file mode 100644 index 0000000000000..d416c680f6f19 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.SByte.cs new file mode 100644 index 0000000000000..ee0cf1385a182 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturate.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturate_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturate_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturateScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturateScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..82a478c05dc1e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedSaturateScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedSaturateScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64(); + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedSaturateScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..236e5058b4d5d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticRoundedScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticRoundedScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticRoundedScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticRoundedScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticRoundedScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticRoundedScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticRoundedScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64(); + var result = AdvSimd.ShiftArithmeticRoundedScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticRoundedScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticRoundedScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticRounded(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticRoundedScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int16.cs new file mode 100644 index 0000000000000..f69865da37308 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int32.cs new file mode 100644 index 0000000000000..c4b65ac67dec9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int64.cs new file mode 100644 index 0000000000000..fa25da4559362 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.SByte.cs new file mode 100644 index 0000000000000..335a55256c564 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.Int16.cs new file mode 100644 index 0000000000000..1c0120331f375 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.Int32.cs new file mode 100644 index 0000000000000..67b0e4dc96e61 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.SByte.cs new file mode 100644 index 0000000000000..89a0732b5fcc7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturate.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturate_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturate_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturate( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturateScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturateScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..f11399812c4b8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticSaturateScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticSaturateScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64(); + var result = AdvSimd.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticSaturateScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..ee58a039ccf2b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftArithmeticScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftArithmeticScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftArithmeticScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftArithmeticScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftArithmeticScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftArithmeticScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftArithmeticScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftArithmeticScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64(); + var result = AdvSimd.ShiftArithmeticScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftArithmeticScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftArithmeticScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftArithmetic(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftArithmeticScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..e5876543df026 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..0acbde2731056 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..f659c72a35604 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..79af663f324f7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..9dd8e89896331 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..aef06f03ac89c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt64.1.cs new file mode 100644 index 0000000000000..74d56e3d66a6b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector128.UInt64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector128_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector128_UInt64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..92ee7ffad1543 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..9fa76a108cffb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..5deca2aa3ad4f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..3c21bf6fe260f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..b6307bfc7f588 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..d7e57acc1492c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogical.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogical_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogical_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogical( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..90999ea1642aa --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..6877a73fd6d1f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..4a76316e39da5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..37dde498561c8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..9eff7dae8b86e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..d0a7cceed73cc --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..7461e8b421132 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt64.1.cs new file mode 100644 index 0000000000000..b7135ce6866ff --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector128.UInt64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector128_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector128_UInt64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..19f6adbc90cd7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..1f2f914a462ea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..9a7e8a89f35d8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..3515faa2d8fc3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..0a0471355a609 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..2a74644f94f7f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturate.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturate_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturate), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturate(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturate_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturate(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturate)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..6794c90089219 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateScalar.Vector64.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateScalar.Vector64.UInt64.1.cs new file mode 100644 index 0000000000000..46ea94dcdfcc0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateScalar.Vector64.UInt64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..6085e1bd99156 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..f9bb48efc64ec --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..53e118e13ebdb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..ced25f2be3b85 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..0ec38fe4678cd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..04170dcc9b793 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..f2eae9c2e7907 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsigned.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsigned( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsigned)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..805b233f85b79 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalSaturateUnsignedScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalSaturateUnsignedScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..40358c81ec1d6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftLeftLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogical(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalScalar.Vector64.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalScalar.Vector64.UInt64.1.cs new file mode 100644 index 0000000000000..a9c5ebabd1281 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalScalar.Vector64.UInt64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalScalar_Vector64_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1(); + var result = AdvSimd.ShiftLeftLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalScalar_Vector64_UInt64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLeftLogical(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..6643b012f5c27 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningLower)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..18b90d66f0c21 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningLower)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..b78654de09858 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningLower)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..ceaf877d20326 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningLower)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..9dcf79fc9bbc6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningLower)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..e53f3be0c9154 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningLower), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningLower_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningLower( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningLower)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..19009e19bca80 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningUpper_Vector128_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningUpper)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..1c8ced42418e7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningUpper_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningUpper)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..5482ea148d99f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningUpper_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningUpper)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..a5158ce7397da --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningUpper_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningUpper)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..ce2a730d027f9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningUpper_Vector128_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningUpper)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..4802406e32717 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLeftLogicalWideningUpper.Vector128.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLeftLogicalWideningUpper_Vector128_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLeftLogicalWideningUpper), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftLeftLogicalWideningUpper_Vector128_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLeftLogicalWideningUpper(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLeftLogicalWideningUpper( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLeftLogicalWideningUpper)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Byte.cs new file mode 100644 index 0000000000000..b5f1ee0ac9a93 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_Byte testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Byte(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int16.cs new file mode 100644 index 0000000000000..61e1428538a9c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int16(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int32.cs new file mode 100644 index 0000000000000..c9e06a69bd944 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int32(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int64.cs new file mode 100644 index 0000000000000..9279375a741a0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int64(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.SByte.cs new file mode 100644 index 0000000000000..9fffdc8224b94 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_SByte(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt16.cs new file mode 100644 index 0000000000000..f9d47ca6c3e8c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt32.cs new file mode 100644 index 0000000000000..1477f27f0237e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt64.cs new file mode 100644 index 0000000000000..878e05f57d89d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector128.UInt64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector128_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Byte.cs new file mode 100644 index 0000000000000..0d0247d2927e9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector64_Byte testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Byte(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Int16.cs new file mode 100644 index 0000000000000..cf370b6685b02 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Int16(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Int32.cs new file mode 100644 index 0000000000000..74e76ebb9a32b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Int32(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.SByte.cs new file mode 100644 index 0000000000000..28171de391d20 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_SByte(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.UInt16.cs new file mode 100644 index 0000000000000..a12a7e6f2e1e9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector64_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.UInt32.cs new file mode 100644 index 0000000000000..da032eca83960 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogical.Vector64.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogical_Vector64_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32 testClass) + { + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogical( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogical), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogical( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogical(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogical_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogical(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogical( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogical(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogical)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Byte.cs new file mode 100644 index 0000000000000..a2b01f27e9c26 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int16.cs new file mode 100644 index 0000000000000..22ab626099019 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int32.cs new file mode 100644 index 0000000000000..ee5505da9a894 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int64.cs new file mode 100644 index 0000000000000..1993f0d372b66 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.SByte.cs new file mode 100644 index 0000000000000..a345dd531ceac --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt16.cs new file mode 100644 index 0000000000000..78d1aeb0268a3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt32.cs new file mode 100644 index 0000000000000..62764e33365c8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt64.cs new file mode 100644 index 0000000000000..29dfe41903e7c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector128.UInt64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector128_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Byte.cs new file mode 100644 index 0000000000000..6900a082bf0e5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Int16.cs new file mode 100644 index 0000000000000..69ee56fceeaa1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Int32.cs new file mode 100644 index 0000000000000..5e2541004b9aa --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.SByte.cs new file mode 100644 index 0000000000000..94df562d5b2ed --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.UInt16.cs new file mode 100644 index 0000000000000..4c192beb8bd31 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector64_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.UInt32.cs new file mode 100644 index 0000000000000..69dac65171824 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRounded.Vector64.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRounded_Vector64_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32 testClass) + { + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRounded( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRounded), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRounded( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRounded(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRounded_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRounded(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRounded)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Byte.cs new file mode 100644 index 0000000000000..2cd0b999b78d4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int16.cs new file mode 100644 index 0000000000000..f30b6ec4362a5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int32.cs new file mode 100644 index 0000000000000..7e2955eeed17c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int64.cs new file mode 100644 index 0000000000000..6d998963744c6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.SByte.cs new file mode 100644 index 0000000000000..e40d14267f656 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt16.cs new file mode 100644 index 0000000000000..8229fd275f561 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt32.cs new file mode 100644 index 0000000000000..7521227343c5f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt64.cs new file mode 100644 index 0000000000000..ec46a3264433f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector128.UInt64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector128_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Byte.cs new file mode 100644 index 0000000000000..efb2d9b2233a0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Int16.cs new file mode 100644 index 0000000000000..200aad4b36ba9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Int32.cs new file mode 100644 index 0000000000000..6774c82376837 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.SByte.cs new file mode 100644 index 0000000000000..ea82600c3c146 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.UInt16.cs new file mode 100644 index 0000000000000..c88b0d3b534b7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector64_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.UInt32.cs new file mode 100644 index 0000000000000..051dd2eb1ef1e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturate.Vector64.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturate_Vector64_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturate_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturate( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturateScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturateScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..bc197aa8ba534 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturateScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64(); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturateScalar.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturateScalar.Vector64.UInt64.cs new file mode 100644 index 0000000000000..b4ac5ec3e07f9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedSaturateScalar.Vector64.UInt64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedSaturateScalar_Vector64_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64(); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedSaturateScalar_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..64738a692c27d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64(); + var result = AdvSimd.ShiftLogicalRoundedScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRounded(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedScalar.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedScalar.Vector64.UInt64.cs new file mode 100644 index 0000000000000..2730747125f70 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalRoundedScalar.Vector64.UInt64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalRoundedScalar_Vector64_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalRoundedScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalRoundedScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalRoundedScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalRoundedScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalRoundedScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64(); + var result = AdvSimd.ShiftLogicalRoundedScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalRoundedScalar_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalRoundedScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalRounded(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalRoundedScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Byte.cs new file mode 100644 index 0000000000000..4ebbb7b4b57dc --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Byte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int16.cs new file mode 100644 index 0000000000000..d58b5729da45c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int32.cs new file mode 100644 index 0000000000000..7343fdb20232d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int64.cs new file mode 100644 index 0000000000000..a5e0dd7d875cb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.Int64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.SByte.cs new file mode 100644 index 0000000000000..b6943048c6175 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pClsVar1)), + AdvSimd.LoadVector128((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(pFld1)), + AdvSimd.LoadVector128((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((SByte*)(&test._fld1)), + AdvSimd.LoadVector128((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt16.cs new file mode 100644 index 0000000000000..b3e37eea5b4f6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)), + AdvSimd.LoadVector128((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(pFld1)), + AdvSimd.LoadVector128((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)), + AdvSimd.LoadVector128((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt32.cs new file mode 100644 index 0000000000000..1ed51fb67edc0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)), + AdvSimd.LoadVector128((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(pFld1)), + AdvSimd.LoadVector128((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)), + AdvSimd.LoadVector128((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt64.cs new file mode 100644 index 0000000000000..1c43ef1a55eba --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector128.UInt64.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector128_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Byte.cs new file mode 100644 index 0000000000000..e44da8d4c8a59 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Byte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector64_Byte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, SByte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Byte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] left, SByte[] right, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Int16.cs new file mode 100644 index 0000000000000..00e63b170038c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Int16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector64_Int16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Int32.cs new file mode 100644 index 0000000000000..699d531bccd70 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.Int32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector64_Int32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((Int32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.SByte.cs new file mode 100644 index 0000000000000..0001fd5a0afdf --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.SByte.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector64_SByte() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pClsVar1)), + AdvSimd.LoadVector64((SByte*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(pFld1)), + AdvSimd.LoadVector64((SByte*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((SByte*)(&test._fld1)), + AdvSimd.LoadVector64((SByte*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.UInt16.cs new file mode 100644 index 0000000000000..c58411177c5fb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.UInt16.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector64_UInt16() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)), + AdvSimd.LoadVector64((Int16*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(pFld1)), + AdvSimd.LoadVector64((Int16*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)), + AdvSimd.LoadVector64((Int16*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] left, Int16[] right, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.UInt32.cs new file mode 100644 index 0000000000000..91e08ee024806 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturate.Vector64.UInt32.cs @@ -0,0 +1,530 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturate_Vector64_UInt32() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32 testClass) + { + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturate( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturate), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturate( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)), + AdvSimd.LoadVector64((Int32*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturate(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturate_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturate(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(pFld1)), + AdvSimd.LoadVector64((Int32*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturate( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)), + AdvSimd.LoadVector64((Int32*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] left, Int32[] right, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturate)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturateScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturateScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..4d9371ef77e55 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturateScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64(); + var result = AdvSimd.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturateScalar.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturateScalar.Vector64.UInt64.cs new file mode 100644 index 0000000000000..337a8d3e6c3e4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalSaturateScalar.Vector64.UInt64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalSaturateScalar_Vector64_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalSaturateScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalSaturateScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalSaturateScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalSaturateScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64(); + var result = AdvSimd.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalSaturateScalar_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalSaturateScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturateScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalSaturateScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalSaturateScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalScalar.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalScalar.Vector64.Int64.cs new file mode 100644 index 0000000000000..558309f83f7d7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalScalar.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalScalar_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64 testClass) + { + var result = AdvSimd.ShiftLogicalScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64(); + var result = AdvSimd.ShiftLogicalScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogical(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalScalar.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalScalar.Vector64.UInt64.cs new file mode 100644 index 0000000000000..32852fe910875 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftLogicalScalar.Vector64.UInt64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftLogicalScalar_Vector64_UInt64() + { + var test = new SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, Int64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64 testClass) + { + var result = AdvSimd.ShiftLogicalScalar(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftLogicalScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftLogicalScalar), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftLogicalScalar( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftLogicalScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftLogicalScalar(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64(); + var result = AdvSimd.ShiftLogicalScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__ShiftLogicalScalar_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftLogicalScalar(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalScalar(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, Int64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftLogical(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftLogicalScalar)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..4e3319ae8f00f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..fe035aa7fccdd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..26f054d9c91a2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..da629e612199e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..a320af6aca1f4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..dd54b73ec1fa5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..679ec212fd4a0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmetic.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmetic_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmetic( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmetic), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmetic( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmetic(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmetic_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmetic(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmetic( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmetic)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..f6cfec500ddd5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..a649bbe23ad9f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..59d05eb5e6f1a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.Int64.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector128_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..647925c244f7e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..1c3c5188783bd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector64_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..6b88a50c83c9e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector64_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..a965bf1f6fcb3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAdd.Vector64.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAdd_Vector64_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAdd_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAddScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAddScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..20967cdf7a39e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticAddScalar.Vector64.Int64.1.cs @@ -0,0 +1,423 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticAddScalar_Vector64_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticAddScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticAddScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticAddScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticAddScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticAddScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticAddScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticAddScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticAddScalar( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticAddScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticAdd(firstOp[0], secondOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticAddScalar)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..2413bc6b2ba11 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..7eef60a65ab6c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..f0e6ad42ea508 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..2fb415b1ae312 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..25f65d74f4846 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..b13144c8dd51d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..693d0330e6986 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Int16[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Int16[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..a11c4073481c4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int32[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Int32[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..12b9fe456195d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUnsignedUpper.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int64[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, Int64[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUnsignedUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..effa7d9d61c46 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..ce6c7ed79fdd7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..0679af81a644e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticNarrowingSaturateUpper.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..89555ea94254d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..217904fb6db4b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..e4bd6b739214b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..d3efbc420189b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..9dba14a59013a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..fdd6d7d9dc639 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..8b2536f5443fd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRounded.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRounded_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRounded_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRounded( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..f914cf3643e28 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..350750d981309 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..16f6b29e7c9e8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.Int64.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector128_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..8dd2c523ddae2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..8a5a35b900b6c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector64_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..cb541c555c574 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector64_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..7b56cc89de3c5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAdd.Vector64.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAdd_Vector64_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAdd_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAddScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAddScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..fab88648a9b2e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedAddScalar.Vector64.Int64.1.cs @@ -0,0 +1,423 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRoundedAdd(firstOp[0], secondOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedAddScalar)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..d348c65cedd45 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..50550ce9104c1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..f2466add87772 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..cc8565df8d209 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..d5f79e43412fe --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..67dbbf7cb4db9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..b78b53582fda7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Int16[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Int16[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..426b85cab078b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, Int32[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Int32[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..bab5e30db1bd3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, Int64[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, Int64[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..43a8740b116b0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..3b1ee352ffcb1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..4e185da5d4181 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedNarrowingSaturateUpper.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..d4c91308c4484 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticRoundedScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticRoundedScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticRoundedScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticRoundedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticRoundedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticRoundedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticRoundedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticRoundedScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticRoundedScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticRoundedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmeticRounded(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticRoundedScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..0bad044604de1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightArithmeticScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightArithmeticScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightArithmeticScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightArithmeticScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightArithmeticScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightArithmeticScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightArithmeticScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightArithmeticScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightArithmeticScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightArithmeticScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightArithmeticScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightArithmeticScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightArithmetic(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightArithmeticScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..23729809ef4ea --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..2f0d94b5684b4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..4e46a2a8f38f3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..ccf01b612b3c8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..72d2dff64eeeb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..8aa45d8f47147 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..9bf9e8fec1790 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt64.1.cs new file mode 100644 index 0000000000000..446fa4cf0889a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector128.UInt64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector128_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector128_UInt64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..ade6a58e16b82 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..c6d9f765d8206 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..cb700766e8946 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..764ca4d3e6312 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..8fad7e0be9070 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..e979a7d7ce6e9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogical.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogical_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogical( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogical), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogical( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogical(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogical_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogical(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogical( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogical)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..d5acb54a342d1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..1478fae32d881 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..f0194aafc6ef8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..806d40762d425 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.Int64.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..f63edb600924e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..26aa47a7e2dc7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..8dc3c3e367d11 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt64.1.cs new file mode 100644 index 0000000000000..96703c835b70c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector128.UInt64.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector128_UInt64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector128_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] secondOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..6ebb0db2d3e09 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector64_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..b0629b1e843d8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector64_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..bc9794e058727 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector64_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..9e0306dd55dcd --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector64_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..5e8f29029f7aa --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector64_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..daeee69415c29 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAdd.Vector64.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAdd_Vector64_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAdd( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAdd_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAddScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAddScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..f626835fc6c80 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAddScalar.Vector64.Int64.1.cs @@ -0,0 +1,423 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAddScalar_Vector64_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAddScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAddScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAddScalar( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightLogicalAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalAdd(firstOp[0], secondOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAddScalar)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAddScalar.Vector64.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAddScalar.Vector64.UInt64.1.cs new file mode 100644 index 0000000000000..d03bd9052dd66 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalAddScalar.Vector64.UInt64.1.cs @@ -0,0 +1,423 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalAddScalar_Vector64_UInt64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_UInt64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalAddScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalAddScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalAddScalar( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalAddScalar_Vector64_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] secondOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalAdd(firstOp[0], secondOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalAddScalar)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..16fad752e05f4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..34b14eb6cd3b3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..852862ee7d409 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..57bb8893ca506 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..4508eb9a005a6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..7a94c47c21f05 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingLower_Vector64_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..7f5dc434b8685 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..aae58ce73f2a4 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..a8068ef4cad65 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..64e843030bc48 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..3b5795724645b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..eeb668d918b3d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..635790706e213 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, UInt16[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..d711d91384e15 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..fb3922be3813c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..c961d2f62cbcf --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..9be98e796867b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt32[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..4d002a582247e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingSaturateUpper.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt64[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..da2d8dc456c45 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingUpper_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, UInt16[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..74e1b9423981a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingUpper_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..84d216eabb414 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingUpper_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..e4733c2473bc8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingUpper_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..96c09e59c8f87 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt32[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..7242b26c4f1b2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalNarrowingUpper.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt64[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..a05c067ffb061 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..31f296e8222b7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..38a7d2ce38d11 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..e90d9eb023e3a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.Int64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_Int64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..2634b2403d767 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..6dae0d74e01fb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..c3cf5d1549f42 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt64.1.cs new file mode 100644 index 0000000000000..c82471766d7cc --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector128.UInt64.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector128_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector128_UInt64_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..c58b5475c7826 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Byte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Byte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Byte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray = new Byte[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..2cdf79c7a1f0f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..2acebaf78c567 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_Int32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..70c35c236dc33 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_SByte_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((SByte*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((SByte*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray = new SByte[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..4dce61b5e8598 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt16_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..49a59f1782dad --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRounded.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRounded_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRounded( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRounded), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRounded(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRounded_Vector64_UInt32_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRounded(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRounded( + AdvSimd.LoadVector64((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRounded)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..5ae6329b39111 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..f235a22a9c496 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..9e450700e34f0 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int64.1.cs new file mode 100644 index 0000000000000..51c1822310817 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.Int64.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_Int64_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..16df705fe083f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..6a96d773637e7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..89c7ff5e8a109 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt64.1.cs new file mode 100644 index 0000000000000..1c72cd0d481e2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector128.UInt64.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector128_UInt64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector128), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector128_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] secondOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector128.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..0a86b96dcfe61 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector64_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, Byte[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static Byte[] _data2 = new Byte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + Byte[] inArray2 = new Byte[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, Byte[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..e576757b44c44 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector64_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int16[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..6549868f8e13e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector64_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int32[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..7d835b05b6d39 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector64_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, SByte[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static SByte[] _data2 = new SByte[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + SByte[] inArray2 = new SByte[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, SByte[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..dedaac14dda3e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector64_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt16[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..01774f2655abc --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAdd.Vector64.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAdd_Vector64_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAdd), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAdd_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAdd(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAdd(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt32[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAdd)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAddScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAddScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..a959472163435 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAddScalar.Vector64.Int64.1.cs @@ -0,0 +1,423 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] secondOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[0], secondOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAddScalar)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAddScalar.Vector64.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAddScalar.Vector64.UInt64.1.cs new file mode 100644 index 0000000000000..5211283aa4848 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedAddScalar.Vector64.UInt64.1.cs @@ -0,0 +1,423 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedAddScalar), new Type[] { typeof(Vector64), typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedAddScalar(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector64 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] secondOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRoundedAdd(firstOp[0], secondOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedAddScalar)}(Vector64.1, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..9d870d5e424ed --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..5f25720d78acb --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..d11de0aeaa62f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..2548dc60a827c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..2d1123813c1f8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..d872562d59d86 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingLower( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Byte.1.cs new file mode 100644 index 0000000000000..3d52447cf9a04 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Byte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray, Byte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static UInt16[] _data = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray = new UInt16[Op1ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int16.1.cs new file mode 100644 index 0000000000000..ee9b1741fa829 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray, Int16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int32[] _data = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray = new Int32[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int32.1.cs new file mode 100644 index 0000000000000..9baab4e0f4950 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.Int32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.SByte.1.cs new file mode 100644 index 0000000000000..c4e1483ad181d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.SByte.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray, SByte[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static Int16[] _data = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((Int16*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray = new Int16[Op1ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt16.1.cs new file mode 100644 index 0000000000000..435f4db3c6932 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt16.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray, UInt16[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt32[] _data = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt32*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray = new UInt32[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt32.1.cs new file mode 100644 index 0000000000000..55728404f1147 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateLower.Vector64.UInt32.1.cs @@ -0,0 +1,500 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt32[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1 testClass) + { + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector128 _clsVar; + + private Vector128 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower), new Type[] { typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1(); + + fixed (Vector128* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower( + AdvSimd.LoadVector128((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateLower)}(Vector128, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..01298deaf16ab --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, UInt16[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..e3224aaedb025 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..c8855546345e2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..6fd123737b4c1 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..4a500aac8380d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt32[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..572bf22ff0834 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingSaturateUpper.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt64[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingSaturateUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Byte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Byte.1.cs new file mode 100644 index 0000000000000..ab9fd0abfbf3d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Byte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, UInt16[] inArray2, Byte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly byte Imm = 1; + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + private static UInt16[] _data2 = new UInt16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, _data2, new Byte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] inArray2 = new UInt16[Op2ElementCount]; + Byte[] outArray = new Byte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, Byte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int16.1.cs new file mode 100644 index 0000000000000..790ad2d1fb5f7 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] inArray2, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly byte Imm = 1; + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + private static Int32[] _data2 = new Int32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, _data2, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] inArray2 = new Int32[Op2ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int32.1.cs new file mode 100644 index 0000000000000..d1da09400aa09 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.Int32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] inArray2, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly byte Imm = 1; + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.SByte.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.SByte.1.cs new file mode 100644 index 0000000000000..c909836b973bf --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.SByte.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] inArray2, SByte[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly byte Imm = 1; + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + private static Int16[] _data2 = new Int16[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, _data2, new SByte[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] inArray2 = new Int16[Op2ElementCount]; + SByte[] outArray = new SByte[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] secondOp, SByte[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt16.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt16.1.cs new file mode 100644 index 0000000000000..aebf41292401d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt16.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt32[] inArray2, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly byte Imm = 1; + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + private static UInt32[] _data2 = new UInt32[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, _data2, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] inArray2 = new UInt32[Op2ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt32.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt32.1.cs new file mode 100644 index 0000000000000..17296820b88b8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedNarrowingUpper.Vector128.UInt32.1.cs @@ -0,0 +1,416 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1() + { + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt64[] inArray2, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly byte Imm = 1; + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector128 _clsVar2; + + private Vector64 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper( + _clsVar1, + _clsVar2, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var secondOp = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(_fld1, _fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedNarrowingUpper(test._fld1, test._fld2, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, Vector128 secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedNarrowingUpper)}(Vector64.1, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..927ae9381968b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRounded(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedScalar.Vector64.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedScalar.Vector64.UInt64.1.cs new file mode 100644 index 0000000000000..ea06b0df0464d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalRoundedScalar.Vector64.UInt64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalRoundedScalar_Vector64_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalRoundedScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalRoundedScalar_Vector64_UInt64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalRoundedScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalRoundedScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogicalRounded(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalRoundedScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalScalar.Vector64.Int64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalScalar.Vector64.Int64.1.cs new file mode 100644 index 0000000000000..033371510253a --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalScalar.Vector64.Int64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalScalar_Vector64_Int64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray, Int64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly byte Imm = 1; + + private static Int64[] _data = new Int64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((Int64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1(); + var result = AdvSimd.ShiftRightLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_Int64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((Int64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((Int64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray = new Int64[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogical(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalScalar.Vector64.UInt64.1.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalScalar.Vector64.UInt64.1.cs new file mode 100644 index 0000000000000..1a5d9712e937b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ShiftRightLogicalScalar.Vector64.UInt64.1.cs @@ -0,0 +1,507 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ShiftRightLogicalScalar_Vector64_UInt64_1() + { + var test = new ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1 + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray, UInt64[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1 testClass) + { + var result = AdvSimd.ShiftRightLogicalScalar(_fld, 1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1 testClass) + { + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 8; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly byte Imm = 1; + + private static UInt64[] _data = new UInt64[Op1ElementCount]; + + private static Vector64 _clsVar; + + private Vector64 _fld; + + private DataTable _dataTable; + + static ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + } + + public ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld), ref Unsafe.As(ref _data[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ShiftRightLogicalScalar( + Unsafe.Read>(_dataTable.inArrayPtr), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArrayPtr), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ShiftRightLogicalScalar), new Type[] { typeof(Vector64), typeof(byte) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)), + (byte)1 + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector64)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ShiftRightLogicalScalar( + _clsVar, + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar = &_clsVar) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pClsVar)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); + var result = AdvSimd.ShiftRightLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArrayPtr)); + var result = AdvSimd.ShiftRightLogicalScalar(firstOp, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1(); + var result = AdvSimd.ShiftRightLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new ImmUnaryOpTest__ShiftRightLogicalScalar_Vector64_UInt64_1(); + + fixed (Vector64* pFld = &test._fld) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ShiftRightLogicalScalar(_fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld = &_fld) + { + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(pFld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalScalar(test._fld, 1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ShiftRightLogicalScalar( + AdvSimd.LoadVector64((UInt64*)(&test._fld)), + 1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray = new UInt64[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.ShiftRightLogical(firstOp[0], Imm) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (result[i] != 0) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ShiftRightLogicalScalar)}(Vector64, 1): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.Int16.cs new file mode 100644 index 0000000000000..56f22324ee1d6 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.Int16.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void SignExtendWideningLower_Vector64_Int16() + { + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16 testClass) + { + var result = AdvSimd.SignExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.SignExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.SignExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.SignExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.SignExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16(); + var result = AdvSimd.SignExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.SignExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.SignExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SignExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.Int32.cs new file mode 100644 index 0000000000000..2a4f37f3de22c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.Int32.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void SignExtendWideningLower_Vector64_Int32() + { + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32 testClass) + { + var result = AdvSimd.SignExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.SignExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.SignExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.SignExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.SignExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32(); + var result = AdvSimd.SignExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.SignExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.SignExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SignExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.SByte.cs new file mode 100644 index 0000000000000..6e3505931d333 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningLower.Vector64.SByte.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void SignExtendWideningLower_Vector64_SByte() + { + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte testClass) + { + var result = AdvSimd.SignExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.SignExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.SignExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.SignExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.SignExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte(); + var result = AdvSimd.SignExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__SignExtendWideningLower_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.SignExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.SignExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SignExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.Int16.cs new file mode 100644 index 0000000000000..ecfa8a20c99ba --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.Int16.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void SignExtendWideningUpper_Vector128_Int16() + { + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16 testClass) + { + var result = AdvSimd.SignExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.SignExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.SignExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.SignExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.SignExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16(); + var result = AdvSimd.SignExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.SignExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.SignExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SignExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.Int32.cs new file mode 100644 index 0000000000000..67de15d90c51b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.Int32.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void SignExtendWideningUpper_Vector128_Int32() + { + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32 testClass) + { + var result = AdvSimd.SignExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.SignExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.SignExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.SignExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.SignExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32(); + var result = AdvSimd.SignExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.SignExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.SignExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SignExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.SByte.cs new file mode 100644 index 0000000000000..7089ef21d2818 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SignExtendWideningUpper.Vector128.SByte.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void SignExtendWideningUpper_Vector128_SByte() + { + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte testClass) + { + var result = AdvSimd.SignExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.SignExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SignExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.SignExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.SignExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.SignExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte(); + var result = AdvSimd.SignExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__SignExtendWideningUpper_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.SignExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.SignExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.SignExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SignExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Byte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Byte.cs index 964bdb8fb0bf0..7c14bab8bceda 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowLower_Vector64_Byte() + private static void SubtractHighNarrowingLower_Vector64_Byte() { - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowLower_Vector64_Byte() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte + public sealed unsafe class SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHig private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte() + static SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte() + public SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte(); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Byte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Int16.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Int16.cs index e39162ea8e3ff..35a4643252630 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowLower_Vector64_Int16() + private static void SubtractHighNarrowingLower_Vector64_Int16() { - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowLower_Vector64_Int16() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16 + public sealed unsafe class SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHig private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16() + static SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16() + public SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16(); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Int32.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Int32.cs index 4ca831f705a8b..b724f5789340a 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowLower_Vector64_Int32() + private static void SubtractHighNarrowingLower_Vector64_Int32() { - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowLower_Vector64_Int32() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32 + public sealed unsafe class SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHig private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32() + static SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32() + public SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32(); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_Int32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.SByte.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.SByte.cs index 831ecd0cf389f..bec44ddbbe0cc 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowLower_Vector64_SByte() + private static void SubtractHighNarrowingLower_Vector64_SByte() { - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowLower_Vector64_SByte() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte + public sealed unsafe class SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHig private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte() + static SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte() + public SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte(); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_SByte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.UInt16.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.UInt16.cs index c69e2c8bd6eb9..cf9fcc96c1a4c 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowLower_Vector64_UInt16() + private static void SubtractHighNarrowingLower_Vector64_UInt16() { - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowLower_Vector64_UInt16() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16 + public sealed unsafe class SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHig private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16() + static SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16() + public SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16(); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.UInt32.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.UInt32.cs index 1c9c3025bc7cd..e1ae11ce88860 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowLower.Vector64.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingLower.Vector64.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowLower_Vector64_UInt32() + private static void SubtractHighNarrowingLower_Vector64_UInt32() { - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowLower_Vector64_UInt32() } } - public sealed unsafe class SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32 + public sealed unsafe class SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__AddReturningRoundedHig private DataTable _dataTable; - static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32() + static SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32() + public SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32(); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__AddReturningRoundedHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__SubtractHighNarrowingLower_Vector64_UInt32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Byte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Byte.cs index 1e2a7cb14bfbe..abd79e0284722 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowUpper_Vector128_Byte() + private static void SubtractHighNarrowingUpper_Vector128_Byte() { - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowUpper_Vector128_Byte() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte + public sealed unsafe class SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHi private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte() + static SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte() + public SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)), AdvSimd.LoadVector128((UInt16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte(); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Byte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)), AdvSimd.LoadVector128((UInt16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Int16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Int16.cs index d9c07e12e15c6..35c625d971cf1 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowUpper_Vector128_Int16() + private static void SubtractHighNarrowingUpper_Vector128_Int16() { - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowUpper_Vector128_Int16() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16 + public sealed unsafe class SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHi private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16() + static SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16() + public SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)), AdvSimd.LoadVector128((Int32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16(); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)), AdvSimd.LoadVector128((Int32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Int32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Int32.cs index a16ee2d136605..d31f07ce3f91f 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowUpper_Vector128_Int32() + private static void SubtractHighNarrowingUpper_Vector128_Int32() { - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowUpper_Vector128_Int32() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32 + public sealed unsafe class SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHi private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32() + static SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32() + public SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)), AdvSimd.LoadVector128((Int64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32(); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_Int32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)), AdvSimd.LoadVector128((Int64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.SByte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.SByte.cs index cf1a0a0d823d3..c1f3e06e1e84b 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowUpper_Vector128_SByte() + private static void SubtractHighNarrowingUpper_Vector128_SByte() { - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowUpper_Vector128_SByte() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte + public sealed unsafe class SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHi private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte() + static SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte() + public SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)), AdvSimd.LoadVector128((Int16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte(); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_SByte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)), AdvSimd.LoadVector128((Int16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.UInt16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.UInt16.cs index 70e20fec0f4f0..2ce1511a3bcc5 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowUpper_Vector128_UInt16() + private static void SubtractHighNarrowingUpper_Vector128_UInt16() { - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowUpper_Vector128_UInt16() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16 + public sealed unsafe class SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHi private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16() + static SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16( Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16() + public SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)), AdvSimd.LoadVector128((UInt32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16(); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)), AdvSimd.LoadVector128((UInt32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.UInt32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.UInt32.cs index 91f4bd718438b..bb378397a8758 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/AddReturningRoundedHighNarrowUpper.Vector128.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractHighNarrowingUpper.Vector128.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void AddReturningRoundedHighNarrowUpper_Vector128_UInt32() + private static void SubtractHighNarrowingUpper_Vector128_UInt32() { - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void AddReturningRoundedHighNarrowUpper_Vector128_UInt32() } } - public sealed unsafe class SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32 + public sealed unsafe class SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32 testClass) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__AddReturningRoundedHi private DataTable _dataTable; - static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32() + static SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32( Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32() + public SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.AddReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)), AdvSimd.LoadVector128((UInt64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32(); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__AddReturningRoundedHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__SubtractHighNarrowingUpper_Vector128_UInt32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.AddReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)), AdvSimd.LoadVector128((UInt64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.AddReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Byte.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Byte.cs index 5d8bd3f85dc95..4eac8fc9b11c0 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowLower_Vector64_Byte() + private static void SubtractRoundedHighNarrowingLower_Vector64_Byte() { - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowLower_Vector64_Byte() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte + public sealed unsafe class SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRound private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte() + static SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte() + public SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte(); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Byte(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Byte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt16[] left, UInt16[] right, Byte[] result, [Calle if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Int16.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Int16.cs index 461a9e67c239c..a538bca9192be 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowLower_Vector64_Int16() + private static void SubtractRoundedHighNarrowingLower_Vector64_Int16() { - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowLower_Vector64_Int16() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16 + public sealed unsafe class SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRound private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16() + static SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int1 Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16() + public SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16(); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int16(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int32[] left, Int32[] right, Int16[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Int32.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Int32.cs index 620812e188efc..e2c23aad0121d 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowLower_Vector64_Int32() + private static void SubtractRoundedHighNarrowingLower_Vector64_Int32() { - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowLower_Vector64_Int32() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32 + public sealed unsafe class SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRound private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32() + static SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int3 Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32() + public SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32(); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_Int32(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_Int32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int64*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int64[] left, Int64[] right, Int32[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.SByte.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.SByte.cs index 910c8781999c7..e1c53772276b8 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowLower_Vector64_SByte() + private static void SubtractRoundedHighNarrowingLower_Vector64_SByte() { - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowLower_Vector64_SByte() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte + public sealed unsafe class SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRound private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte() + static SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByt Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte() + public SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte(); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_SByte(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_SByte(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(Int16[] left, Int16[] right, SByte[] result, [Caller if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.UInt16.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.UInt16.cs index a94328c85d3f6..d83de1959b87f 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowLower_Vector64_UInt16() + private static void SubtractRoundedHighNarrowingLower_Vector64_UInt16() { - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowLower_Vector64_UInt16() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16 + public sealed unsafe class SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRound private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16() + static SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16() + public SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16(); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt16(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt16(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt32[] left, UInt32[] right, UInt16[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.UInt32.cs similarity index 89% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.UInt32.cs index 6f720f8dc5da8..ea17396a4306f 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowLower.Vector64.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingLower.Vector64.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowLower_Vector64_UInt32() + private static void SubtractRoundedHighNarrowingLower_Vector64_UInt32() { - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowLower_Vector64_UInt32() } } - public sealed unsafe class SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32 + public sealed unsafe class SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32 { private struct DataTable { @@ -182,20 +182,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32 testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -223,7 +223,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractReturningRound private DataTable _dataTable; - static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32() + static SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -231,7 +231,7 @@ static SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32() + public SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32() { Succeeded = true; @@ -253,7 +253,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -266,7 +266,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) ); @@ -279,7 +279,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -293,7 +293,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingLower), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) @@ -307,7 +307,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( _clsVar1, _clsVar2 ); @@ -323,7 +323,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)) ); @@ -339,7 +339,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -351,7 +351,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(op1, op2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(op1, op2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, _dataTable.outArrayPtr); @@ -361,8 +361,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32(); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -372,12 +372,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__SubtractReturningRoundedHighNarrowLower_Vector64_UInt32(); + var test = new SimpleBinaryOpTest__SubtractRoundedHighNarrowingLower_Vector64_UInt32(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -391,7 +391,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(_fld1, _fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -404,7 +404,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)) ); @@ -419,7 +419,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower(test._fld1, test._fld2); + var result = AdvSimd.SubtractRoundedHighNarrowingLower(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -430,7 +430,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowLower( + var result = AdvSimd.SubtractRoundedHighNarrowingLower( AdvSimd.LoadVector128((UInt64*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)) ); @@ -508,7 +508,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]) + if (Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]) { succeeded = false; break; @@ -517,7 +517,7 @@ private void ValidateResult(UInt64[] left, UInt64[] right, UInt32[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowLower)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingLower)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Byte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Byte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Byte.cs index 562d71f9d67d0..2dd7c3918c6e0 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Byte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowUpper_Vector128_Byte() + private static void SubtractRoundedHighNarrowingUpper_Vector128_Byte() { - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowUpper_Vector128_Byte() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte + public sealed unsafe class SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoun private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte() + static SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_By Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte() + public SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pClsVar1)), AdvSimd.LoadVector128((UInt16*)(pClsVar2)), AdvSimd.LoadVector128((UInt16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte(); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Byte(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Byte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(pFld1)), AdvSimd.LoadVector128((UInt16*)(pFld2)), AdvSimd.LoadVector128((UInt16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Byte*)(&test._fld1)), AdvSimd.LoadVector128((UInt16*)(&test._fld2)), AdvSimd.LoadVector128((UInt16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] secondOp, UInt16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Int16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Int16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Int16.cs index ce3bb0f3705f8..73b854f868af5 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Int16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Int16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowUpper_Vector128_Int16() + private static void SubtractRoundedHighNarrowingUpper_Vector128_Int16() { - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowUpper_Vector128_Int16() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16 + public sealed unsafe class SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoun private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16() + static SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_In Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16() + public SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pClsVar1)), AdvSimd.LoadVector128((Int32*)(pClsVar2)), AdvSimd.LoadVector128((Int32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16(); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int16(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(pFld1)), AdvSimd.LoadVector128((Int32*)(pFld2)), AdvSimd.LoadVector128((Int32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int16*)(&test._fld1)), AdvSimd.LoadVector128((Int32*)(&test._fld2)), AdvSimd.LoadVector128((Int32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int16[] firstOp, Int32[] secondOp, Int32[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Int32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Int32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Int32.cs index 773665aeb6d1e..4ab22c7a31f63 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.Int32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.Int32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowUpper_Vector128_Int32() + private static void SubtractRoundedHighNarrowingUpper_Vector128_Int32() { - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowUpper_Vector128_Int32() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32 + public sealed unsafe class SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoun private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32() + static SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_In Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32() + public SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pClsVar1)), AdvSimd.LoadVector128((Int64*)(pClsVar2)), AdvSimd.LoadVector128((Int64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32(); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_Int32(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_Int32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(pFld1)), AdvSimd.LoadVector128((Int64*)(pFld2)), AdvSimd.LoadVector128((Int64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((Int32*)(&test._fld1)), AdvSimd.LoadVector128((Int64*)(&test._fld2)), AdvSimd.LoadVector128((Int64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(Int32[] firstOp, Int64[] secondOp, Int64[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.SByte.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.SByte.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.SByte.cs index bdc097d7fb5f9..e2ecb71bfc068 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.SByte.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.SByte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowUpper_Vector128_SByte() + private static void SubtractRoundedHighNarrowingUpper_Vector128_SByte() { - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowUpper_Vector128_SByte() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte + public sealed unsafe class SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoun private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte() + static SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SB Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte() + public SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pClsVar1)), AdvSimd.LoadVector128((Int16*)(pClsVar2)), AdvSimd.LoadVector128((Int16*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte(); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_SByte(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_SByte(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(pFld1)), AdvSimd.LoadVector128((Int16*)(pFld2)), AdvSimd.LoadVector128((Int16*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((SByte*)(&test._fld1)), AdvSimd.LoadVector128((Int16*)(&test._fld2)), AdvSimd.LoadVector128((Int16*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(SByte[] firstOp, Int16[] secondOp, Int16[] thirdOp, if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.UInt16.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.UInt16.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.UInt16.cs index 03f61e4b9e4d5..3080f3c0002dd 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.UInt16.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16() + private static void SubtractRoundedHighNarrowingUpper_Vector128_UInt16() { - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16 + public sealed unsafe class SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoun private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16() + static SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UI Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16() + public SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pClsVar1)), AdvSimd.LoadVector128((UInt32*)(pClsVar2)), AdvSimd.LoadVector128((UInt32*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16(); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt16(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(pFld1)), AdvSimd.LoadVector128((UInt32*)(pFld2)), AdvSimd.LoadVector128((UInt32*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt16*)(&test._fld1)), AdvSimd.LoadVector128((UInt32*)(&test._fld2)), AdvSimd.LoadVector128((UInt32*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] secondOp, UInt32[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.UInt32.cs similarity index 90% rename from src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.UInt32.cs rename to src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.UInt32.cs index 2e1e1af8a603e..da9245113a140 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractReturningRoundedHighNarrowUpper.Vector128.UInt32.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/SubtractRoundedHighNarrowingUpper.Vector128.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.Arm { public static partial class Program { - private static void SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32() + private static void SubtractRoundedHighNarrowingUpper_Vector128_UInt32() { - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32(); if (test.IsSupported) { @@ -110,7 +110,7 @@ private static void SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32() } } - public sealed unsafe class SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32 + public sealed unsafe class SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32 { private struct DataTable { @@ -193,21 +193,21 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32 testClass) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32 testClass) + public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32 testClass) { fixed (Vector64* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -240,7 +240,7 @@ public void RunStructFldScenario_Load(SimpleTernaryOpTest__SubtractReturningRoun private DataTable _dataTable; - static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32() + static SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -250,7 +250,7 @@ static SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UI Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar3), ref Unsafe.As(ref _data3[0]), (uint)Unsafe.SizeOf>()); } - public SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32() + public SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32() { Succeeded = true; @@ -275,7 +275,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), Unsafe.Read>(_dataTable.inArray3Ptr) @@ -289,7 +289,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)) @@ -303,7 +303,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr), @@ -318,7 +318,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SubtractRoundedHighNarrowingUpper), new Type[] { typeof(Vector64), typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)), AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)), @@ -333,7 +333,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( _clsVar1, _clsVar2, _clsVar3 @@ -351,7 +351,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar2 = &_clsVar2) fixed (Vector128* pClsVar3 = &_clsVar3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pClsVar1)), AdvSimd.LoadVector128((UInt64*)(pClsVar2)), AdvSimd.LoadVector128((UInt64*)(pClsVar3)) @@ -369,7 +369,7 @@ public void RunLclVarScenario_UnsafeRead() var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); var op3 = Unsafe.Read>(_dataTable.inArray3Ptr); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -382,7 +382,7 @@ public void RunLclVarScenario_Load() var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); var op3 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray3Ptr)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(op1, op2, op3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(op1, op2, op3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); @@ -392,8 +392,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32(); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -403,13 +403,13 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleTernaryOpTest__SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32(); + var test = new SimpleTernaryOpTest__SubtractRoundedHighNarrowingUpper_Vector128_UInt32(); fixed (Vector64* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) fixed (Vector128* pFld3 = &test._fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -424,7 +424,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(_fld1, _fld2, _fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(_fld1, _fld2, _fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); @@ -438,7 +438,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld2 = &_fld2) fixed (Vector128* pFld3 = &_fld3) { - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(pFld1)), AdvSimd.LoadVector128((UInt64*)(pFld2)), AdvSimd.LoadVector128((UInt64*)(pFld3)) @@ -454,7 +454,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper(test._fld1, test._fld2, test._fld3); + var result = AdvSimd.SubtractRoundedHighNarrowingUpper(test._fld1, test._fld2, test._fld3); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); @@ -465,7 +465,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = AdvSimd.SubtractReturningRoundedHighNarrowUpper( + var result = AdvSimd.SubtractRoundedHighNarrowingUpper( AdvSimd.LoadVector64((UInt32*)(&test._fld1)), AdvSimd.LoadVector128((UInt64*)(&test._fld2)), AdvSimd.LoadVector128((UInt64*)(&test._fld3)) @@ -548,7 +548,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO for (var i = 0; i < RetElementCount; i++) { - if (Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]) + if (Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]) { succeeded = false; break; @@ -557,7 +557,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] secondOp, UInt64[] thirdO if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractReturningRoundedHighNarrowUpper)}(Vector64, Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractRoundedHighNarrowingUpper)}(Vector64, Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Byte.cs new file mode 100644 index 0000000000000..0519407fbbd5e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Byte.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningLower_Vector64_Byte() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte testClass) + { + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Byte*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Byte(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Byte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Byte*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Int16.cs new file mode 100644 index 0000000000000..3a58cbf2e89ba --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Int16.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningLower_Vector64_Int16() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16 testClass) + { + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int16(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int16*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Int32.cs new file mode 100644 index 0000000000000..05205c7fbb449 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.Int32.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningLower_Vector64_Int32() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32 testClass) + { + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_Int32(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((Int32*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.SByte.cs new file mode 100644 index 0000000000000..9701cdda6d48c --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.SByte.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningLower_Vector64_SByte() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte testClass) + { + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_SByte(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((SByte*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.UInt16.cs new file mode 100644 index 0000000000000..94696f369d89d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.UInt16.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningLower_Vector64_UInt16() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16 testClass) + { + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt16*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt16*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt16(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt16*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.UInt32.cs new file mode 100644 index 0000000000000..d2a4a895d5265 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningLower.Vector64.UInt32.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningLower_Vector64_UInt32() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32 testClass) + { + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt32*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + + private static Vector64 _clsVar1; + + private Vector64 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningLower), new Type[] { typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningLower( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt32*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningLower(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningLower_Vector64_UInt32(); + + fixed (Vector64* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningLower(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningLower( + AdvSimd.LoadVector64((UInt32*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWidening(firstOp[i]) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningLower)}(Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Byte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Byte.cs new file mode 100644 index 0000000000000..07f995be11a61 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Byte.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningUpper_Vector128_Byte() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Byte[] inArray1, UInt16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte testClass) + { + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Byte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + + private static Byte[] _data1 = new Byte[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); } + _dataTable = new DataTable(_data1, new UInt16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Byte*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Byte(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Byte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Byte*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Byte[] inArray1 = new Byte[Op1ElementCount]; + UInt16[] outArray = new UInt16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Byte[] firstOp, UInt16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Int16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Int16.cs new file mode 100644 index 0000000000000..1feb2f0e43608 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Int16.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningUpper_Vector128_Int16() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int16[] inArray1, Int32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16 testClass) + { + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int32); + + private static Int16[] _data1 = new Int16[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); } + _dataTable = new DataTable(_data1, new Int32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int16(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int16*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int16[] inArray1 = new Int16[Op1ElementCount]; + Int32[] outArray = new Int32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int16[] firstOp, Int32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Int32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Int32.cs new file mode 100644 index 0000000000000..b007617f701f5 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.Int32.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningUpper_Vector128_Int32() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int32[] inArray1, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32 testClass) + { + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int32[] _data1 = new Int32[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); } + _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_Int32(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((Int32*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + Int32[] inArray1 = new Int32[Op1ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(Int32[] firstOp, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.SByte.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.SByte.cs new file mode 100644 index 0000000000000..dfa0e9e90e0cc --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.SByte.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningUpper_Vector128_SByte() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(SByte[] inArray1, Int16[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte testClass) + { + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(SByte); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int16); + + private static SByte[] _data1 = new SByte[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); } + _dataTable = new DataTable(_data1, new Int16[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_SByte(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((SByte*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + SByte[] inArray1 = new SByte[Op1ElementCount]; + Int16[] outArray = new Int16[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(SByte[] firstOp, Int16[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.UInt16.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.UInt16.cs new file mode 100644 index 0000000000000..0d471011a7b7b --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.UInt16.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningUpper_Vector128_UInt16() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt16[] inArray1, UInt32[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16 testClass) + { + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt16); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + + private static UInt16[] _data1 = new UInt16[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); } + _dataTable = new DataTable(_data1, new UInt32[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt16(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt16*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt16*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt16[] inArray1 = new UInt16[Op1ElementCount]; + UInt32[] outArray = new UInt32[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt16[] firstOp, UInt32[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.UInt32.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.UInt32.cs new file mode 100644 index 0000000000000..c35161443743d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/AdvSimd/ZeroExtendWideningUpper.Vector128.UInt32.cs @@ -0,0 +1,489 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void ZeroExtendWideningUpper_Vector128_UInt32() + { + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt32[] inArray1, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32 testClass) + { + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pFld1)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt32); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt32[] _data1 = new UInt32[Op1ElementCount]; + + private static Vector128 _clsVar1; + + private Vector128 _fld1; + + private DataTable _dataTable; + + static SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); } + _dataTable = new DataTable(_data1, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => AdvSimd.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = AdvSimd.ZeroExtendWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.ZeroExtendWideningUpper), new Type[] { typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper( + _clsVar1 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pClsVar1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)); + var result = AdvSimd.ZeroExtendWideningUpper(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleUnaryOpTest__ZeroExtendWideningUpper_Vector128_UInt32(); + + fixed (Vector128* pFld1 = &test._fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = AdvSimd.ZeroExtendWideningUpper(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + { + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt32*)(pFld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = AdvSimd.ZeroExtendWideningUpper( + AdvSimd.LoadVector128((UInt32*)(&test._fld1)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + UInt32[] inArray1 = new UInt32[Op1ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(UInt32[] firstOp, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if (Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.ZeroExtendWideningUpper)}(Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_r.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_r.csproj index 0742b17dadfe6..ee55253dbbb23 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_r.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_r.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_ro.csproj b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_ro.csproj index e4b915cd4e3f7..509b345bdc5ca 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_ro.csproj +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Aes_ro.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningLower.Vector64.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningLower.Vector64.Int64.cs new file mode 100644 index 0000000000000..3cba2406b3af3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningLower.Vector64.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningLower_Vector64_Int64() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64 testClass) + { + var result = Aes.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Aes.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Aes.PolynomialMultiplyWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Aes.PolynomialMultiplyWideningLower( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Int64*)(pClsVar1)), + AdvSimd.LoadVector64((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Aes.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr)); + var result = Aes.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64(); + var result = Aes.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_Int64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Aes.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Int64*)(pFld1)), + AdvSimd.LoadVector64((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((Int64*)(&test._fld1)), + AdvSimd.LoadVector64((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.PolynomialMultiplyWideningLo64(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWideningHi64(left[0], right[0]) != result[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Aes)}.{nameof(Aes.PolynomialMultiplyWideningLower)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningLower.Vector64.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningLower.Vector64.UInt64.cs new file mode 100644 index 0000000000000..9941f644a2dc2 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningLower.Vector64.UInt64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningLower_Vector64_UInt64() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector64 _fld1; + public Vector64 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64 testClass) + { + var result = Aes.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64 testClass) + { + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector64 _clsVar1; + private static Vector64 _clsVar2; + + private Vector64 _fld1; + private Vector64 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Aes.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Aes.PolynomialMultiplyWideningLower( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningLower), new Type[] { typeof(Vector64), typeof(Vector64) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Aes.PolynomialMultiplyWideningLower( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector64* pClsVar1 = &_clsVar1) + fixed (Vector64* pClsVar2 = &_clsVar2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((UInt64*)(pClsVar1)), + AdvSimd.LoadVector64((UInt64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Aes.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr)); + var result = Aes.PolynomialMultiplyWideningLower(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64(); + var result = Aes.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningLower_Vector64_UInt64(); + + fixed (Vector64* pFld1 = &test._fld1) + fixed (Vector64* pFld2 = &test._fld2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Aes.PolynomialMultiplyWideningLower(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector64* pFld1 = &_fld1) + fixed (Vector64* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((UInt64*)(pFld1)), + AdvSimd.LoadVector64((UInt64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningLower(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningLower( + AdvSimd.LoadVector64((UInt64*)(&test._fld1)), + AdvSimd.LoadVector64((UInt64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector64 op1, Vector64 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.PolynomialMultiplyWideningLo64(left[0], right[0]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWideningHi64(left[0], right[0]) != result[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Aes)}.{nameof(Aes.PolynomialMultiplyWideningLower)}(Vector64, Vector64): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningUpper.Vector128.Int64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningUpper.Vector128.Int64.cs new file mode 100644 index 0000000000000..72791aa51283d --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningUpper.Vector128.Int64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningUpper_Vector128_Int64() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64 testClass) + { + var result = Aes.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(Int64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(Int64); + + private static Int64[] _data1 = new Int64[Op1ElementCount]; + private static Int64[] _data2 = new Int64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); } + _dataTable = new DataTable(_data1, _data2, new Int64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Aes.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Aes.PolynomialMultiplyWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Aes.PolynomialMultiplyWideningUpper( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Int64*)(pClsVar1)), + AdvSimd.LoadVector128((Int64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Aes.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr)); + var result = Aes.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64(); + var result = Aes.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_Int64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Aes.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Int64*)(pFld1)), + AdvSimd.LoadVector128((Int64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((Int64*)(&test._fld1)), + AdvSimd.LoadVector128((Int64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + Int64[] inArray1 = new Int64[Op1ElementCount]; + Int64[] inArray2 = new Int64[Op2ElementCount]; + Int64[] outArray = new Int64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.PolynomialMultiplyWideningLo64(left[1], right[1]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWideningHi64(left[1], right[1]) != result[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Aes)}.{nameof(Aes.PolynomialMultiplyWideningUpper)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningUpper.Vector128.UInt64.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningUpper.Vector128.UInt64.cs new file mode 100644 index 0000000000000..bb4064cfa115e --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/PolynomialMultiplyWideningUpper.Vector128.UInt64.cs @@ -0,0 +1,537 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void PolynomialMultiplyWideningUpper_Vector128_UInt64() + { + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if (AdvSimd.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if (AdvSimd.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64 + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public Vector128 _fld1; + public Vector128 _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref testStruct._fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + return testStruct; + } + + public void RunStructFldScenario(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64 testClass) + { + var result = Aes.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load(SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64 testClass) + { + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)) + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = 16; + + private static readonly int Op1ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int Op2ElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + private static readonly int RetElementCount = Unsafe.SizeOf>() / sizeof(UInt64); + + private static UInt64[] _data1 = new UInt64[Op1ElementCount]; + private static UInt64[] _data2 = new UInt64[Op2ElementCount]; + + private static Vector128 _clsVar1; + private static Vector128 _clsVar2; + + private Vector128 _fld1; + private Vector128 _fld2; + + private DataTable _dataTable; + + static SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + } + + public SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _fld2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); } + _dataTable = new DataTable(_data1, _data2, new UInt64[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => Aes.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = Aes.PolynomialMultiplyWideningUpper( + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + Unsafe.Read>(_dataTable.inArray1Ptr), + Unsafe.Read>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof(Aes).GetMethod(nameof(Aes.PolynomialMultiplyWideningUpper), new Type[] { typeof(Vector128), typeof(Vector128) }) + .Invoke(null, new object[] { + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)), + AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, (Vector128)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = Aes.PolynomialMultiplyWideningUpper( + _clsVar1, + _clsVar2 + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed (Vector128* pClsVar1 = &_clsVar1) + fixed (Vector128* pClsVar2 = &_clsVar2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((UInt64*)(pClsVar1)), + AdvSimd.LoadVector128((UInt64*)(pClsVar2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read>(_dataTable.inArray2Ptr); + var result = Aes.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var op1 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)); + var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr)); + var result = Aes.PolynomialMultiplyWideningUpper(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64(); + var result = Aes.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new SimpleBinaryOpTest__PolynomialMultiplyWideningUpper_Vector128_UInt64(); + + fixed (Vector128* pFld1 = &test._fld1) + fixed (Vector128* pFld2 = &test._fld2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = Aes.PolynomialMultiplyWideningUpper(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed (Vector128* pFld1 = &_fld1) + fixed (Vector128* pFld2 = &_fld2) + { + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((UInt64*)(pFld1)), + AdvSimd.LoadVector128((UInt64*)(pFld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningUpper(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = Aes.PolynomialMultiplyWideningUpper( + AdvSimd.LoadVector128((UInt64*)(&test._fld1)), + AdvSimd.LoadVector128((UInt64*)(&test._fld2)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(Vector128 op1, Vector128 op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + UInt64[] inArray1 = new UInt64[Op1ElementCount]; + UInt64[] inArray2 = new UInt64[Op2ElementCount]; + UInt64[] outArray = new UInt64[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if (Helpers.PolynomialMultiplyWideningLo64(left[1], right[1]) != result[0]) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if (Helpers.PolynomialMultiplyWideningHi64(left[1], right[1]) != result[1]) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof(Aes)}.{nameof(Aes.PolynomialMultiplyWideningUpper)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Program.Aes.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Program.Aes.cs index fd0188702e40f..96b49b50943e3 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Program.Aes.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Aes/Program.Aes.cs @@ -16,6 +16,10 @@ static Program() ["Encrypt.Vector128.Byte"] = Encrypt_Vector128_Byte, ["InverseMixColumns.Vector128.Byte"] = InverseMixColumns_Vector128_Byte, ["MixColumns.Vector128.Byte"] = MixColumns_Vector128_Byte, + ["PolynomialMultiplyWideningLower.Vector64.Int64"] = PolynomialMultiplyWideningLower_Vector64_Int64, + ["PolynomialMultiplyWideningLower.Vector64.UInt64"] = PolynomialMultiplyWideningLower_Vector64_UInt64, + ["PolynomialMultiplyWideningUpper.Vector128.Int64"] = PolynomialMultiplyWideningUpper_Vector128_Int64, + ["PolynomialMultiplyWideningUpper.Vector128.UInt64"] = PolynomialMultiplyWideningUpper_Vector128_UInt64, }; } } diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx index c7bea91cb434a..50bc84cdbb522 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/GenerateTests.csx @@ -86,6 +86,12 @@ private const string SecureHashOpTest_ValidationLogic = @"{RetBaseType}[] expect private static readonly (string templateFileName, string outputTemplateName, Dictionary templateData)[] Templates = new[] { + ("_UnaryOpScalarTestTemplate.template", "DuplicateTest.template", new Dictionary { ["TemplateName"] = "Duplicate", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmUnaryOpTestTemplate.template", "ImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmUnaryOpTestTemplate.template", "VecImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmOpTestTemplate.template", "ImmOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmBinaryOpTestTemplate.template", "ImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmBinaryOpTestTemplate.template", "VecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), ("_TernaryOpTestTemplate.template", "VecTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), @@ -97,1199 +103,1655 @@ private static readonly (string templateFileName, string outputTemplateName, Dic ("_UnaryOpTestTemplate.template", "SecureHashUnOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), ("_BinaryOpTestTemplate.template", "SecureHashBinOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }) - }; private static readonly (string templateFileName, Dictionary templateData)[] AdvSimdInputs = new [] { - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Abs(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Abs(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AbsScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Abs(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AbsScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Abs(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Add(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Add(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AddPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAddScalar_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAddScalar_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningScalar_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWidening(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningScalar_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWidening(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningHighNarrowUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddReturningRoundedHighNarrowUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Add(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Add(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Add(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Add(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Byte_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int16_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int16_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int32_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int32_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int64_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_SByte_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt16_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt16_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt32_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt32_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt64_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "DivideScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Divide(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "DivideScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateResult"] = "BitConverter.SingleToInt32Bits(firstOp[ElementIndex]) != BitConverter.SingleToInt32Bits(result)"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Double_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["ValidateResult"] = "BitConverter.DoubleToInt64Bits(firstOp[ElementIndex]) != BitConverter.DoubleToInt64Bits(result)"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateResult"] = "BitConverter.SingleToInt32Bits(firstOp[ElementIndex]) != BitConverter.SingleToInt32Bits(result)"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowHigh_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowHigh_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowHigh_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowHigh_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowHigh_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowHigh_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.ExtractAndNarrowHigh(0, left, right, result)", ["ValidateRemainingResults"] = "Helpers.ExtractAndNarrowHigh(i, left, right, result)"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowLow_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "((SByte)firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowLow_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "((Int16)firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowLow_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "((Int32)firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowLow_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "((Byte)firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowLow_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "((UInt16)firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractAndNarrowLow_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractAndNarrowLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "((UInt32)firstOp[i]) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Double_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAdd_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAdd_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddNegatedScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAddNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddNegatedScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAddNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtract_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtract_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtract(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractNegatedScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtractNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractNegatedScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtractNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Insert(firstOp, ElementIndex, thirdOp, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Double_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Insert(firstOp, ElementIndex, thirdOp, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Insert(firstOp, ElementIndex, thirdOp, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Byte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Double", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Int16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Int32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Int64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_SByte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Single", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_UInt16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_UInt32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_UInt64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Byte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Double", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Int16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Int32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Int64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_SByte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Single", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_UInt16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_UInt32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_UInt64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumber_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumber_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumber(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumber(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumber_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumber_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumber(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumber(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "NegateScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "NegateScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x409e8000"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRecipEstimate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x409e8000"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRecipEstimate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x400e8000"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRSqrtEstimate(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x400e8000"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRSqrtEstimate(firstOp[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStep_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStep", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRSqrtStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStep_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRSqrtStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStep_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStep", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRecipStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStep_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRecipStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "SqrtScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "SqrtScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrow(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningHighNarrowUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrow(left[i], right[i]) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowUpper_Vector128_UInt16",["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractReturningRoundedHighNarrowUpper_Vector128_UInt32",["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractReturningRoundedHighNarrowUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractReturningRoundedHighNarrowUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Byte_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int16_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int16_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int32_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int32_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int64_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_SByte_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt16_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt16_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt32_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt32_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt64_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Abs(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Abs(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AbsScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Abs(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AbsScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Abs(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWidening(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningLowerAndAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpper(left, right, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceWideningUpperAndAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifferenceWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Add(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Add(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddHighNarrowingUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AddPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWidening_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWidening", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWidening(firstOp, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, i) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAddScalar_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningAndAddScalar_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningAndAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWideningAndAdd(left, right, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningScalar_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWidening(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseWideningScalar_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseWideningScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.AddPairwiseWidening(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "AddRoundedHighNarrowingUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturate_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Add(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Add(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Add(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Add(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningLower_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Byte_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int16_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int16_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int32_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int32_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_Int64_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_SByte_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt16_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt16_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt32_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt32_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddWideningUpper_Vector128_UInt64_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "And_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "BitwiseClear_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "BitwiseSelect_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThan(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThanOrEqual(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "DivideScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Divide(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "DivideScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_Byte_8", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "8", ["ValidateFirstResult"] = "result[0] != firstOp[8]", ["ValidateRemainingResults"] = "result[i] != firstOp[8]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_Int16_4", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "4", ["ValidateFirstResult"] = "result[0] != firstOp[4]", ["ValidateRemainingResults"] = "result[i] != firstOp[4]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_Int32_2", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "2", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "result[i] != firstOp[2]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_SByte_8", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "8", ["ValidateFirstResult"] = "result[0] != firstOp[8]", ["ValidateRemainingResults"] = "result[i] != firstOp[8]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_Single_2", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "2", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "result[i] != firstOp[2]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_UInt16_4", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "4", ["ValidateFirstResult"] = "result[0] != firstOp[4]", ["ValidateRemainingResults"] = "result[i] != firstOp[4]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector64_V128_UInt32_2", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "2", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "result[i] != firstOp[2]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_Byte_8", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "8", ["ValidateFirstResult"] = "result[0] != firstOp[8]", ["ValidateRemainingResults"] = "result[i] != firstOp[8]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_Int16_4", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "4", ["ValidateFirstResult"] = "result[0] != firstOp[4]", ["ValidateRemainingResults"] = "result[i] != firstOp[4]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_Int32_2", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "2", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "result[i] != firstOp[2]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_SByte_8", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "8", ["ValidateFirstResult"] = "result[0] != firstOp[8]", ["ValidateRemainingResults"] = "result[i] != firstOp[8]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_Single_2", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "2", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "result[i] != firstOp[2]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_UInt16_4", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "4", ["ValidateFirstResult"] = "result[0] != firstOp[4]", ["ValidateRemainingResults"] = "result[i] != firstOp[4]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_UInt32_2", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "2", ["ValidateFirstResult"] = "result[0] != firstOp[2]", ["ValidateRemainingResults"] = "result[i] != firstOp[2]" }), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Byte_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Int16_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Int32_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_SByte_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_Single_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_UInt16_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector64_UInt32_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Byte_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Int16_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Int32_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_SByte_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Single_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_UInt16_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_UInt32_31", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateResult"] = "BitConverter.SingleToInt32Bits(firstOp[ElementIndex]) != BitConverter.SingleToInt32Bits(result)"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Double_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["ValidateResult"] = "BitConverter.DoubleToInt64Bits(firstOp[ElementIndex]) != BitConverter.DoubleToInt64Bits(result)"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateResult"] = "BitConverter.SingleToInt32Bits(firstOp[ElementIndex]) != BitConverter.SingleToInt32Bits(result)"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("ExtractTest.template", new Dictionary { ["TestName"] = "Extract_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Extract", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["ValidateResult"] = "firstOp[ElementIndex] != result"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ExtractNarrowingUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ExtractNarrowingUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingUpper_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ExtractNarrowingUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.ExtractNarrowingUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.ExtractNarrowingUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingUpper_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.ExtractNarrowingUpper(left, right, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingLower_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ExtractNarrowing(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingLower_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ExtractNarrowing(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingLower_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ExtractNarrowing(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingLower_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.ExtractNarrowing(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingLower_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.ExtractNarrowing(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ExtractNarrowingLower_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.ExtractNarrowing(firstOp[i]) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Double_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("ExtractVectorTest.template", new Dictionary { ["TestName"] = "ExtractVector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["ValidateIterResult"] = "Helpers.ExtractVector(firstOp, secondOp, ElementIndex, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddHalving_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedAddRoundedHalving_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedAddRoundedHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedAddRoundedHalving(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAdd_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAdd_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddNegatedScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAddNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAddNegatedScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAddNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAddNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtract_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtract_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtract(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractNegatedScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtractNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtractNegatedScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtractNegatedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtractNegated(firstOp[0], secondOp[0], thirdOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "FusedSubtractHalving_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedSubtractHalving", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.FusedSubtractHalving(left[i], right[i]) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Insert(firstOp, ElementIndex, thirdOp, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Double_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Insert(firstOp, ElementIndex, thirdOp, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_Single_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Insert(firstOp, ElementIndex, thirdOp, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("InsertTest.template", new Dictionary { ["TestName"] = "Insert_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Insert", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ElementIndex"] = "1", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Insert(firstOp, ElementIndex, thirdOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingZeroCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingZeroBits(firstOp[i]) != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Byte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Double", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Int16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Int32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Int64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_SByte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_Single", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_UInt16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_UInt32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector64_UInt64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector64", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Byte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Double", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Int16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Int32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Int64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_SByte", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_Single", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_UInt16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_UInt32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("LoadUnOpTest.template", new Dictionary { ["TestName"] = "LoadVector128_UInt64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumber_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumber_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumber(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumber(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumber_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumber_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumber(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumber(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumber(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplySubtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndAdd_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningLowerAndSubtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningLowerAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningAndSubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndAdd_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndAdd(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "MultiplyWideningUpperAndSubtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyWideningUpperAndSubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyWideningUpperAndSubtract(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "NegateScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "NegateScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Not_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Or_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "OrNot_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiply_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiply(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiplyWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiplyWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.PolynomialMultiplyWideningUpper(left, right, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "PopCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x409e8000"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRecipEstimate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x409e8000"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRecipEstimate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x400e8000"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRSqrtEstimate(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(result[i]) != 0x400e8000"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.UnsignedRSqrtEstimate(firstOp[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStep_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStep", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRSqrtStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStep_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRSqrtStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStep_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStep", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRecipStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStep_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRecipStepFused(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmetic_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmetic(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRounded_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticRounded(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftArithmeticSaturate(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftArithmetic(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogical_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturate_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[i], Imm) != result[i]"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsigned_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsigned", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogical(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalScalar_Vector64_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogical(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWidening(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalWideningUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftLeftLogicalWideningUpper(firstOp, Imm, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogical_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogical(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRounded_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRounded(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturate_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRounded(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRounded(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturate_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.ShiftLogicalSaturate(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogical(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.ShiftLogical(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmetic_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmetic", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmetic(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAdd_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("ImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticAddScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticAdd(firstOp[0], secondOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRounded_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAdd_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("ImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedAddScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedAdd(firstOp[0], secondOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt16_1",["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper_Vector128_UInt32_1",["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRounded(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmetic(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogical_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogical(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAdd_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("ImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAddScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[0], secondOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalAddScalar_Vector64_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalAdd(firstOp[0], secondOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRounded_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRounded", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAdd_Vector128_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[i], secondOp[i], Imm) != result[i]"}), + ("ImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAddScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[0], secondOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedAddScalar_Vector64_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedAddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedAdd(firstOp[0], secondOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedScalar_Vector64_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRounded(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalScalar_Vector64_Int64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogical(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalScalar_Vector64_UInt64_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftRightLogical(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "SignExtendWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "SignExtendWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "SignExtendWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "SignExtendWideningUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "SignExtendWideningUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "SignExtendWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "SqrtScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "SqrtScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("StoreUnOpTest.template", new Dictionary { ["TestName"] = "Store_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Store", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractHighNarrowingUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowing(left[i], right[i]) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "SubtractRoundedHighNarrowingUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractRoundedHighNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractRoundedHighNarrowingUpper(firstOp, secondOp, thirdOp, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturate_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningLower_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWidening(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Byte_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int16_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int16_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int32_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int32_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_Int64_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_SByte_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt16_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt16_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt32_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt32_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "SubtractWideningUpper_Vector128_UInt64_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractWideningUpper(left, right, i) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Xor_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningLower_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningLower_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningLower_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningLower_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningLower_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningLower_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningUpper_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningUpper_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningUpper_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningUpper_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningUpper_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ZeroExtendWideningUpper_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}) }; private static readonly (string templateFileName, Dictionary templateData)[] AdvSimd_Arm64Inputs = new [] { - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Abs(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AbsScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Abs(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteDifference(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Add(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AddPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AddPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AddPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AddPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.AddPairwise(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.AddPairwise(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareTestScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareTest(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareTestScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareTest(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareTestScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareTest(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Divide_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Divide_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Divide(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Divide_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAdd_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtract_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Max(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumber_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumber(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxNumberAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwise_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumberPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumberPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Max(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Min(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumber_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumber(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinNumberAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwise_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumberPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumberPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Min(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtended_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MultiplyExtended(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtended_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MultiplyExtended(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtended_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MultiplyExtended(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtendedScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtendedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MultiplyExtended(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtendedScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtendedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MultiplyExtended(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "NegateScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Negate(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0x4013d00000000000"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimateScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != 0x4013d00000000000", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimateScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != 0x409e8000", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalExponentScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalExponentScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != 0x4030000000000000", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalExponentScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalExponentScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != 0x41800000", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateIterResult"] = " BitConverter.DoubleToInt64Bits(result[i]) != 0x4001d00000000000"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimateScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != 0x4001d00000000000", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimateScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != 0x400e8000", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStep_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRSqrtStepFused(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStepScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRSqrtStepFused(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStepScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRSqrtStepFused(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStep_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRecipStepFused(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStepScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRecipStepFused(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStepScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRecipStepFused(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), - ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), - ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Abs(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Abs_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Abs", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AbsScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Abs(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareGreaterThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteCompareLessThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteCompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteCompareLessThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifference_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteDifference(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AbsoluteDifferenceScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AbsoluteDifferenceScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Add_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Add", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Add(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "AddAcross_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AddPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AddPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "AddPairwise_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddPairwise(left, right, i) != result[i]"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.AddPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AddPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.AddPairwise(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "AddPairwiseScalar_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.AddPairwise(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "AddSaturateScalar_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.AddSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqual_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareEqual(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareEqualScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThan_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThan(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqual_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareGreaterThanOrEqual(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareGreaterThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareGreaterThanOrEqualScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareGreaterThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThan(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThan_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThan(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThan(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThan(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThan(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThanOrEqual(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqual_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareLessThanOrEqual(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareLessThanOrEqual(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareLessThanOrEqual(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareLessThanOrEqualScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareLessThanOrEqual(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "CompareTest_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareTestScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.CompareTest(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareTestScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareTest(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "CompareTestScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareTest(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Divide_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Divide_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Divide(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Divide_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_Double_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_Int64_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "DuplicateSelectedScalarToVector128_V128_UInt64_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateSelectedScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateFirstResult"] = "result[0] != firstOp[1]", ["ValidateRemainingResults"] = "result[i] != firstOp[1]" }), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Double_31", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_Int64_31", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("DuplicateTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != data", ["ValidateRemainingResults"] = "result[i] != data"}), + ("ImmOpTest.template", new Dictionary { ["TestName"] = "DuplicateToVector128_UInt64_31", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "DuplicateToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["Imm"] = "31", ["ValidateFirstResult"] = "result[0] != 31", ["ValidateRemainingResults"] = "result[i] != 31"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplyAdd_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "FusedMultiplySubtract_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Max_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Max(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxAcross_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumber_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumber(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MaxNumberAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwise_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumberPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxNumberPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxNumberPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxNumberPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MaxPairwise_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MaxPairwise(left, right, i) != result[i]"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MaxPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MaxPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MaxPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Max(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MaxScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Min_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Min(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinAcross_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumber_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumber(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecReduceUnOpTest.template", new Dictionary { ["TestName"] = "MinNumberAcross_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberAcross", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberAcross(firstOp)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwise_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwise", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumberPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinNumberPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinNumberPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinNumberPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinNumberPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinPairwise(left, right, i)) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinPairwise(left, right, i)) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MinPairwise_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwise", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MinPairwise(left, right, i) != result[i]"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinPairwiseScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MinPairwise(firstOp, 0)) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "MinPairwiseScalar_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinPairwiseScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MinPairwise(firstOp, 0)) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Min(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MinScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Multiply_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtended_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MultiplyExtended(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtended_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MultiplyExtended(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtended_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.MultiplyExtended(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtendedScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtendedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.MultiplyExtended(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "MultiplyExtendedScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyExtendedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.MultiplyExtended(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Negate_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "NegateScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Negate(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0x4013d00000000000"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimateScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != 0x4013d00000000000", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalEstimateScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != 0x409e8000", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalExponentScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalExponentScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != 0x4030000000000000", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalExponentScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalExponentScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != 0x41800000", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateIterResult"] = " BitConverter.DoubleToInt64Bits(result[i]) != 0x4001d00000000000"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimateScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int64BitsToDouble(0x3fc9db3dab555868)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != 0x4001d00000000000", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleUnOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootEstimateScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootEstimateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "BitConverter.Int32BitsToSingle(0x3e4ed9ed)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != 0x400e8000", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStep_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRSqrtStepFused(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStepScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRSqrtStepFused(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalSquareRootStepScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalSquareRootStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRSqrtStepFused(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStep_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStep", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRecipStepFused(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStepScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FPRecipStepFused(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ReciprocalStepScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReciprocalStepScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.FPRecipStepFused(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticRoundedSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftArithmeticSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftArithmeticSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.ShiftArithmeticSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_Byte_7", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_Int16_15", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "15", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_Int32_31", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "31", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_SByte_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_UInt16_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateScalar_Vector64_UInt32_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int16_5", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "5", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsignedScalar_Vector64_Int32_7", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftLeftLogicalSaturateUnsignedScalar_Vector64_SByte_3", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLeftLogicalSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "3", ["ValidateFirstResult"] = "Helpers.ShiftLeftLogicalSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalRoundedSaturateScalar_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalRoundedSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalRoundedSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "ShiftLogicalSaturateScalar_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftLogicalSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.ShiftLogicalSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int16_16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "16", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateScalar_Vector64_Int32_32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "32", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateScalar_Vector64_SByte_8", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "8", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_Byte_3", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "3", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt16_5", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "5", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticNarrowingSaturateUnsignedScalar_Vector64_UInt32_7", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticNarrowingSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int16_32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "16", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_Int32_64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "32", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateScalar_Vector64_SByte_16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "8", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_Byte_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt16_1",["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "15", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar_Vector64_UInt32_1",["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "31", ["ValidateFirstResult"] = "Helpers.ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_Byte_5", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int16_7", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "15", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_Int32_11", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "31", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_SByte_3", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "15", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "31", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "3", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "5", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "3", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "5", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), + ("VecBinOpTest.template", new Dictionary { ["TestName"] = "Subtract_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "SubtractSaturateScalar_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "Helpers.SubtractSaturate(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeEven_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "TransposeOdd_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[++index] != right[i+1]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookup_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookup", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateFirstResult"] = "Helpers.TableVectorLookup(0, right, left) != result[0]", ["ValidateRemainingResults"] = "Helpers.TableVectorLookup(i, right, left) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(Byte)(TestLibrary.Generator.GetByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), + ("VecTernOpTest.template", new Dictionary { ["TestName"] = "VectorTableLookupExtension_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "VectorTableLookupExtension", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(SByte)(TestLibrary.Generator.GetSByte() % 20)", ["ValidateIterResult"] = "Helpers.TableVectorExtension(i, firstOp, thirdOp, secondOp) != result[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipEven_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "UnzipOdd_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i+1] || result[index + half] != right[i+1]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipHigh_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index+half] || result[i+1] != right[index+half]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector64_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_UInt16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_UInt32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), + ("VecPairBinOpTest.template", new Dictionary { ["TestName"] = "ZipLow_Vector128_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i+1] != right[index]"}), }; private static readonly (string templateFileName, Dictionary templateData)[] AesInputs = new [] { - ("AesBinOpTest.template", new Dictionary { ["TestName"] = "Decrypt_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "Decrypt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["KeySize"] = "16", ["Key"] = "{0xFF, 0xDD, 0xBB, 0x99, 0x77, 0x55, 0x33, 0x11, 0xEE, 0xCC, 0xAA, 0x88, 0x66, 0x44, 0x22, 0x00}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0x7C, 0x99, 0x02, 0x7C, 0x7C, 0x7C, 0xFE, 0x86, 0xE3, 0x7C, 0x7C, 0x97, 0xC9, 0x94, 0x7C, 0x7C}"}), - ("AesBinOpTest.template", new Dictionary { ["TestName"] = "Encrypt_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "Encrypt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["KeySize"] = "16", ["Key"] = "{0xFF, 0xDD, 0xBB, 0x99, 0x77, 0x55, 0x33, 0x11, 0xEE, 0xCC, 0xAA, 0x88, 0x66, 0x44, 0x22, 0x00}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0xCA, 0xCA, 0xF5, 0xC4, 0xCA, 0x93, 0xEA, 0xCA, 0x82, 0x28, 0xCA, 0xCA, 0xC1, 0xCA, 0xCA, 0x1B}"}), - ("AesUnOpTest.template", new Dictionary { ["TestName"] = "InverseMixColumns_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "InverseMixColumns", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0xA0, 0x0A, 0xE4, 0x4E, 0x28, 0x82, 0x6C, 0xC6, 0x55, 0x00, 0x77, 0x22, 0x11, 0x44, 0x33, 0x66}"}), - ("AesUnOpTest.template", new Dictionary { ["TestName"] = "MixColumns_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "MixColumns", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0xAB, 0x01, 0xEF, 0x45, 0x23, 0x89, 0x67, 0xCD, 0xDD, 0x88, 0xFF, 0xAA, 0x99, 0xCC, 0xBB, 0xEE}"}), + ("AesBinOpTest.template", new Dictionary { ["TestName"] = "Decrypt_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "Decrypt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["KeySize"] = "16", ["Key"] = "{0xFF, 0xDD, 0xBB, 0x99, 0x77, 0x55, 0x33, 0x11, 0xEE, 0xCC, 0xAA, 0x88, 0x66, 0x44, 0x22, 0x00}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0x7C, 0x99, 0x02, 0x7C, 0x7C, 0x7C, 0xFE, 0x86, 0xE3, 0x7C, 0x7C, 0x97, 0xC9, 0x94, 0x7C, 0x7C}"}), + ("AesBinOpTest.template", new Dictionary { ["TestName"] = "Encrypt_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "Encrypt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["KeySize"] = "16", ["Key"] = "{0xFF, 0xDD, 0xBB, 0x99, 0x77, 0x55, 0x33, 0x11, 0xEE, 0xCC, 0xAA, 0x88, 0x66, 0x44, 0x22, 0x00}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0xCA, 0xCA, 0xF5, 0xC4, 0xCA, 0x93, 0xEA, 0xCA, 0x82, 0x28, 0xCA, 0xCA, 0xC1, 0xCA, 0xCA, 0x1B}"}), + ("AesUnOpTest.template", new Dictionary { ["TestName"] = "InverseMixColumns_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "InverseMixColumns", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0xA0, 0x0A, 0xE4, 0x4E, 0x28, 0x82, 0x6C, 0xC6, 0x55, 0x00, 0x77, 0x22, 0x11, 0x44, 0x33, 0x66}"}), + ("AesUnOpTest.template", new Dictionary { ["TestName"] = "MixColumns_Vector128_Byte", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "MixColumns", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["InputSize"] = "16", ["Input"] = "{0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}", ["ExpectedRetSize"] = "16", ["ExpectedRet"] = "{0xAB, 0x01, 0xEF, 0x45, 0x23, 0x89, 0x67, 0xCD, 0xDD, 0x88, 0xFF, 0xAA, 0x99, 0xCC, 0xBB, 0xEE}"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningLower_Vector64_Int64", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.PolynomialMultiplyWideningLo64(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.PolynomialMultiplyWideningHi64(left[0], right[0]) != result[1]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningLower_Vector64_UInt64", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningLower", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.PolynomialMultiplyWideningLo64(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.PolynomialMultiplyWideningHi64(left[0], right[0]) != result[1]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningUpper_Vector128_Int64", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.PolynomialMultiplyWideningLo64(left[1], right[1]) != result[0]", ["ValidateRemainingResults"] = "Helpers.PolynomialMultiplyWideningHi64(left[1], right[1]) != result[1]"}), + ("SimpleBinOpTest.template", new Dictionary { ["TestName"] = "PolynomialMultiplyWideningUpper_Vector128_UInt64", ["Isa"] = "Aes", ["LoadIsa"] = "AdvSimd", ["Method"] = "PolynomialMultiplyWideningUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.PolynomialMultiplyWideningLo64(left[1], right[1]) != result[0]", ["ValidateRemainingResults"] = "Helpers.PolynomialMultiplyWideningHi64(left[1], right[1]) != result[1]"}) }; private static readonly (string templateFileName, Dictionary templateData)[] ArmBaseInputs = new [] { - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Int32", ["Isa"] = "ArmBase", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 31; (((uint)data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_UInt32", ["Isa"] = "ArmBase", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 31; ((data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Int32", ["Isa"] = "ArmBase", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_UInt32", ["Isa"] = "ArmBase", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Int32", ["Isa"] = "ArmBase", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 31; (((uint)data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_UInt32", ["Isa"] = "ArmBase", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 31; ((data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Int32", ["Isa"] = "ArmBase", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_UInt32", ["Isa"] = "ArmBase", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), }; private static readonly (string templateFileName, Dictionary templateData)[] ArmBase_Arm64Inputs = new [] { - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Int32", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingSignCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 30; (((uint)data >> index) & 1) == (((uint)data >> 31) & 1); index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Int64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingSignCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 62; (((ulong)data >> index) & 1) == (((ulong)data >> 63) & 1); index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Int64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 63; (((ulong)data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_UInt64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 63; ((data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Int64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "Int64", ["Op1BaseType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), - ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_UInt64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Int32", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingSignCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 30; (((uint)data >> index) & 1) == (((uint)data >> 31) & 1); index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingSignCount_Int64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingSignCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 62; (((ulong)data >> index) & 1) == (((ulong)data >> 63) & 1); index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_Int64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 63; (((ulong)data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "LeadingZeroCount_UInt64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "LeadingZeroCount", ["RetBaseType"] = "Int32", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "int expectedResult = 0; for (int index = 63; ((data >> index) & 1) == 0; index--) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_Int64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "Int64", ["Op1BaseType"] = "Int64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "ReverseElementBits_UInt64", ["Isa"] = "ArmBase.Arm64", ["Method"] = "ReverseElementBits", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = Helpers.ReverseElementBits(data) != result;" }), }; private static readonly (string templateFileName, Dictionary templateData)[] Crc32Inputs = new [] { - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_Byte", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20", ["ValidateResult"] = "uint expectedResult = 0x169330BA; isUnexpectedResult = (expectedResult != result);" }), - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt16", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x2019", ["ValidateResult"] = "uint expectedResult = 0x1E4864D0; isUnexpectedResult = (expectedResult != result);" }), - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt32", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113", ["ValidateResult"] = "uint expectedResult = 0x219D9805; isUnexpectedResult = (expectedResult != result);" }), - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_Byte", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20", ["ValidateResult"] = "uint expectedResult = 0x8D3F2270; isUnexpectedResult = (expectedResult != result);" }), - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt16", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x2019", ["ValidateResult"] = "uint expectedResult = 0x9F50ACBD; isUnexpectedResult = (expectedResult != result);" }), - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt32", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113", ["ValidateResult"] = "uint expectedResult = 0x78F34758; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_Byte", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20", ["ValidateResult"] = "uint expectedResult = 0x169330BA; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt16", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x2019", ["ValidateResult"] = "uint expectedResult = 0x1E4864D0; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt32", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113", ["ValidateResult"] = "uint expectedResult = 0x219D9805; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_Byte", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20", ["ValidateResult"] = "uint expectedResult = 0x8D3F2270; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt16", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x2019", ["ValidateResult"] = "uint expectedResult = 0x9F50ACBD; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt32", ["Isa"] = "Crc32", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113", ["ValidateResult"] = "uint expectedResult = 0x78F34758; isUnexpectedResult = (expectedResult != result);" }), }; private static readonly (string templateFileName, Dictionary templateData)[] Crc32_Arm64Inputs = new [] { - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt64", ["Isa"] = "Crc32.Arm64", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113110219UL", ["ValidateResult"] = "uint expectedResult = 0xEFAAAB74; isUnexpectedResult = (expectedResult != result);" }), - ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt64", ["Isa"] = "Crc32.Arm64", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113110219UL", ["ValidateResult"] = "uint expectedResult = 0x6295C71A; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32_UInt64", ["Isa"] = "Crc32.Arm64", ["Method"] = "ComputeCrc32", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113110219UL", ["ValidateResult"] = "uint expectedResult = 0xEFAAAB74; isUnexpectedResult = (expectedResult != result);" }), + ("ScalarBinOpTest.template", new Dictionary { ["TestName"] = "ComputeCrc32C_UInt64", ["Isa"] = "Crc32.Arm64", ["Method"] = "ComputeCrc32C", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "0x20191113110219UL", ["ValidateResult"] = "uint expectedResult = 0x6295C71A; isUnexpectedResult = (expectedResult != result);" }), }; private static readonly (string templateFileName, Dictionary templateData)[] Sha1Inputs = new [] { - ("SecureHashUnOpTest.template", new Dictionary { ["TestName"] = "FixedRotate_Vector64_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "FixedRotate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "0x00112233", ["ExpectedResult"] = "{0xC004488C, 0x0, 0x0, 0x0}"}), - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdateChoose_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdateChoose", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x27A38C6D, 0xEFEFCA67, 0xDB4E8169, 0x73C91E71}"}), - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdateMajority_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdateMajority", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0xEC691B1D, 0xF21410C7, 0x9B52C9F6, 0x73C91E71}"}), - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdateParity_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdateParity", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0xDAB2AF34, 0xFF990D18, 0xCB4F938C, 0x73C91E71}"}), - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "ScheduleUpdate0_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate0", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x8899AABB, 0x8899AABB, 0xCCDDEEFF, 0xCCDDEEFF}"}), - ("SecureHashBinOpTest.template", new Dictionary { ["TestName"] = "ScheduleUpdate1_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate1", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["ExpectedResult"] = "{0x88888888, 0x88888888, 0x88888888, 0x11335577}"}), + ("SecureHashUnOpTest.template", new Dictionary { ["TestName"] = "FixedRotate_Vector64_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "FixedRotate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "0x00112233", ["ExpectedResult"] = "{0xC004488C, 0x0, 0x0, 0x0}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdateChoose_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdateChoose", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x27A38C6D, 0xEFEFCA67, 0xDB4E8169, 0x73C91E71}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdateMajority_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdateMajority", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0xEC691B1D, 0xF21410C7, 0x9B52C9F6, 0x73C91E71}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdateParity_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdateParity", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0xDAB2AF34, 0xFF990D18, 0xCB4F938C, 0x73C91E71}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "ScheduleUpdate0_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate0", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x8899AABB, 0x8899AABB, 0xCCDDEEFF, 0xCCDDEEFF}"}), + ("SecureHashBinOpTest.template", new Dictionary { ["TestName"] = "ScheduleUpdate1_Vector128_UInt32", ["Isa"] = "Sha1", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate1", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["ExpectedResult"] = "{0x88888888, 0x88888888, 0x88888888, 0x11335577}"}), }; private static readonly (string templateFileName, Dictionary templateData)[] Sha256Inputs = new [] { - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdate1_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdate1", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x3D22118E, 0x987CA5FB, 0x54F4E477, 0xDFB50278}"}), - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdate2_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdate2", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0xFFD38634, 0x2A33F83F, 0x55A1BE45, 0x5002B4C4}"}), - ("SecureHashBinOpTest.template", new Dictionary { ["TestName"] = "ScheduleUpdate0_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate0", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["ExpectedResult"] = "{0x2E9FE839, 0x2E9FE839, 0x2E9FE839, 0xBFB0F94A}"}), - ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "ScheduleUpdate1_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate1", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x248F1BDF, 0x248F1BDF, 0xB303DDBA, 0xF74821FE}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdate1_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdate1", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x3D22118E, 0x987CA5FB, 0x54F4E477, 0xDFB50278}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "HashUpdate2_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "HashUpdate2", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0xFFD38634, 0x2A33F83F, 0x55A1BE45, 0x5002B4C4}"}), + ("SecureHashBinOpTest.template", new Dictionary { ["TestName"] = "ScheduleUpdate0_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate0", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["ExpectedResult"] = "{0x2E9FE839, 0x2E9FE839, 0x2E9FE839, 0xBFB0F94A}"}), + ("SecureHashTernOpTest.template",new Dictionary { ["TestName"] = "ScheduleUpdate1_Vector128_UInt32", ["Isa"] = "Sha256", ["LoadIsa"] = "AdvSimd", ["Method"] = "ScheduleUpdate1", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "0x00112233", ["NextValueOp2"] = "0x44556677", ["NextValueOp3"] = "0x8899AABB", ["ExpectedResult"] = "{0x248F1BDF, 0x248F1BDF, 0xB303DDBA, 0xF74821FE}"}), }; private static void ProcessInputs(string groupName, (string templateFileName, Dictionary templateData)[] inputs) diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 7ece1a765ccb9..9dede7c81433f 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -9,7 +9,6 @@ using System; using System.Linq; -using System.Numerics; namespace JIT.HardwareIntrinsics.Arm { @@ -1447,7 +1446,7 @@ public static float CompareTest(float left, float right) public static short AddPairwiseWideningAndAdd(short[] op1, sbyte[] op2, int i) => (short)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static sbyte HighNarrow(short op1, bool round) + private static sbyte HighNarrowing(short op1, bool round) { ushort roundConst = 0; if (round) @@ -1457,13 +1456,13 @@ private static sbyte HighNarrow(short op1, bool round) return (sbyte)(((ushort)op1 + roundConst) >> (8 * sizeof(sbyte))); } - public static sbyte AddReturningHighNarrow(short op1, short op2) => HighNarrow((short)(op1 + op2), round: false); + public static sbyte AddHighNarrowing(short op1, short op2) => HighNarrowing((short)(op1 + op2), round: false); - public static sbyte AddReturningHighNarrowUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static sbyte AddHighNarrowingUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static sbyte AddReturningRoundedHighNarrow(short op1, short op2) => HighNarrow((short)(op1 + op2), round: true); + public static sbyte AddRoundedHighNarrowing(short op1, short op2) => HighNarrowing((short)(op1 + op2), round: true); - public static short AddReturningRoundedHighNarrowUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static short AddRoundedHighNarrowingUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static short AddWidening(sbyte op1, sbyte op2) => (short)((short)op1 + (short)op2); @@ -1473,6 +1472,10 @@ private static sbyte HighNarrow(short op1, bool round) public static short AddWideningUpper(short[] op1, sbyte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static sbyte ExtractNarrowing(short op1) => (sbyte)op1; + + public static sbyte ExtractNarrowingUpper(sbyte[] op1, short[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static sbyte FusedAddHalving(sbyte op1, sbyte op2) => (sbyte)((ushort)((short)op1 + (short)op2) >> 1); public static sbyte FusedAddRoundedHalving(sbyte op1, sbyte op2) => (sbyte)((ushort)((short)op1 + (short)op2 + 1) >> 1); @@ -1491,13 +1494,13 @@ private static sbyte HighNarrow(short op1, bool round) public static short MultiplyWideningUpperAndSubtract(short[] op1, sbyte[] op2, sbyte[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); - public static sbyte SubtractReturningHighNarrow(short op1, short op2) => HighNarrow((short)(op1 - op2), round: false); + public static sbyte SubtractHighNarrowing(short op1, short op2) => HighNarrowing((short)(op1 - op2), round: false); - public static short SubtractReturningHighNarrowUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static short SubtractHighNarrowingUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static sbyte SubtractReturningRoundedHighNarrow(short op1, short op2) => HighNarrow((short)(op1 - op2), round: true); + public static sbyte SubtractRoundedHighNarrowing(short op1, short op2) => HighNarrowing((short)(op1 - op2), round: true); - public static short SubtractReturningRoundedHighNarrowUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static short SubtractRoundedHighNarrowingUpper(sbyte[] op1, short[] op2, short[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static short SubtractWidening(sbyte op1, sbyte op2) => (short)((short)op1 - (short)op2); @@ -1507,6 +1510,10 @@ private static sbyte HighNarrow(short op1, bool round) public static short SubtractWideningUpper(short[] op1, sbyte[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + public static short ZeroExtendWidening(sbyte op1) => (short)(ushort)op1; + + public static short ZeroExtendWideningUpper(sbyte[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + public static uint AbsoluteDifferenceWidening(short op1, short op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); public static uint AbsoluteDifferenceWideningUpper(short[] op1, short[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1519,7 +1526,7 @@ private static sbyte HighNarrow(short op1, bool round) public static int AddPairwiseWideningAndAdd(int[] op1, short[] op2, int i) => (int)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static short HighNarrow(int op1, bool round) + private static short HighNarrowing(int op1, bool round) { uint roundConst = 0; if (round) @@ -1529,13 +1536,13 @@ private static short HighNarrow(int op1, bool round) return (short)(((uint)op1 + roundConst) >> (8 * sizeof(short))); } - public static short AddReturningHighNarrow(int op1, int op2) => HighNarrow((int)(op1 + op2), round: false); + public static short AddHighNarrowing(int op1, int op2) => HighNarrowing((int)(op1 + op2), round: false); - public static short AddReturningHighNarrowUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static short AddHighNarrowingUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static short AddReturningRoundedHighNarrow(int op1, int op2) => HighNarrow((int)(op1 + op2), round: true); + public static short AddRoundedHighNarrowing(int op1, int op2) => HighNarrowing((int)(op1 + op2), round: true); - public static int AddReturningRoundedHighNarrowUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static int AddRoundedHighNarrowingUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static int AddWidening(short op1, short op2) => (int)((int)op1 + (int)op2); @@ -1545,6 +1552,10 @@ private static short HighNarrow(int op1, bool round) public static int AddWideningUpper(int[] op1, short[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static short ExtractNarrowing(int op1) => (short)op1; + + public static short ExtractNarrowingUpper(short[] op1, int[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static short FusedAddHalving(short op1, short op2) => (short)((uint)((int)op1 + (int)op2) >> 1); public static short FusedAddRoundedHalving(short op1, short op2) => (short)((uint)((int)op1 + (int)op2 + 1) >> 1); @@ -1563,13 +1574,13 @@ private static short HighNarrow(int op1, bool round) public static int MultiplyWideningUpperAndSubtract(int[] op1, short[] op2, short[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); - public static short SubtractReturningHighNarrow(int op1, int op2) => HighNarrow((int)(op1 - op2), round: false); + public static short SubtractHighNarrowing(int op1, int op2) => HighNarrowing((int)(op1 - op2), round: false); - public static int SubtractReturningHighNarrowUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static int SubtractHighNarrowingUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static short SubtractReturningRoundedHighNarrow(int op1, int op2) => HighNarrow((int)(op1 - op2), round: true); + public static short SubtractRoundedHighNarrowing(int op1, int op2) => HighNarrowing((int)(op1 - op2), round: true); - public static int SubtractReturningRoundedHighNarrowUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static int SubtractRoundedHighNarrowingUpper(short[] op1, int[] op2, int[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static int SubtractWidening(short op1, short op2) => (int)((int)op1 - (int)op2); @@ -1579,6 +1590,10 @@ private static short HighNarrow(int op1, bool round) public static int SubtractWideningUpper(int[] op1, short[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + public static int ZeroExtendWidening(short op1) => (int)(uint)op1; + + public static int ZeroExtendWideningUpper(short[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + public static ulong AbsoluteDifferenceWidening(int op1, int op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); public static ulong AbsoluteDifferenceWideningUpper(int[] op1, int[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1591,7 +1606,7 @@ private static short HighNarrow(int op1, bool round) public static long AddPairwiseWideningAndAdd(long[] op1, int[] op2, int i) => (long)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static int HighNarrow(long op1, bool round) + private static int HighNarrowing(long op1, bool round) { ulong roundConst = 0; if (round) @@ -1601,13 +1616,13 @@ private static int HighNarrow(long op1, bool round) return (int)(((ulong)op1 + roundConst) >> (8 * sizeof(int))); } - public static int AddReturningHighNarrow(long op1, long op2) => HighNarrow((long)(op1 + op2), round: false); + public static int AddHighNarrowing(long op1, long op2) => HighNarrowing((long)(op1 + op2), round: false); - public static int AddReturningHighNarrowUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static int AddHighNarrowingUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static int AddReturningRoundedHighNarrow(long op1, long op2) => HighNarrow((long)(op1 + op2), round: true); + public static int AddRoundedHighNarrowing(long op1, long op2) => HighNarrowing((long)(op1 + op2), round: true); - public static long AddReturningRoundedHighNarrowUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static long AddRoundedHighNarrowingUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static long AddWidening(int op1, int op2) => (long)((long)op1 + (long)op2); @@ -1617,6 +1632,10 @@ private static int HighNarrow(long op1, bool round) public static long AddWideningUpper(long[] op1, int[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static int ExtractNarrowing(long op1) => (int)op1; + + public static int ExtractNarrowingUpper(int[] op1, long[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static int FusedAddHalving(int op1, int op2) => (int)((ulong)((long)op1 + (long)op2) >> 1); public static int FusedAddRoundedHalving(int op1, int op2) => (int)((ulong)((long)op1 + (long)op2 + 1) >> 1); @@ -1635,13 +1654,13 @@ private static int HighNarrow(long op1, bool round) public static long MultiplyWideningUpperAndSubtract(long[] op1, int[] op2, int[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); - public static int SubtractReturningHighNarrow(long op1, long op2) => HighNarrow((long)(op1 - op2), round: false); + public static int SubtractHighNarrowing(long op1, long op2) => HighNarrowing((long)(op1 - op2), round: false); - public static long SubtractReturningHighNarrowUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static long SubtractHighNarrowingUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static int SubtractReturningRoundedHighNarrow(long op1, long op2) => HighNarrow((long)(op1 - op2), round: true); + public static int SubtractRoundedHighNarrowing(long op1, long op2) => HighNarrowing((long)(op1 - op2), round: true); - public static long SubtractReturningRoundedHighNarrowUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static long SubtractRoundedHighNarrowingUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static long SubtractWidening(int op1, int op2) => (long)((long)op1 - (long)op2); @@ -1651,6 +1670,10 @@ private static int HighNarrow(long op1, bool round) public static long SubtractWideningUpper(long[] op1, int[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + public static long ZeroExtendWidening(int op1) => (long)(ulong)op1; + + public static long ZeroExtendWideningUpper(int[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + public static ushort AbsoluteDifferenceWidening(byte op1, byte op2) => op1 < op2 ? (ushort)(op2 - op1) : (ushort)(op1 - op2); public static ushort AbsoluteDifferenceWideningUpper(byte[] op1, byte[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1663,7 +1686,7 @@ private static int HighNarrow(long op1, bool round) public static ushort AddPairwiseWideningAndAdd(ushort[] op1, byte[] op2, int i) => (ushort)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static byte HighNarrow(ushort op1, bool round) + private static byte HighNarrowing(ushort op1, bool round) { ushort roundConst = 0; if (round) @@ -1673,13 +1696,13 @@ private static byte HighNarrow(ushort op1, bool round) return (byte)(((ushort)op1 + roundConst) >> (8 * sizeof(byte))); } - public static byte AddReturningHighNarrow(ushort op1, ushort op2) => HighNarrow((ushort)(op1 + op2), round: false); + public static byte AddHighNarrowing(ushort op1, ushort op2) => HighNarrowing((ushort)(op1 + op2), round: false); - public static byte AddReturningHighNarrowUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static byte AddHighNarrowingUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static byte AddReturningRoundedHighNarrow(ushort op1, ushort op2) => HighNarrow((ushort)(op1 + op2), round: true); + public static byte AddRoundedHighNarrowing(ushort op1, ushort op2) => HighNarrowing((ushort)(op1 + op2), round: true); - public static ushort AddReturningRoundedHighNarrowUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static ushort AddRoundedHighNarrowingUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static ushort AddWidening(byte op1, byte op2) => (ushort)((ushort)op1 + (ushort)op2); @@ -1689,6 +1712,10 @@ private static byte HighNarrow(ushort op1, bool round) public static ushort AddWideningUpper(ushort[] op1, byte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static byte ExtractNarrowing(ushort op1) => (byte)op1; + + public static byte ExtractNarrowingUpper(byte[] op1, ushort[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static byte FusedAddHalving(byte op1, byte op2) => (byte)((ushort)((ushort)op1 + (ushort)op2) >> 1); public static byte FusedAddRoundedHalving(byte op1, byte op2) => (byte)((ushort)((ushort)op1 + (ushort)op2 + 1) >> 1); @@ -1707,13 +1734,13 @@ private static byte HighNarrow(ushort op1, bool round) public static ushort MultiplyWideningUpperAndSubtract(ushort[] op1, byte[] op2, byte[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); - public static byte SubtractReturningHighNarrow(ushort op1, ushort op2) => HighNarrow((ushort)(op1 - op2), round: false); + public static byte SubtractHighNarrowing(ushort op1, ushort op2) => HighNarrowing((ushort)(op1 - op2), round: false); - public static ushort SubtractReturningHighNarrowUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static ushort SubtractHighNarrowingUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static byte SubtractReturningRoundedHighNarrow(ushort op1, ushort op2) => HighNarrow((ushort)(op1 - op2), round: true); + public static byte SubtractRoundedHighNarrowing(ushort op1, ushort op2) => HighNarrowing((ushort)(op1 - op2), round: true); - public static ushort SubtractReturningRoundedHighNarrowUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static ushort SubtractRoundedHighNarrowingUpper(byte[] op1, ushort[] op2, ushort[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static ushort SubtractWidening(byte op1, byte op2) => (ushort)((ushort)op1 - (ushort)op2); @@ -1723,6 +1750,10 @@ private static byte HighNarrow(ushort op1, bool round) public static ushort SubtractWideningUpper(ushort[] op1, byte[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + public static ushort ZeroExtendWidening(byte op1) => (ushort)(ushort)op1; + + public static ushort ZeroExtendWideningUpper(byte[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + public static uint AbsoluteDifferenceWidening(ushort op1, ushort op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); public static uint AbsoluteDifferenceWideningUpper(ushort[] op1, ushort[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1735,7 +1766,7 @@ private static byte HighNarrow(ushort op1, bool round) public static uint AddPairwiseWideningAndAdd(uint[] op1, ushort[] op2, int i) => (uint)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static ushort HighNarrow(uint op1, bool round) + private static ushort HighNarrowing(uint op1, bool round) { uint roundConst = 0; if (round) @@ -1745,13 +1776,13 @@ private static ushort HighNarrow(uint op1, bool round) return (ushort)(((uint)op1 + roundConst) >> (8 * sizeof(ushort))); } - public static ushort AddReturningHighNarrow(uint op1, uint op2) => HighNarrow((uint)(op1 + op2), round: false); + public static ushort AddHighNarrowing(uint op1, uint op2) => HighNarrowing((uint)(op1 + op2), round: false); - public static ushort AddReturningHighNarrowUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static ushort AddHighNarrowingUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static ushort AddReturningRoundedHighNarrow(uint op1, uint op2) => HighNarrow((uint)(op1 + op2), round: true); + public static ushort AddRoundedHighNarrowing(uint op1, uint op2) => HighNarrowing((uint)(op1 + op2), round: true); - public static uint AddReturningRoundedHighNarrowUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static uint AddRoundedHighNarrowingUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static uint AddWidening(ushort op1, ushort op2) => (uint)((uint)op1 + (uint)op2); @@ -1761,6 +1792,10 @@ private static ushort HighNarrow(uint op1, bool round) public static uint AddWideningUpper(uint[] op1, ushort[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static ushort ExtractNarrowing(uint op1) => (ushort)op1; + + public static ushort ExtractNarrowingUpper(ushort[] op1, uint[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static ushort FusedAddHalving(ushort op1, ushort op2) => (ushort)((uint)((uint)op1 + (uint)op2) >> 1); public static ushort FusedAddRoundedHalving(ushort op1, ushort op2) => (ushort)((uint)((uint)op1 + (uint)op2 + 1) >> 1); @@ -1779,13 +1814,13 @@ private static ushort HighNarrow(uint op1, bool round) public static uint MultiplyWideningUpperAndSubtract(uint[] op1, ushort[] op2, ushort[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); - public static ushort SubtractReturningHighNarrow(uint op1, uint op2) => HighNarrow((uint)(op1 - op2), round: false); + public static ushort SubtractHighNarrowing(uint op1, uint op2) => HighNarrowing((uint)(op1 - op2), round: false); - public static uint SubtractReturningHighNarrowUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static uint SubtractHighNarrowingUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static ushort SubtractReturningRoundedHighNarrow(uint op1, uint op2) => HighNarrow((uint)(op1 - op2), round: true); + public static ushort SubtractRoundedHighNarrowing(uint op1, uint op2) => HighNarrowing((uint)(op1 - op2), round: true); - public static uint SubtractReturningRoundedHighNarrowUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static uint SubtractRoundedHighNarrowingUpper(ushort[] op1, uint[] op2, uint[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static uint SubtractWidening(ushort op1, ushort op2) => (uint)((uint)op1 - (uint)op2); @@ -1795,6 +1830,10 @@ private static ushort HighNarrow(uint op1, bool round) public static uint SubtractWideningUpper(uint[] op1, ushort[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + public static uint ZeroExtendWidening(ushort op1) => (uint)(uint)op1; + + public static uint ZeroExtendWideningUpper(ushort[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + public static ulong AbsoluteDifferenceWidening(uint op1, uint op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); public static ulong AbsoluteDifferenceWideningUpper(uint[] op1, uint[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1807,7 +1846,7 @@ private static ushort HighNarrow(uint op1, bool round) public static ulong AddPairwiseWideningAndAdd(ulong[] op1, uint[] op2, int i) => (ulong)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static uint HighNarrow(ulong op1, bool round) + private static uint HighNarrowing(ulong op1, bool round) { ulong roundConst = 0; if (round) @@ -1817,13 +1856,13 @@ private static uint HighNarrow(ulong op1, bool round) return (uint)(((ulong)op1 + roundConst) >> (8 * sizeof(uint))); } - public static uint AddReturningHighNarrow(ulong op1, ulong op2) => HighNarrow((ulong)(op1 + op2), round: false); + public static uint AddHighNarrowing(ulong op1, ulong op2) => HighNarrowing((ulong)(op1 + op2), round: false); - public static uint AddReturningHighNarrowUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static uint AddHighNarrowingUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static uint AddReturningRoundedHighNarrow(ulong op1, ulong op2) => HighNarrow((ulong)(op1 + op2), round: true); + public static uint AddRoundedHighNarrowing(ulong op1, ulong op2) => HighNarrowing((ulong)(op1 + op2), round: true); - public static ulong AddReturningRoundedHighNarrowUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static ulong AddRoundedHighNarrowingUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static ulong AddWidening(uint op1, uint op2) => (ulong)((ulong)op1 + (ulong)op2); @@ -1833,327 +1872,1755 @@ private static uint HighNarrow(ulong op1, bool round) public static ulong AddWideningUpper(ulong[] op1, uint[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static uint ExtractNarrowing(ulong op1) => (uint)op1; + + public static uint ExtractNarrowingUpper(uint[] op1, ulong[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static uint FusedAddHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 + (ulong)op2) >> 1); public static uint FusedAddRoundedHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 + (ulong)op2 + 1) >> 1); - public static uint FusedSubtractHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 - (ulong)op2) >> 1); + public static uint FusedSubtractHalving(uint op1, uint op2) => (uint)((ulong)((ulong)op1 - (ulong)op2) >> 1); + + public static ulong MultiplyWidening(uint op1, uint op2) => (ulong)((ulong)op1 * (ulong)op2); + + public static ulong MultiplyWideningAndAdd(ulong op1, uint op2, uint op3) => (ulong)(op1 + MultiplyWidening(op2, op3)); + + public static ulong MultiplyWideningAndSubtract(ulong op1, uint op2, uint op3) => (ulong)(op1 - MultiplyWidening(op2, op3)); + + public static ulong MultiplyWideningUpper(uint[] op1, uint[] op2, int i) => MultiplyWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + + public static ulong MultiplyWideningUpperAndAdd(ulong[] op1, uint[] op2, uint[] op3, int i) => MultiplyWideningAndAdd(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); + + public static ulong MultiplyWideningUpperAndSubtract(ulong[] op1, uint[] op2, uint[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); + + public static uint SubtractHighNarrowing(ulong op1, ulong op2) => HighNarrowing((ulong)(op1 - op2), round: false); + + public static ulong SubtractHighNarrowingUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); + + public static uint SubtractRoundedHighNarrowing(ulong op1, ulong op2) => HighNarrowing((ulong)(op1 - op2), round: true); + + public static ulong SubtractRoundedHighNarrowingUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); + + public static ulong SubtractWidening(uint op1, uint op2) => (ulong)((ulong)op1 - (ulong)op2); + + public static ulong SubtractWidening(ulong op1, uint op2) => (ulong)(op1 - op2); + + public static ulong SubtractWideningUpper(uint[] op1, uint[] op2, int i) => SubtractWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + + public static ulong SubtractWideningUpper(ulong[] op1, uint[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + + public static ulong ZeroExtendWidening(uint op1) => (ulong)(ulong)op1; + + public static ulong ZeroExtendWideningUpper(uint[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + + private static bool SignedSatQ(short val, out sbyte result) + { + bool saturated = false; + + if (val > sbyte.MaxValue) + { + result = sbyte.MaxValue; + saturated = true; + } + else if (val < sbyte.MinValue) + { + result = sbyte.MinValue; + saturated = true; + } + else + { + result = (sbyte)val; + } + + return saturated; + } + + private static bool SignedSatQ(short val, out byte result) + { + bool saturated = false; + + if (val > byte.MaxValue) + { + result = byte.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (byte)val; + } + + return saturated; + } + + private static bool UnsignedSatQ(short val, out sbyte result) + { + byte res; + + bool saturated = UnsignedSatQ((ushort)val, out res); + + result = (sbyte)res; + return saturated; + } + + private static bool UnsignedSatQ(ushort val, out byte result) + { + bool saturated = false; + + if (val > byte.MaxValue) + { + result = byte.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (byte)val; + } + + return saturated; + } + + public static short ShiftLeftLogicalWidening(sbyte op1, byte op2) => UnsignedShift((short)op1, (short)op2); + + public static ushort ShiftLeftLogicalWidening(byte op1, byte op2) => UnsignedShift((ushort)op1, (short)op2); + + public static short ShiftLeftLogicalWideningUpper(sbyte[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static ushort ShiftLeftLogicalWideningUpper(byte[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static sbyte ShiftRightArithmeticRoundedNarrowingSaturate(short op1, byte op2) + { + sbyte result; + + SignedSatQ(SignedShift(op1, (short)(-op2), rounding: true), out result); + + return result; + } + + public static byte ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(short op1, byte op2) + { + byte result; + + SignedSatQ(SignedShift(op1, (short)(-op2), rounding: true), out result); + + return result; + } + + public static byte ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(byte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (byte)ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static sbyte ShiftRightArithmeticRoundedNarrowingSaturateUpper(sbyte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (sbyte)ShiftRightArithmeticRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static sbyte ShiftRightArithmeticNarrowingSaturate(short op1, byte op2) + { + sbyte result; + + SignedSatQ(SignedShift(op1, (short)(-op2)), out result); + + return result; + } + + public static byte ShiftRightArithmeticNarrowingSaturateUnsigned(short op1, byte op2) + { + byte result; + + SignedSatQ(SignedShift(op1, (short)(-op2)), out result); + + return result; + } + + public static byte ShiftRightArithmeticNarrowingSaturateUnsignedUpper(byte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (byte)ShiftRightArithmeticNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static sbyte ShiftRightArithmeticNarrowingSaturateUpper(sbyte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (sbyte)ShiftRightArithmeticNarrowingSaturate(op2[i - op1.Length], op3); + + public static sbyte ShiftRightLogicalNarrowing(short op1, byte op2) => (sbyte)UnsignedShift(op1, (short)(-op2)); + + public static byte ShiftRightLogicalNarrowing(ushort op1, byte op2) => (byte)UnsignedShift(op1, (short)(-op2)); + + public static sbyte ShiftRightLogicalRoundedNarrowing(short op1, byte op2) => (sbyte)UnsignedShift(op1, (short)(-op2), rounding: true); + + public static byte ShiftRightLogicalRoundedNarrowing(ushort op1, byte op2) => (byte)UnsignedShift(op1, (short)(-op2), rounding: true); + + public static sbyte ShiftRightLogicalRoundedNarrowingUpper(sbyte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (sbyte)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static byte ShiftRightLogicalRoundedNarrowingUpper(byte[] op1, ushort[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (byte)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static sbyte ShiftRightLogicalRoundedNarrowingSaturate(short op1, byte op2) + { + sbyte result; + + UnsignedSatQ(UnsignedShift(op1, (short)(-op2), rounding: true), out result); + + return result; + } + + public static byte ShiftRightLogicalRoundedNarrowingSaturate(ushort op1, byte op2) + { + byte result; + + UnsignedSatQ(UnsignedShift(op1, (short)(-op2), rounding: true), out result); + + return result; + } + + public static sbyte ShiftRightLogicalRoundedNarrowingSaturateUpper(sbyte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (sbyte)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static byte ShiftRightLogicalRoundedNarrowingSaturateUpper(byte[] op1, ushort[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (byte)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static sbyte ShiftRightLogicalNarrowingUpper(sbyte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (sbyte)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static byte ShiftRightLogicalNarrowingUpper(byte[] op1, ushort[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (byte)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static sbyte ShiftRightLogicalNarrowingSaturate(short op1, byte op2) + { + sbyte result; + + UnsignedSatQ(UnsignedShift(op1, (short)(-op2)), out result); + + return result; + } + + public static byte ShiftRightLogicalNarrowingSaturate(ushort op1, byte op2) + { + byte result; + + UnsignedSatQ(UnsignedShift(op1, (short)(-op2)), out result); + + return result; + } + + public static sbyte ShiftRightLogicalNarrowingSaturateUpper(sbyte[] op1, short[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (sbyte)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static byte ShiftRightLogicalNarrowingSaturateUpper(byte[] op1, ushort[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (byte)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static short SignExtendWidening(sbyte op1) => op1; + + public static short SignExtendWideningUpper(sbyte[] op1, int i) => SignExtendWidening(op1[i + op1.Length / 2]); + + private static bool SignedSatQ(int val, out short result) + { + bool saturated = false; + + if (val > short.MaxValue) + { + result = short.MaxValue; + saturated = true; + } + else if (val < short.MinValue) + { + result = short.MinValue; + saturated = true; + } + else + { + result = (short)val; + } + + return saturated; + } + + private static bool SignedSatQ(int val, out ushort result) + { + bool saturated = false; + + if (val > ushort.MaxValue) + { + result = ushort.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (ushort)val; + } + + return saturated; + } + + private static bool UnsignedSatQ(int val, out short result) + { + ushort res; + + bool saturated = UnsignedSatQ((uint)val, out res); + + result = (short)res; + return saturated; + } + + private static bool UnsignedSatQ(uint val, out ushort result) + { + bool saturated = false; + + if (val > ushort.MaxValue) + { + result = ushort.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (ushort)val; + } + + return saturated; + } + + public static int ShiftLeftLogicalWidening(short op1, byte op2) => UnsignedShift((int)op1, (int)op2); + + public static uint ShiftLeftLogicalWidening(ushort op1, byte op2) => UnsignedShift((uint)op1, (int)op2); + + public static int ShiftLeftLogicalWideningUpper(short[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static uint ShiftLeftLogicalWideningUpper(ushort[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static short ShiftRightArithmeticRoundedNarrowingSaturate(int op1, byte op2) + { + short result; + + SignedSatQ(SignedShift(op1, (int)(-op2), rounding: true), out result); + + return result; + } + + public static ushort ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(int op1, byte op2) + { + ushort result; + + SignedSatQ(SignedShift(op1, (int)(-op2), rounding: true), out result); + + return result; + } + + public static ushort ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(ushort[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (ushort)ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static short ShiftRightArithmeticRoundedNarrowingSaturateUpper(short[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (short)ShiftRightArithmeticRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static short ShiftRightArithmeticNarrowingSaturate(int op1, byte op2) + { + short result; + + SignedSatQ(SignedShift(op1, (int)(-op2)), out result); + + return result; + } + + public static ushort ShiftRightArithmeticNarrowingSaturateUnsigned(int op1, byte op2) + { + ushort result; + + SignedSatQ(SignedShift(op1, (int)(-op2)), out result); + + return result; + } + + public static ushort ShiftRightArithmeticNarrowingSaturateUnsignedUpper(ushort[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (ushort)ShiftRightArithmeticNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static short ShiftRightArithmeticNarrowingSaturateUpper(short[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (short)ShiftRightArithmeticNarrowingSaturate(op2[i - op1.Length], op3); + + public static short ShiftRightLogicalNarrowing(int op1, byte op2) => (short)UnsignedShift(op1, (int)(-op2)); + + public static ushort ShiftRightLogicalNarrowing(uint op1, byte op2) => (ushort)UnsignedShift(op1, (int)(-op2)); + + public static short ShiftRightLogicalRoundedNarrowing(int op1, byte op2) => (short)UnsignedShift(op1, (int)(-op2), rounding: true); + + public static ushort ShiftRightLogicalRoundedNarrowing(uint op1, byte op2) => (ushort)UnsignedShift(op1, (int)(-op2), rounding: true); + + public static short ShiftRightLogicalRoundedNarrowingUpper(short[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (short)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static ushort ShiftRightLogicalRoundedNarrowingUpper(ushort[] op1, uint[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (ushort)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static short ShiftRightLogicalRoundedNarrowingSaturate(int op1, byte op2) + { + short result; + + UnsignedSatQ(UnsignedShift(op1, (int)(-op2), rounding: true), out result); + + return result; + } + + public static ushort ShiftRightLogicalRoundedNarrowingSaturate(uint op1, byte op2) + { + ushort result; + + UnsignedSatQ(UnsignedShift(op1, (int)(-op2), rounding: true), out result); + + return result; + } + + public static short ShiftRightLogicalRoundedNarrowingSaturateUpper(short[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (short)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static ushort ShiftRightLogicalRoundedNarrowingSaturateUpper(ushort[] op1, uint[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (ushort)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static short ShiftRightLogicalNarrowingUpper(short[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (short)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static ushort ShiftRightLogicalNarrowingUpper(ushort[] op1, uint[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (ushort)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static short ShiftRightLogicalNarrowingSaturate(int op1, byte op2) + { + short result; + + UnsignedSatQ(UnsignedShift(op1, (int)(-op2)), out result); + + return result; + } + + public static ushort ShiftRightLogicalNarrowingSaturate(uint op1, byte op2) + { + ushort result; + + UnsignedSatQ(UnsignedShift(op1, (int)(-op2)), out result); + + return result; + } + + public static short ShiftRightLogicalNarrowingSaturateUpper(short[] op1, int[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (short)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static ushort ShiftRightLogicalNarrowingSaturateUpper(ushort[] op1, uint[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (ushort)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static int SignExtendWidening(short op1) => op1; + + public static int SignExtendWideningUpper(short[] op1, int i) => SignExtendWidening(op1[i + op1.Length / 2]); + + private static bool SignedSatQ(long val, out int result) + { + bool saturated = false; + + if (val > int.MaxValue) + { + result = int.MaxValue; + saturated = true; + } + else if (val < int.MinValue) + { + result = int.MinValue; + saturated = true; + } + else + { + result = (int)val; + } + + return saturated; + } + + private static bool SignedSatQ(long val, out uint result) + { + bool saturated = false; + + if (val > uint.MaxValue) + { + result = uint.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (uint)val; + } + + return saturated; + } + + private static bool UnsignedSatQ(long val, out int result) + { + uint res; + + bool saturated = UnsignedSatQ((ulong)val, out res); + + result = (int)res; + return saturated; + } + + private static bool UnsignedSatQ(ulong val, out uint result) + { + bool saturated = false; + + if (val > uint.MaxValue) + { + result = uint.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (uint)val; + } + + return saturated; + } + + public static long ShiftLeftLogicalWidening(int op1, byte op2) => UnsignedShift((long)op1, (long)op2); + + public static ulong ShiftLeftLogicalWidening(uint op1, byte op2) => UnsignedShift((ulong)op1, (long)op2); + + public static long ShiftLeftLogicalWideningUpper(int[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static ulong ShiftLeftLogicalWideningUpper(uint[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static int ShiftRightArithmeticRoundedNarrowingSaturate(long op1, byte op2) + { + int result; + + SignedSatQ(SignedShift(op1, (long)(-op2), rounding: true), out result); + + return result; + } + + public static uint ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(long op1, byte op2) + { + uint result; + + SignedSatQ(SignedShift(op1, (long)(-op2), rounding: true), out result); + + return result; + } + + public static uint ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(uint[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (uint)ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static int ShiftRightArithmeticRoundedNarrowingSaturateUpper(int[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (int)ShiftRightArithmeticRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static int ShiftRightArithmeticNarrowingSaturate(long op1, byte op2) + { + int result; + + SignedSatQ(SignedShift(op1, (long)(-op2)), out result); + + return result; + } + + public static uint ShiftRightArithmeticNarrowingSaturateUnsigned(long op1, byte op2) + { + uint result; + + SignedSatQ(SignedShift(op1, (long)(-op2)), out result); + + return result; + } + + public static uint ShiftRightArithmeticNarrowingSaturateUnsignedUpper(uint[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (uint)ShiftRightArithmeticNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static int ShiftRightArithmeticNarrowingSaturateUpper(int[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (int)ShiftRightArithmeticNarrowingSaturate(op2[i - op1.Length], op3); + + public static int ShiftRightLogicalNarrowing(long op1, byte op2) => (int)UnsignedShift(op1, (long)(-op2)); + + public static uint ShiftRightLogicalNarrowing(ulong op1, byte op2) => (uint)UnsignedShift(op1, (long)(-op2)); + + public static int ShiftRightLogicalRoundedNarrowing(long op1, byte op2) => (int)UnsignedShift(op1, (long)(-op2), rounding: true); + + public static uint ShiftRightLogicalRoundedNarrowing(ulong op1, byte op2) => (uint)UnsignedShift(op1, (long)(-op2), rounding: true); + + public static int ShiftRightLogicalRoundedNarrowingUpper(int[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (int)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static uint ShiftRightLogicalRoundedNarrowingUpper(uint[] op1, ulong[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (uint)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static int ShiftRightLogicalRoundedNarrowingSaturate(long op1, byte op2) + { + int result; + + UnsignedSatQ(UnsignedShift(op1, (long)(-op2), rounding: true), out result); + + return result; + } + + public static uint ShiftRightLogicalRoundedNarrowingSaturate(ulong op1, byte op2) + { + uint result; + + UnsignedSatQ(UnsignedShift(op1, (long)(-op2), rounding: true), out result); + + return result; + } + + public static int ShiftRightLogicalRoundedNarrowingSaturateUpper(int[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (int)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static uint ShiftRightLogicalRoundedNarrowingSaturateUpper(uint[] op1, ulong[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (uint)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static int ShiftRightLogicalNarrowingUpper(int[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (int)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static uint ShiftRightLogicalNarrowingUpper(uint[] op1, ulong[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (uint)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static int ShiftRightLogicalNarrowingSaturate(long op1, byte op2) + { + int result; + + UnsignedSatQ(UnsignedShift(op1, (long)(-op2)), out result); + + return result; + } + + public static uint ShiftRightLogicalNarrowingSaturate(ulong op1, byte op2) + { + uint result; + + UnsignedSatQ(UnsignedShift(op1, (long)(-op2)), out result); + + return result; + } + + public static int ShiftRightLogicalNarrowingSaturateUpper(int[] op1, long[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (int)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static uint ShiftRightLogicalNarrowingSaturateUpper(uint[] op1, ulong[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (uint)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static long SignExtendWidening(int op1) => op1; + + public static long SignExtendWideningUpper(int[] op1, int i) => SignExtendWidening(op1[i + op1.Length / 2]); + + public static sbyte ShiftArithmetic(sbyte op1, sbyte op2) => SignedShift(op1, op2); + + public static sbyte ShiftArithmeticRounded(sbyte op1, sbyte op2) => SignedShift(op1, op2, rounding: true); + + public static sbyte ShiftArithmeticSaturate(sbyte op1, sbyte op2) => SignedShift(op1, op2, saturating: true); + + public static sbyte ShiftArithmeticRoundedSaturate(sbyte op1, sbyte op2) => SignedShift(op1, op2, rounding: true, saturating: true); + + private static sbyte SignedShift(sbyte op1, sbyte op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + sbyte rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((sbyte)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + sbyte result; + + bool addOvf; + + (result, addOvf) = AddOvf(op1, rndCns); + + if (addOvf) + { + result = (sbyte)ShiftOvf((byte)result, shift).val; + } + else + { + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (saturating) + { + if (shiftOvf) + { + result = sbyte.MaxValue; + } + } + } + + return result; + } + + public static sbyte ShiftLeftLogical(sbyte op1, byte op2) => UnsignedShift(op1, (sbyte)op2); + + public static byte ShiftLeftLogical(byte op1, byte op2) => UnsignedShift(op1, (sbyte)op2); + + public static sbyte ShiftLeftLogicalSaturate(sbyte op1, byte op2) => SignedShift(op1, (sbyte)op2, saturating: true); + + public static byte ShiftLeftLogicalSaturate(byte op1, byte op2) => UnsignedShift(op1, (sbyte)op2, saturating: true); + + public static byte ShiftLeftLogicalSaturateUnsigned(sbyte op1, byte op2) => (byte)UnsignedShift(op1, (sbyte)op2, saturating: true); + + public static sbyte ShiftLogical(sbyte op1, sbyte op2) => UnsignedShift(op1, op2); + + public static byte ShiftLogical(byte op1, sbyte op2) => UnsignedShift(op1, op2); + + public static byte ShiftLogicalRounded(byte op1, sbyte op2) => UnsignedShift(op1, op2, rounding: true); + + public static sbyte ShiftLogicalRounded(sbyte op1, sbyte op2) => UnsignedShift(op1, op2, rounding: true); + + public static byte ShiftLogicalRoundedSaturate(byte op1, sbyte op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static sbyte ShiftLogicalRoundedSaturate(sbyte op1, sbyte op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static sbyte ShiftLogicalSaturate(sbyte op1, sbyte op2) => UnsignedShift(op1, op2, saturating: true); + + public static byte ShiftLogicalSaturate(byte op1, sbyte op2) => UnsignedShift(op1, op2, saturating: true); + + public static sbyte ShiftRightArithmetic(sbyte op1, byte op2) => SignedShift(op1, (sbyte)(-op2)); + + public static sbyte ShiftRightArithmeticAdd(sbyte op1, sbyte op2, byte op3) => (sbyte)(op1 + ShiftRightArithmetic(op2, op3)); + + public static sbyte ShiftRightArithmeticRounded(sbyte op1, byte op2) => SignedShift(op1, (sbyte)(-op2), rounding: true); + + public static sbyte ShiftRightArithmeticRoundedAdd(sbyte op1, sbyte op2, byte op3) => (sbyte)(op1 + ShiftRightArithmeticRounded(op2, op3)); + + public static sbyte ShiftRightLogical(sbyte op1, byte op2) => UnsignedShift(op1, (sbyte)(-op2)); + + public static byte ShiftRightLogical(byte op1, byte op2) => UnsignedShift(op1, (sbyte)(-op2)); + + public static sbyte ShiftRightLogicalAdd(sbyte op1, sbyte op2, byte op3) => (sbyte)(op1 + ShiftRightLogical(op2, op3)); + + public static byte ShiftRightLogicalAdd(byte op1, byte op2, byte op3) => (byte)(op1 + ShiftRightLogical(op2, op3)); + + public static sbyte ShiftRightLogicalRounded(sbyte op1, byte op2) => UnsignedShift(op1, (sbyte)(-op2), rounding: true); + + public static byte ShiftRightLogicalRounded(byte op1, byte op2) => UnsignedShift(op1, (sbyte)(-op2), rounding: true); + + public static sbyte ShiftRightLogicalRoundedAdd(sbyte op1, sbyte op2, byte op3) => (sbyte)(op1 + ShiftRightLogicalRounded(op2, op3)); + + public static byte ShiftRightLogicalRoundedAdd(byte op1, byte op2, byte op3) => (byte)(op1 + ShiftRightLogicalRounded(op2, op3)); + + private static byte UnsignedShift(byte op1, sbyte op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + byte rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((byte)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + (byte result, bool addOvf) = AddOvf(op1, rndCns); + + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (addOvf) + { + byte shiftedCarry = ShiftOvf((byte)1, 8 * sizeof(byte) + shift).val; + result = (byte)(result | shiftedCarry); + } + + if (saturating) + { + if (shiftOvf) + { + result = byte.MaxValue; + } + } + + return result; + } + + private static sbyte UnsignedShift(sbyte op1, sbyte op2, bool rounding = false, bool saturating = false) => (sbyte)UnsignedShift((byte)op1, op2, rounding, saturating); + + private static (sbyte val, bool ovf) AddOvf(sbyte op1, sbyte op2) + { + sbyte result = (sbyte)(op1 + op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 > 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 < 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (byte val, bool ovf) AddOvf(byte op1, byte op2) + { + byte result = (byte)(op1 + op2); + + bool ovf = (result < op1); + + return (result, ovf); + } + + private static (sbyte val, bool ovf) SubtractOvf(sbyte op1, sbyte op2) + { + sbyte result = (sbyte)(op1 - op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 < 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 > 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (byte val, bool ovf) SubtractOvf(byte op1, byte op2) + { + byte result = (byte)(op1 - op2); + + bool ovf = (op1 < op2); + + return (result, ovf); + } + + public static sbyte AddSaturate(sbyte op1, sbyte op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? (result > 0 ? sbyte.MinValue : sbyte.MaxValue) : result; + } + + public static byte AddSaturate(byte op1, byte op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? byte.MaxValue : result; + } + + public static sbyte SubtractSaturate(sbyte op1, sbyte op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? (result > 0 ? sbyte.MinValue : sbyte.MaxValue) : result; + } + + public static byte SubtractSaturate(byte op1, byte op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? byte.MinValue : result; + } + + public static short ShiftArithmetic(short op1, short op2) => SignedShift(op1, op2); + + public static short ShiftArithmeticRounded(short op1, short op2) => SignedShift(op1, op2, rounding: true); + + public static short ShiftArithmeticSaturate(short op1, short op2) => SignedShift(op1, op2, saturating: true); + + public static short ShiftArithmeticRoundedSaturate(short op1, short op2) => SignedShift(op1, op2, rounding: true, saturating: true); + + private static short SignedShift(short op1, short op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + short rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((short)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + short result; + + bool addOvf; + + (result, addOvf) = AddOvf(op1, rndCns); + + if (addOvf) + { + result = (short)ShiftOvf((ushort)result, shift).val; + } + else + { + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (saturating) + { + if (shiftOvf) + { + result = short.MaxValue; + } + } + } + + return result; + } + + public static short ShiftLeftLogical(short op1, byte op2) => UnsignedShift(op1, (short)op2); + + public static ushort ShiftLeftLogical(ushort op1, byte op2) => UnsignedShift(op1, (short)op2); + + public static short ShiftLeftLogicalSaturate(short op1, byte op2) => SignedShift(op1, (short)op2, saturating: true); + + public static ushort ShiftLeftLogicalSaturate(ushort op1, byte op2) => UnsignedShift(op1, (short)op2, saturating: true); + + public static ushort ShiftLeftLogicalSaturateUnsigned(short op1, byte op2) => (ushort)UnsignedShift(op1, (short)op2, saturating: true); + + public static short ShiftLogical(short op1, short op2) => UnsignedShift(op1, op2); + + public static ushort ShiftLogical(ushort op1, short op2) => UnsignedShift(op1, op2); + + public static ushort ShiftLogicalRounded(ushort op1, short op2) => UnsignedShift(op1, op2, rounding: true); + + public static short ShiftLogicalRounded(short op1, short op2) => UnsignedShift(op1, op2, rounding: true); + + public static ushort ShiftLogicalRoundedSaturate(ushort op1, short op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static short ShiftLogicalRoundedSaturate(short op1, short op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static short ShiftLogicalSaturate(short op1, short op2) => UnsignedShift(op1, op2, saturating: true); + + public static ushort ShiftLogicalSaturate(ushort op1, short op2) => UnsignedShift(op1, op2, saturating: true); + + public static short ShiftRightArithmetic(short op1, byte op2) => SignedShift(op1, (short)(-op2)); + + public static short ShiftRightArithmeticAdd(short op1, short op2, byte op3) => (short)(op1 + ShiftRightArithmetic(op2, op3)); + + public static short ShiftRightArithmeticRounded(short op1, byte op2) => SignedShift(op1, (short)(-op2), rounding: true); + + public static short ShiftRightArithmeticRoundedAdd(short op1, short op2, byte op3) => (short)(op1 + ShiftRightArithmeticRounded(op2, op3)); + + public static short ShiftRightLogical(short op1, byte op2) => UnsignedShift(op1, (short)(-op2)); + + public static ushort ShiftRightLogical(ushort op1, byte op2) => UnsignedShift(op1, (short)(-op2)); + + public static short ShiftRightLogicalAdd(short op1, short op2, byte op3) => (short)(op1 + ShiftRightLogical(op2, op3)); + + public static ushort ShiftRightLogicalAdd(ushort op1, ushort op2, byte op3) => (ushort)(op1 + ShiftRightLogical(op2, op3)); + + public static short ShiftRightLogicalRounded(short op1, byte op2) => UnsignedShift(op1, (short)(-op2), rounding: true); + + public static ushort ShiftRightLogicalRounded(ushort op1, byte op2) => UnsignedShift(op1, (short)(-op2), rounding: true); + + public static short ShiftRightLogicalRoundedAdd(short op1, short op2, byte op3) => (short)(op1 + ShiftRightLogicalRounded(op2, op3)); + + public static ushort ShiftRightLogicalRoundedAdd(ushort op1, ushort op2, byte op3) => (ushort)(op1 + ShiftRightLogicalRounded(op2, op3)); + + private static ushort UnsignedShift(ushort op1, short op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + ushort rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((ushort)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + (ushort result, bool addOvf) = AddOvf(op1, rndCns); + + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (addOvf) + { + ushort shiftedCarry = ShiftOvf((ushort)1, 8 * sizeof(ushort) + shift).val; + result = (ushort)(result | shiftedCarry); + } + + if (saturating) + { + if (shiftOvf) + { + result = ushort.MaxValue; + } + } + + return result; + } + + private static short UnsignedShift(short op1, short op2, bool rounding = false, bool saturating = false) => (short)UnsignedShift((ushort)op1, op2, rounding, saturating); + + private static (short val, bool ovf) AddOvf(short op1, short op2) + { + short result = (short)(op1 + op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 > 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 < 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (ushort val, bool ovf) AddOvf(ushort op1, ushort op2) + { + ushort result = (ushort)(op1 + op2); + + bool ovf = (result < op1); + + return (result, ovf); + } + + private static (short val, bool ovf) SubtractOvf(short op1, short op2) + { + short result = (short)(op1 - op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 < 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 > 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (ushort val, bool ovf) SubtractOvf(ushort op1, ushort op2) + { + ushort result = (ushort)(op1 - op2); + + bool ovf = (op1 < op2); + + return (result, ovf); + } + + public static short AddSaturate(short op1, short op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? (result > 0 ? short.MinValue : short.MaxValue) : result; + } + + public static ushort AddSaturate(ushort op1, ushort op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? ushort.MaxValue : result; + } + + public static short SubtractSaturate(short op1, short op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? (result > 0 ? short.MinValue : short.MaxValue) : result; + } + + public static ushort SubtractSaturate(ushort op1, ushort op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? ushort.MinValue : result; + } + + public static int ShiftArithmetic(int op1, int op2) => SignedShift(op1, op2); + + public static int ShiftArithmeticRounded(int op1, int op2) => SignedShift(op1, op2, rounding: true); + + public static int ShiftArithmeticSaturate(int op1, int op2) => SignedShift(op1, op2, saturating: true); + + public static int ShiftArithmeticRoundedSaturate(int op1, int op2) => SignedShift(op1, op2, rounding: true, saturating: true); + + private static int SignedShift(int op1, int op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + int rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((int)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + int result; + + bool addOvf; + + (result, addOvf) = AddOvf(op1, rndCns); + + if (addOvf) + { + result = (int)ShiftOvf((uint)result, shift).val; + } + else + { + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (saturating) + { + if (shiftOvf) + { + result = int.MaxValue; + } + } + } + + return result; + } + + public static int ShiftLeftLogical(int op1, byte op2) => UnsignedShift(op1, (int)op2); + + public static uint ShiftLeftLogical(uint op1, byte op2) => UnsignedShift(op1, (int)op2); + + public static int ShiftLeftLogicalSaturate(int op1, byte op2) => SignedShift(op1, (int)op2, saturating: true); + + public static uint ShiftLeftLogicalSaturate(uint op1, byte op2) => UnsignedShift(op1, (int)op2, saturating: true); + + public static uint ShiftLeftLogicalSaturateUnsigned(int op1, byte op2) => (uint)UnsignedShift(op1, (int)op2, saturating: true); + + public static int ShiftLogical(int op1, int op2) => UnsignedShift(op1, op2); + + public static uint ShiftLogical(uint op1, int op2) => UnsignedShift(op1, op2); + + public static uint ShiftLogicalRounded(uint op1, int op2) => UnsignedShift(op1, op2, rounding: true); + + public static int ShiftLogicalRounded(int op1, int op2) => UnsignedShift(op1, op2, rounding: true); + + public static uint ShiftLogicalRoundedSaturate(uint op1, int op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static int ShiftLogicalRoundedSaturate(int op1, int op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static int ShiftLogicalSaturate(int op1, int op2) => UnsignedShift(op1, op2, saturating: true); + + public static uint ShiftLogicalSaturate(uint op1, int op2) => UnsignedShift(op1, op2, saturating: true); + + public static int ShiftRightArithmetic(int op1, byte op2) => SignedShift(op1, (int)(-op2)); + + public static int ShiftRightArithmeticAdd(int op1, int op2, byte op3) => (int)(op1 + ShiftRightArithmetic(op2, op3)); + + public static int ShiftRightArithmeticRounded(int op1, byte op2) => SignedShift(op1, (int)(-op2), rounding: true); + + public static int ShiftRightArithmeticRoundedAdd(int op1, int op2, byte op3) => (int)(op1 + ShiftRightArithmeticRounded(op2, op3)); + + public static int ShiftRightLogical(int op1, byte op2) => UnsignedShift(op1, (int)(-op2)); + + public static uint ShiftRightLogical(uint op1, byte op2) => UnsignedShift(op1, (int)(-op2)); + + public static int ShiftRightLogicalAdd(int op1, int op2, byte op3) => (int)(op1 + ShiftRightLogical(op2, op3)); + + public static uint ShiftRightLogicalAdd(uint op1, uint op2, byte op3) => (uint)(op1 + ShiftRightLogical(op2, op3)); + + public static int ShiftRightLogicalRounded(int op1, byte op2) => UnsignedShift(op1, (int)(-op2), rounding: true); + + public static uint ShiftRightLogicalRounded(uint op1, byte op2) => UnsignedShift(op1, (int)(-op2), rounding: true); + + public static int ShiftRightLogicalRoundedAdd(int op1, int op2, byte op3) => (int)(op1 + ShiftRightLogicalRounded(op2, op3)); + + public static uint ShiftRightLogicalRoundedAdd(uint op1, uint op2, byte op3) => (uint)(op1 + ShiftRightLogicalRounded(op2, op3)); + + private static uint UnsignedShift(uint op1, int op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + uint rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((uint)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + (uint result, bool addOvf) = AddOvf(op1, rndCns); + + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (addOvf) + { + uint shiftedCarry = ShiftOvf((uint)1, 8 * sizeof(uint) + shift).val; + result = (uint)(result | shiftedCarry); + } + + if (saturating) + { + if (shiftOvf) + { + result = uint.MaxValue; + } + } + + return result; + } + + private static int UnsignedShift(int op1, int op2, bool rounding = false, bool saturating = false) => (int)UnsignedShift((uint)op1, op2, rounding, saturating); + + private static (int val, bool ovf) AddOvf(int op1, int op2) + { + int result = (int)(op1 + op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 > 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 < 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (uint val, bool ovf) AddOvf(uint op1, uint op2) + { + uint result = (uint)(op1 + op2); + + bool ovf = (result < op1); + + return (result, ovf); + } + + private static (int val, bool ovf) SubtractOvf(int op1, int op2) + { + int result = (int)(op1 - op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 < 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 > 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (uint val, bool ovf) SubtractOvf(uint op1, uint op2) + { + uint result = (uint)(op1 - op2); + + bool ovf = (op1 < op2); + + return (result, ovf); + } + + public static int AddSaturate(int op1, int op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? (result > 0 ? int.MinValue : int.MaxValue) : result; + } + + public static uint AddSaturate(uint op1, uint op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? uint.MaxValue : result; + } + + public static int SubtractSaturate(int op1, int op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? (result > 0 ? int.MinValue : int.MaxValue) : result; + } + + public static uint SubtractSaturate(uint op1, uint op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? uint.MinValue : result; + } + + public static long ShiftArithmetic(long op1, long op2) => SignedShift(op1, op2); + + public static long ShiftArithmeticRounded(long op1, long op2) => SignedShift(op1, op2, rounding: true); + + public static long ShiftArithmeticSaturate(long op1, long op2) => SignedShift(op1, op2, saturating: true); + + public static long ShiftArithmeticRoundedSaturate(long op1, long op2) => SignedShift(op1, op2, rounding: true, saturating: true); + + private static long SignedShift(long op1, long op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + long rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((long)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + long result; + + bool addOvf; + + (result, addOvf) = AddOvf(op1, rndCns); + + if (addOvf) + { + result = (long)ShiftOvf((ulong)result, shift).val; + } + else + { + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (saturating) + { + if (shiftOvf) + { + result = long.MaxValue; + } + } + } + + return result; + } + + public static long ShiftLeftLogical(long op1, byte op2) => UnsignedShift(op1, (long)op2); + + public static ulong ShiftLeftLogical(ulong op1, byte op2) => UnsignedShift(op1, (long)op2); + + public static long ShiftLeftLogicalSaturate(long op1, byte op2) => SignedShift(op1, (long)op2, saturating: true); + + public static ulong ShiftLeftLogicalSaturate(ulong op1, byte op2) => UnsignedShift(op1, (long)op2, saturating: true); + + public static ulong ShiftLeftLogicalSaturateUnsigned(long op1, byte op2) => (ulong)UnsignedShift(op1, (long)op2, saturating: true); + + public static long ShiftLogical(long op1, long op2) => UnsignedShift(op1, op2); + + public static ulong ShiftLogical(ulong op1, long op2) => UnsignedShift(op1, op2); + + public static ulong ShiftLogicalRounded(ulong op1, long op2) => UnsignedShift(op1, op2, rounding: true); + + public static long ShiftLogicalRounded(long op1, long op2) => UnsignedShift(op1, op2, rounding: true); + + public static ulong ShiftLogicalRoundedSaturate(ulong op1, long op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static long ShiftLogicalRoundedSaturate(long op1, long op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static long ShiftLogicalSaturate(long op1, long op2) => UnsignedShift(op1, op2, saturating: true); + + public static ulong ShiftLogicalSaturate(ulong op1, long op2) => UnsignedShift(op1, op2, saturating: true); + + public static long ShiftRightArithmetic(long op1, byte op2) => SignedShift(op1, (long)(-op2)); + + public static long ShiftRightArithmeticAdd(long op1, long op2, byte op3) => (long)(op1 + ShiftRightArithmetic(op2, op3)); + + public static long ShiftRightArithmeticRounded(long op1, byte op2) => SignedShift(op1, (long)(-op2), rounding: true); + + public static long ShiftRightArithmeticRoundedAdd(long op1, long op2, byte op3) => (long)(op1 + ShiftRightArithmeticRounded(op2, op3)); + + public static long ShiftRightLogical(long op1, byte op2) => UnsignedShift(op1, (long)(-op2)); + + public static ulong ShiftRightLogical(ulong op1, byte op2) => UnsignedShift(op1, (long)(-op2)); + + public static long ShiftRightLogicalAdd(long op1, long op2, byte op3) => (long)(op1 + ShiftRightLogical(op2, op3)); + + public static ulong ShiftRightLogicalAdd(ulong op1, ulong op2, byte op3) => (ulong)(op1 + ShiftRightLogical(op2, op3)); + + public static long ShiftRightLogicalRounded(long op1, byte op2) => UnsignedShift(op1, (long)(-op2), rounding: true); + + public static ulong ShiftRightLogicalRounded(ulong op1, byte op2) => UnsignedShift(op1, (long)(-op2), rounding: true); + + public static long ShiftRightLogicalRoundedAdd(long op1, long op2, byte op3) => (long)(op1 + ShiftRightLogicalRounded(op2, op3)); + + public static ulong ShiftRightLogicalRoundedAdd(ulong op1, ulong op2, byte op3) => (ulong)(op1 + ShiftRightLogicalRounded(op2, op3)); + + private static ulong UnsignedShift(ulong op1, long op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + ulong rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((ulong)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + (ulong result, bool addOvf) = AddOvf(op1, rndCns); + + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (addOvf) + { + ulong shiftedCarry = ShiftOvf((ulong)1, 8 * sizeof(ulong) + shift).val; + result = (ulong)(result | shiftedCarry); + } + + if (saturating) + { + if (shiftOvf) + { + result = ulong.MaxValue; + } + } + + return result; + } + + private static long UnsignedShift(long op1, long op2, bool rounding = false, bool saturating = false) => (long)UnsignedShift((ulong)op1, op2, rounding, saturating); + + private static (long val, bool ovf) AddOvf(long op1, long op2) + { + long result = (long)(op1 + op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 > 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 < 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (ulong val, bool ovf) AddOvf(ulong op1, ulong op2) + { + ulong result = (ulong)(op1 + op2); - public static ulong MultiplyWidening(uint op1, uint op2) => (ulong)((ulong)op1 * (ulong)op2); + bool ovf = (result < op1); - public static ulong MultiplyWideningAndAdd(ulong op1, uint op2, uint op3) => (ulong)(op1 + MultiplyWidening(op2, op3)); + return (result, ovf); + } - public static ulong MultiplyWideningAndSubtract(ulong op1, uint op2, uint op3) => (ulong)(op1 - MultiplyWidening(op2, op3)); + private static (long val, bool ovf) SubtractOvf(long op1, long op2) + { + long result = (long)(op1 - op2); - public static ulong MultiplyWideningUpper(uint[] op1, uint[] op2, int i) => MultiplyWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + bool ovf = false; - public static ulong MultiplyWideningUpperAndAdd(ulong[] op1, uint[] op2, uint[] op3, int i) => MultiplyWideningAndAdd(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); + if ((op1 > 0) && (op2 < 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 > 0)) + { + ovf = (result > 0); + } - public static ulong MultiplyWideningUpperAndSubtract(ulong[] op1, uint[] op2, uint[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); + return (result, ovf); + } - public static uint SubtractReturningHighNarrow(ulong op1, ulong op2) => HighNarrow((ulong)(op1 - op2), round: false); + private static (ulong val, bool ovf) SubtractOvf(ulong op1, ulong op2) + { + ulong result = (ulong)(op1 - op2); - public static ulong SubtractReturningHighNarrowUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + bool ovf = (op1 < op2); - public static uint SubtractReturningRoundedHighNarrow(ulong op1, ulong op2) => HighNarrow((ulong)(op1 - op2), round: true); + return (result, ovf); + } - public static ulong SubtractReturningRoundedHighNarrowUpper(uint[] op1, ulong[] op2, ulong[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static long AddSaturate(long op1, long op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? (result > 0 ? long.MinValue : long.MaxValue) : result; + } - public static ulong SubtractWidening(uint op1, uint op2) => (ulong)((ulong)op1 - (ulong)op2); + public static ulong AddSaturate(ulong op1, ulong op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? ulong.MaxValue : result; + } - public static ulong SubtractWidening(ulong op1, uint op2) => (ulong)(op1 - op2); + public static long SubtractSaturate(long op1, long op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? (result > 0 ? long.MinValue : long.MaxValue) : result; + } - public static ulong SubtractWideningUpper(uint[] op1, uint[] op2, int i) => SubtractWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + public static ulong SubtractSaturate(ulong op1, ulong op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? ulong.MinValue : result; + } - public static ulong SubtractWideningUpper(ulong[] op1, uint[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); - private static bool SatQ(BigInteger i, out sbyte result) + private static (sbyte val, bool ovf) ShiftOvf(sbyte value, int shift) { - bool saturated = false; + sbyte result = value; - if (i > sbyte.MaxValue) + bool ovf = false; + sbyte msb = 1; + msb = (sbyte)(msb << (8 * sizeof(sbyte) - 1)); + + for (int i = 0; i < shift; i++) { - result = sbyte.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < sbyte.MinValue) + + for (int i = 0; i > shift; i--) { - result = sbyte.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (sbyte)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static sbyte AddSaturate(sbyte op1, sbyte op2) - { - sbyte result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static sbyte SubtractSaturate(sbyte op1, sbyte op2) - { - sbyte result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out byte result) + private static (byte val, bool ovf) ShiftOvf(byte value, int shift) { - bool saturated = false; + byte result = value; - if (i > byte.MaxValue) + bool ovf = false; + byte msb = 1; + msb = (byte)(msb << (8 * sizeof(byte) - 1)); + + for (int i = 0; i < shift; i++) { - result = byte.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < byte.MinValue) + + for (int i = 0; i > shift; i--) { - result = byte.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (byte)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static byte AddSaturate(byte op1, byte op2) - { - byte result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static byte SubtractSaturate(byte op1, byte op2) - { - byte result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out short result) + private static (short val, bool ovf) ShiftOvf(short value, int shift) { - bool saturated = false; + short result = value; + + bool ovf = false; + short msb = 1; + msb = (short)(msb << (8 * sizeof(short) - 1)); - if (i > short.MaxValue) + for (int i = 0; i < shift; i++) { - result = short.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < short.MinValue) + + for (int i = 0; i > shift; i--) { - result = short.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (short)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static short AddSaturate(short op1, short op2) - { - short result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static short SubtractSaturate(short op1, short op2) - { - short result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out ushort result) + private static (ushort val, bool ovf) ShiftOvf(ushort value, int shift) { - bool saturated = false; + ushort result = value; + + bool ovf = false; + ushort msb = 1; + msb = (ushort)(msb << (8 * sizeof(ushort) - 1)); - if (i > ushort.MaxValue) + for (int i = 0; i < shift; i++) { - result = ushort.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < ushort.MinValue) + + for (int i = 0; i > shift; i--) { - result = ushort.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (ushort)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static ushort AddSaturate(ushort op1, ushort op2) - { - ushort result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static ushort SubtractSaturate(ushort op1, ushort op2) - { - ushort result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out int result) + private static (int val, bool ovf) ShiftOvf(int value, int shift) { - bool saturated = false; + int result = value; - if (i > int.MaxValue) + bool ovf = false; + int msb = 1; + msb = (int)(msb << (8 * sizeof(int) - 1)); + + for (int i = 0; i < shift; i++) { - result = int.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < int.MinValue) + + for (int i = 0; i > shift; i--) { - result = int.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (int)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static int AddSaturate(int op1, int op2) - { - int result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static int SubtractSaturate(int op1, int op2) - { - int result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out uint result) + private static (uint val, bool ovf) ShiftOvf(uint value, int shift) { - bool saturated = false; + uint result = value; - if (i > uint.MaxValue) + bool ovf = false; + uint msb = 1; + msb = (uint)(msb << (8 * sizeof(uint) - 1)); + + for (int i = 0; i < shift; i++) { - result = uint.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < uint.MinValue) + + for (int i = 0; i > shift; i--) { - result = uint.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (uint)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static uint AddSaturate(uint op1, uint op2) - { - uint result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static uint SubtractSaturate(uint op1, uint op2) - { - uint result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out long result) + private static (long val, bool ovf) ShiftOvf(long value, int shift) { - bool saturated = false; + long result = value; + + bool ovf = false; + long msb = 1; + msb = (long)(msb << (8 * sizeof(long) - 1)); - if (i > long.MaxValue) + for (int i = 0; i < shift; i++) { - result = long.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < long.MinValue) + + for (int i = 0; i > shift; i--) { - result = long.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (long)i; + ovf = true; } - return saturated; + return (result, ovf); } - public static long AddSaturate(long op1, long op2) - { - long result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; - } - public static long SubtractSaturate(long op1, long op2) - { - long result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } - private static bool SatQ(BigInteger i, out ulong result) + private static (ulong val, bool ovf) ShiftOvf(ulong value, int shift) { - bool saturated = false; + ulong result = value; + + bool ovf = false; + ulong msb = 1; + msb = (ulong)(msb << (8 * sizeof(ulong) - 1)); - if (i > ulong.MaxValue) + for (int i = 0; i < shift; i++) { - result = ulong.MaxValue; - saturated = true; + ovf = ovf || ((result & msb) != 0); + result <<= 1; } - else if (i < ulong.MinValue) + + for (int i = 0; i > shift; i--) { - result = ulong.MinValue; - saturated = true; + result >>= 1; } - else + + if ((value > 0) && (result < 0)) { - result = (ulong)i; + ovf = true; } - return saturated; - } - - public static ulong AddSaturate(ulong op1, ulong op2) - { - ulong result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); - return result; + return (result, ovf); } - public static ulong SubtractSaturate(ulong op1, ulong op2) - { - ulong result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); - return result; - } public static float AbsoluteDifference(float op1, float op2) => MathF.Abs(op1 - op2); @@ -2983,96 +4450,135 @@ private static double Reduce(Func reduceOp, double[] op1 public static float MinNumberAcross(float[] op1) => Reduce(MinNumber, op1); - private static ulong PolynomialMult(sbyte op1, sbyte op2) + private struct poly128_t { - ulong result = 0; - ulong extendedOp2 = (ulong)op2; + public ulong lo; + public ulong hi; - for (int i = 0; i < 8 * sizeof(sbyte); i++) + public static poly128_t operator ^(poly128_t op1, poly128_t op2) + { + op1.lo ^= op2.lo; + op1.hi ^= op2.hi; + + return op1; + } + + public static poly128_t operator <<(poly128_t val, int shiftAmount) { - if ((op1 & (1 << i)) != 0) + for (int i = 0; i < shiftAmount; i++) { - result ^= (extendedOp2 << i); + val.hi <<= 1; + + if ((val.lo & 0x8000000000000000U) != 0) + { + val.hi |= 1; + } + + val.lo <<= 1; } + + return val; } - return result; - } + public static implicit operator poly128_t(ulong lo) + { + poly128_t result = new poly128_t(); + result.lo = lo; + return result; + } - public static sbyte PolynomialMultiply(sbyte op1, sbyte op2) => (sbyte)PolynomialMult(op1, op2); + public static explicit operator poly128_t(long lo) + { + poly128_t result = new poly128_t(); + result.lo = (ulong)lo; + return result; + } + } - private static ulong PolynomialMult(byte op1, byte op2) + private static ushort PolynomialMult(byte op1, byte op2) { - ulong result = 0; - ulong extendedOp2 = (ulong)op2; + ushort result = default(ushort); + ushort extendedOp2 = (ushort)op2; for (int i = 0; i < 8 * sizeof(byte); i++) { - if ((op1 & (1 << i)) != 0) + if ((op1 & ((byte)1 << i)) != 0) { - result ^= (extendedOp2 << i); + result = (ushort)(result ^ (extendedOp2 << i)); } } return result; } - public static byte PolynomialMultiply(byte op1, byte op2) => (byte)PolynomialMult(op1, op2); - - public static bool ExtractAndNarrowHigh(int i, sbyte[] left, - short[] right, - sbyte[] result) - { - if (i < left.Length) - return left[i] != result[i]; - else - return (sbyte)right[i - left.Length] != result[i]; - } - public static bool ExtractAndNarrowHigh(int i, short[] left, - int[] right, - short[] result) + private static short PolynomialMult(sbyte op1, sbyte op2) { - if (i < left.Length) - return left[i] != result[i]; - else - return (short)right[i - left.Length] != result[i]; - } - public static bool ExtractAndNarrowHigh(int i, int[] left, - long[] right, - int[] result) - { - if (i < left.Length) - return left[i] != result[i]; - else - return (int)right[i - left.Length] != result[i]; - } - public static bool ExtractAndNarrowHigh(int i, byte[] left, - ushort[] right, - byte[] result) - { - if (i < left.Length) - return left[i] != result[i]; - else - return (byte)right[i - left.Length] != result[i]; + short result = default(short); + short extendedOp2 = (short)op2; + + for (int i = 0; i < 8 * sizeof(sbyte); i++) + { + if ((op1 & ((sbyte)1 << i)) != 0) + { + result = (short)(result ^ (extendedOp2 << i)); + } + } + + return result; } - public static bool ExtractAndNarrowHigh(int i, ushort[] left, - uint[] right, - ushort[] result) + + private static poly128_t PolynomialMult(ulong op1, ulong op2) { - if (i < left.Length) - return left[i] != result[i]; - else - return (ushort)right[i - left.Length] != result[i]; + poly128_t result = default(poly128_t); + poly128_t extendedOp2 = (poly128_t)op2; + + for (int i = 0; i < 8 * sizeof(ulong); i++) + { + if ((op1 & ((ulong)1 << i)) != 0) + { + result = (poly128_t)(result ^ (extendedOp2 << i)); + } + } + + return result; } - public static bool ExtractAndNarrowHigh(int i, uint[] left, - ulong[] right, - uint[] result) + + private static poly128_t PolynomialMult(long op1, long op2) { - if (i < left.Length) - return left[i] != result[i]; - else - return (uint)right[i - left.Length] != result[i]; + poly128_t result = default(poly128_t); + poly128_t extendedOp2 = (poly128_t)op2; + + for (int i = 0; i < 8 * sizeof(long); i++) + { + if ((op1 & ((long)1 << i)) != 0) + { + result = (poly128_t)(result ^ (extendedOp2 << i)); + } + } + + return result; } + + public static byte PolynomialMultiply(byte op1, byte op2) => (byte)PolynomialMult(op1, op2); + + public static ushort PolynomialMultiplyWidening(byte op1, byte op2) => PolynomialMult(op1, op2); + + public static ushort PolynomialMultiplyWideningUpper(byte[] op1, byte[] op2, int i) => PolynomialMultiplyWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + + public static sbyte PolynomialMultiply(sbyte op1, sbyte op2) => (sbyte)PolynomialMult(op1, op2); + + public static short PolynomialMultiplyWidening(sbyte op1, sbyte op2) => PolynomialMult(op1, op2); + + public static short PolynomialMultiplyWideningUpper(sbyte[] op1, sbyte[] op2, int i) => PolynomialMultiplyWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + + public static ulong PolynomialMultiplyWideningLo64(ulong op1, ulong op2) => PolynomialMult(op1, op2).lo; + + public static long PolynomialMultiplyWideningLo64(long op1, long op2) => (long)PolynomialMult(op1, op2).lo; + + public static ulong PolynomialMultiplyWideningHi64(ulong op1, ulong op2) => PolynomialMult(op1, op2).hi; + + public static long PolynomialMultiplyWideningHi64(long op1, long op2) => (long)PolynomialMult(op1, op2).hi; + public static sbyte ExtractVector(sbyte[] op1, sbyte[] op2, int op3, int i) => (op3 + i < op1.Length) ? op1[op3 + i] : op2[op3 + i - op1.Length]; public static sbyte Insert(sbyte[] op1, int op2, sbyte op3, int i) => (op2 != i) ? op1[i] : op3; diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt index b10aa7fe23a29..9c50cda89e592 100644 --- a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt @@ -11,7 +11,6 @@ using System; using System.Linq; -using System.Numerics; namespace JIT.HardwareIntrinsics.Arm { @@ -345,7 +344,7 @@ namespace JIT.HardwareIntrinsics.Arm public static <#= type.wide #> AddPairwiseWideningAndAdd(<#= type.wide #>[] op1, <#= type.name #>[] op2, int i) => (<#= type.wide #>)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); - private static <#= type.name #> HighNarrow(<#= type.wide #> op1, bool round) + private static <#= type.name #> HighNarrowing(<#= type.wide #> op1, bool round) { <#= type.wideUnsigned #> roundConst = 0; if (round) @@ -355,13 +354,13 @@ namespace JIT.HardwareIntrinsics.Arm return (<#= type.name #>)(((<#= type.wideUnsigned #>)op1 + roundConst) >> (8 * sizeof(<#= type.name #>))); } - public static <#= type.name #> AddReturningHighNarrow(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrow((<#= type.wide #>)(op1 + op2), round: false); + public static <#= type.name #> AddHighNarrowing(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrowing((<#= type.wide #>)(op1 + op2), round: false); - public static <#= type.name #> AddReturningHighNarrowUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : AddReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static <#= type.name #> AddHighNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : AddHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static <#= type.name #> AddReturningRoundedHighNarrow(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrow((<#= type.wide #>)(op1 + op2), round: true); + public static <#= type.name #> AddRoundedHighNarrowing(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrowing((<#= type.wide #>)(op1 + op2), round: true); - public static <#= type.wide #> AddReturningRoundedHighNarrowUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : AddReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static <#= type.wide #> AddRoundedHighNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : AddRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static <#= type.wide #> AddWidening(<#= type.name #> op1, <#= type.name #> op2) => (<#= type.wide #>)((<#= type.wide #>)op1 + (<#= type.wide #>)op2); @@ -371,6 +370,10 @@ namespace JIT.HardwareIntrinsics.Arm public static <#= type.wide #> AddWideningUpper(<#= type.wide #>[] op1, <#= type.name #>[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static <#= type.name #> ExtractNarrowing(<#= type.wide #> op1) => (<#= type.name #>)op1; + + public static <#= type.name #> ExtractNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); + public static <#= type.name #> FusedAddHalving(<#= type.name #> op1, <#= type.name #> op2) => (<#= type.name #>)((<#= type.wideUnsigned #>)((<#= type.wide #>)op1 + (<#= type.wide #>)op2) >> 1); public static <#= type.name #> FusedAddRoundedHalving(<#= type.name #> op1, <#= type.name #> op2) => (<#= type.name #>)((<#= type.wideUnsigned #>)((<#= type.wide #>)op1 + (<#= type.wide #>)op2 + 1) >> 1); @@ -389,13 +392,13 @@ namespace JIT.HardwareIntrinsics.Arm public static <#= type.wide #> MultiplyWideningUpperAndSubtract(<#= type.wide #>[] op1, <#= type.name #>[] op2, <#= type.name #>[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); - public static <#= type.name #> SubtractReturningHighNarrow(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrow((<#= type.wide #>)(op1 - op2), round: false); + public static <#= type.name #> SubtractHighNarrowing(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrowing((<#= type.wide #>)(op1 - op2), round: false); - public static <#= type.wide #> SubtractReturningHighNarrowUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static <#= type.wide #> SubtractHighNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); - public static <#= type.name #> SubtractReturningRoundedHighNarrow(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrow((<#= type.wide #>)(op1 - op2), round: true); + public static <#= type.name #> SubtractRoundedHighNarrowing(<#= type.wide #> op1, <#= type.wide #> op2) => HighNarrowing((<#= type.wide #>)(op1 - op2), round: true); - public static <#= type.wide #> SubtractReturningRoundedHighNarrowUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : SubtractReturningRoundedHighNarrow(op2[i - op1.Length], op3[i - op1.Length]); + public static <#= type.wide #> SubtractRoundedHighNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, <#= type.wide #>[] op3, int i) => i < op1.Length ? op1[i] : SubtractRoundedHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); public static <#= type.wide #> SubtractWidening(<#= type.name #> op1, <#= type.name #> op2) => (<#= type.wide #>)((<#= type.wide #>)op1 - (<#= type.wide #>)op2); @@ -405,48 +408,479 @@ namespace JIT.HardwareIntrinsics.Arm public static <#= type.wide #> SubtractWideningUpper(<#= type.wide #>[] op1, <#= type.name #>[] op2, int i) => SubtractWidening(op1[i], op2[i + op2.Length / 2]); + public static <#= type.wide #> ZeroExtendWidening(<#= type.name #> op1) => (<#= type.wide #>)(<#= type.wideUnsigned #>)op1; + + public static <#= type.wide #> ZeroExtendWideningUpper(<#= type.name #>[] op1, int i) => ZeroExtendWidening(op1[i + op1.Length / 2]); + <# } - foreach (string typeName in new string[] { "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong" }) + foreach (var type in new[] { (name: "sbyte", unsigned: "byte", wide: "short", wideUnsigned: "ushort"), + (name: "short", unsigned: "ushort", wide: "int", wideUnsigned: "uint"), + (name: "int", unsigned: "uint", wide: "long", wideUnsigned: "ulong") }) { #> - private static bool SatQ(BigInteger i, out <#= typeName #> result) + private static bool SignedSatQ(<#= type.wide #> val, out <#= type.name #> result) { bool saturated = false; - if (i > <#= typeName #>.MaxValue) + if (val > <#= type.name #>.MaxValue) { - result = <#= typeName #>.MaxValue; + result = <#= type.name #>.MaxValue; saturated = true; } - else if (i < <#= typeName #>.MinValue) + else if (val < <#= type.name #>.MinValue) { - result = <#= typeName #>.MinValue; + result = <#= type.name #>.MinValue; saturated = true; } else { - result = (<#= typeName #>)i; + result = (<#= type.name #>)val; } return saturated; } - public static <#= typeName #> AddSaturate(<#= typeName #> op1, <#= typeName #> op2) + private static bool SignedSatQ(<#= type.wide #> val, out <#= type.unsigned #> result) { - <#= typeName #> result; - SatQ(new BigInteger(op1) + new BigInteger(op2), out result); + bool saturated = false; + + if (val > <#= type.unsigned #>.MaxValue) + { + result = <#= type.unsigned #>.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (<#= type.unsigned #>)val; + } + + return saturated; + } + + private static bool UnsignedSatQ(<#= type.wide #> val, out <#= type.name #> result) + { + <#= type.unsigned #> res; + + bool saturated = UnsignedSatQ((<#= type.wideUnsigned #>)val, out res); + + result = (<#= type.name #>)res; + return saturated; + } + + private static bool UnsignedSatQ(<#= type.wideUnsigned #> val, out <#= type.unsigned #> result) + { + bool saturated = false; + + if (val > <#= type.unsigned #>.MaxValue) + { + result = <#= type.unsigned #>.MaxValue; + saturated = true; + } + else if (val < 0) + { + result = 0; + saturated = true; + } + else + { + result = (<#= type.unsigned #>)val; + } + + return saturated; + } + + public static <#= type.wide #> ShiftLeftLogicalWidening(<#= type.name #> op1, byte op2) => UnsignedShift((<#= type.wide #>)op1, (<#= type.wide #>)op2); + + public static <#= type.wideUnsigned #> ShiftLeftLogicalWidening(<#= type.unsigned #> op1, byte op2) => UnsignedShift((<#= type.wideUnsigned #>)op1, (<#= type.wide #>)op2); + + public static <#= type.wide #> ShiftLeftLogicalWideningUpper(<#= type.name #>[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static <#= type.wideUnsigned #> ShiftLeftLogicalWideningUpper(<#= type.unsigned #>[] op1, byte op2, int i) => ShiftLeftLogicalWidening(op1[i + op1.Length / 2], op2); + + public static <#= type.name #> ShiftRightArithmeticRoundedNarrowingSaturate(<#= type.wide #> op1, byte op2) + { + <#= type.name #> result; + + SignedSatQ(SignedShift(op1, (<#= type.wide #>)(-op2), rounding: true), out result); + + return result; + } + + public static <#= type.unsigned #> ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(<#= type.wide #> op1, byte op2) + { + <#= type.unsigned #> result; + + SignedSatQ(SignedShift(op1, (<#= type.wide #>)(-op2), rounding: true), out result); + + return result; + } + + public static <#= type.unsigned #> ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(<#= type.unsigned #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.unsigned #>)ShiftRightArithmeticRoundedNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightArithmeticRoundedNarrowingSaturateUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.name #>)ShiftRightArithmeticRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightArithmeticNarrowingSaturate(<#= type.wide #> op1, byte op2) + { + <#= type.name #> result; + + SignedSatQ(SignedShift(op1, (<#= type.wide #>)(-op2)), out result); + + return result; + } + + public static <#= type.unsigned #> ShiftRightArithmeticNarrowingSaturateUnsigned(<#= type.wide #> op1, byte op2) + { + <#= type.unsigned #> result; + + SignedSatQ(SignedShift(op1, (<#= type.wide #>)(-op2)), out result); + return result; } - public static <#= typeName #> SubtractSaturate(<#= typeName #> op1, <#= typeName #> op2) + public static <#= type.unsigned #> ShiftRightArithmeticNarrowingSaturateUnsignedUpper(<#= type.unsigned #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.unsigned #>)ShiftRightArithmeticNarrowingSaturateUnsigned(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightArithmeticNarrowingSaturateUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.name #>)ShiftRightArithmeticNarrowingSaturate(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightLogicalNarrowing(<#= type.wide #> op1, byte op2) => (<#= type.name #>)UnsignedShift(op1, (<#= type.wide #>)(-op2)); + + public static <#= type.unsigned #> ShiftRightLogicalNarrowing(<#= type.wideUnsigned #> op1, byte op2) => (<#= type.unsigned #>)UnsignedShift(op1, (<#= type.wide #>)(-op2)); + + public static <#= type.name #> ShiftRightLogicalRoundedNarrowing(<#= type.wide #> op1, byte op2) => (<#= type.name #>)UnsignedShift(op1, (<#= type.wide #>)(-op2), rounding: true); + + public static <#= type.unsigned #> ShiftRightLogicalRoundedNarrowing(<#= type.wideUnsigned #> op1, byte op2) => (<#= type.unsigned #>)UnsignedShift(op1, (<#= type.wide #>)(-op2), rounding: true); + + public static <#= type.name #> ShiftRightLogicalRoundedNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.name #>)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static <#= type.unsigned #> ShiftRightLogicalRoundedNarrowingUpper(<#= type.unsigned #>[] op1, <#= type.wideUnsigned #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.unsigned #>)ShiftRightLogicalRoundedNarrowing(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightLogicalRoundedNarrowingSaturate(<#= type.wide #> op1, byte op2) + { + <#= type.name #> result; + + UnsignedSatQ(UnsignedShift(op1, (<#= type.wide #>)(-op2), rounding: true), out result); + + return result; + } + + public static <#= type.unsigned #> ShiftRightLogicalRoundedNarrowingSaturate(<#= type.wideUnsigned #> op1, byte op2) + { + <#= type.unsigned #> result; + + UnsignedSatQ(UnsignedShift(op1, (<#= type.wide #>)(-op2), rounding: true), out result); + + return result; + } + + public static <#= type.name #> ShiftRightLogicalRoundedNarrowingSaturateUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.name #>)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static <#= type.unsigned #> ShiftRightLogicalRoundedNarrowingSaturateUpper(<#= type.unsigned #>[] op1, <#= type.wideUnsigned #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.unsigned #>)ShiftRightLogicalRoundedNarrowingSaturate(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightLogicalNarrowingUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.name #>)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static <#= type.unsigned #> ShiftRightLogicalNarrowingUpper(<#= type.unsigned #>[] op1, <#= type.wideUnsigned #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.unsigned #>)ShiftRightLogicalNarrowing(op2[i - op1.Length], op3); + + public static <#= type.name #> ShiftRightLogicalNarrowingSaturate(<#= type.wide #> op1, byte op2) + { + <#= type.name #> result; + + UnsignedSatQ(UnsignedShift(op1, (<#= type.wide #>)(-op2)), out result); + + return result; + } + + public static <#= type.unsigned #> ShiftRightLogicalNarrowingSaturate(<#= type.wideUnsigned #> op1, byte op2) + { + <#= type.unsigned #> result; + + UnsignedSatQ(UnsignedShift(op1, (<#= type.wide #>)(-op2)), out result); + + return result; + } + + public static <#= type.name #> ShiftRightLogicalNarrowingSaturateUpper(<#= type.name #>[] op1, <#= type.wide #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.name #>)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static <#= type.unsigned #> ShiftRightLogicalNarrowingSaturateUpper(<#= type.unsigned #>[] op1, <#= type.wideUnsigned #>[] op2, byte op3, int i) => i < op1.Length ? op1[i] : (<#= type.unsigned #>)ShiftRightLogicalNarrowingSaturate(op2[i - op1.Length], op3); + + public static <#= type.wide #> SignExtendWidening(<#= type.name #> op1) => op1; + + public static <#= type.wide #> SignExtendWideningUpper(<#= type.name #>[] op1, int i) => SignExtendWidening(op1[i + op1.Length / 2]); + +<# + } + + foreach (var type in new[] { (name: "sbyte", unsigned: "byte"), + (name: "short", unsigned: "ushort"), + (name: "int", unsigned: "uint"), + (name: "long", unsigned: "ulong") }) + { +#> + public static <#= type.name #> ShiftArithmetic(<#= type.name #> op1, <#= type.name #> op2) => SignedShift(op1, op2); + + public static <#= type.name #> ShiftArithmeticRounded(<#= type.name #> op1, <#= type.name #> op2) => SignedShift(op1, op2, rounding: true); + + public static <#= type.name #> ShiftArithmeticSaturate(<#= type.name #> op1, <#= type.name #> op2) => SignedShift(op1, op2, saturating: true); + + public static <#= type.name #> ShiftArithmeticRoundedSaturate(<#= type.name #> op1, <#= type.name #> op2) => SignedShift(op1, op2, rounding: true, saturating: true); + + private static <#= type.name #> SignedShift(<#= type.name #> op1, <#= type.name #> op2, bool rounding = false, bool saturating = false) + { + int shift = (sbyte)(op2 & 0xFF); + + <#= type.name #> rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((<#= type.name #>)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + <#= type.name #> result; + + bool addOvf; + + (result, addOvf) = AddOvf(op1, rndCns); + + if (addOvf) + { + result = (<#= type.name #>)ShiftOvf((<#= type.unsigned #>)result, shift).val; + } + else + { + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (saturating) + { + if (shiftOvf) + { + result = <#= type.name #>.MaxValue; + } + } + } + + return result; + } + + public static <#= type.name #> ShiftLeftLogical(<#= type.name #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)op2); + + public static <#= type.unsigned #> ShiftLeftLogical(<#= type.unsigned #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)op2); + + public static <#= type.name #> ShiftLeftLogicalSaturate(<#= type.name #> op1, byte op2) => SignedShift(op1, (<#= type.name #>)op2, saturating: true); + + public static <#= type.unsigned #> ShiftLeftLogicalSaturate(<#= type.unsigned #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)op2, saturating: true); + + public static <#= type.unsigned #> ShiftLeftLogicalSaturateUnsigned(<#= type.name #> op1, byte op2) => (<#= type.unsigned #>)UnsignedShift(op1, (<#= type.name #>)op2, saturating: true); + + public static <#= type.name #> ShiftLogical(<#= type.name #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2); + + public static <#= type.unsigned #> ShiftLogical(<#= type.unsigned #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2); + + public static <#= type.unsigned #> ShiftLogicalRounded(<#= type.unsigned #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2, rounding: true); + + public static <#= type.name #> ShiftLogicalRounded(<#= type.name #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2, rounding: true); + + public static <#= type.unsigned #> ShiftLogicalRoundedSaturate(<#= type.unsigned #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static <#= type.name #> ShiftLogicalRoundedSaturate(<#= type.name #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2, rounding: true, saturating: true); + + public static <#= type.name #> ShiftLogicalSaturate(<#= type.name #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2, saturating: true); + + public static <#= type.unsigned #> ShiftLogicalSaturate(<#= type.unsigned #> op1, <#= type.name #> op2) => UnsignedShift(op1, op2, saturating: true); + + public static <#= type.name #> ShiftRightArithmetic(<#= type.name #> op1, byte op2) => SignedShift(op1, (<#= type.name #>)(-op2)); + + public static <#= type.name #> ShiftRightArithmeticAdd(<#= type.name #> op1, <#= type.name #> op2, byte op3) => (<#= type.name #>)(op1 + ShiftRightArithmetic(op2, op3)); + + public static <#= type.name #> ShiftRightArithmeticRounded(<#= type.name #> op1, byte op2) => SignedShift(op1, (<#= type.name #>)(-op2), rounding: true); + + public static <#= type.name #> ShiftRightArithmeticRoundedAdd(<#= type.name #> op1, <#= type.name #> op2, byte op3) => (<#= type.name #>)(op1 + ShiftRightArithmeticRounded(op2, op3)); + + public static <#= type.name #> ShiftRightLogical(<#= type.name #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)(-op2)); + + public static <#= type.unsigned #> ShiftRightLogical(<#= type.unsigned #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)(-op2)); + + public static <#= type.name #> ShiftRightLogicalAdd(<#= type.name #> op1, <#= type.name #> op2, byte op3) => (<#= type.name #>)(op1 + ShiftRightLogical(op2, op3)); + + public static <#= type.unsigned #> ShiftRightLogicalAdd(<#= type.unsigned #> op1, <#= type.unsigned #> op2, byte op3) => (<#= type.unsigned #>)(op1 + ShiftRightLogical(op2, op3)); + + public static <#= type.name #> ShiftRightLogicalRounded(<#= type.name #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)(-op2), rounding: true); + + public static <#= type.unsigned #> ShiftRightLogicalRounded(<#= type.unsigned #> op1, byte op2) => UnsignedShift(op1, (<#= type.name #>)(-op2), rounding: true); + + public static <#= type.name #> ShiftRightLogicalRoundedAdd(<#= type.name #> op1, <#= type.name #> op2, byte op3) => (<#= type.name #>)(op1 + ShiftRightLogicalRounded(op2, op3)); + + public static <#= type.unsigned #> ShiftRightLogicalRoundedAdd(<#= type.unsigned #> op1, <#= type.unsigned #> op2, byte op3) => (<#= type.unsigned #>)(op1 + ShiftRightLogicalRounded(op2, op3)); + + private static <#= type.unsigned #> UnsignedShift(<#= type.unsigned #> op1, <#= type.name #> op2, bool rounding = false, bool saturating = false) { - <#= typeName #> result; - SatQ(new BigInteger(op1) - new BigInteger(op2), out result); + int shift = (sbyte)(op2 & 0xFF); + + <#= type.unsigned #> rndCns = 0; + + if (rounding) + { + bool ovf; + + (rndCns, ovf) = ShiftOvf((<#= type.unsigned #>)1, -shift-1); + + if (ovf) + { + return 0; + } + } + + (<#= type.unsigned #> result, bool addOvf) = AddOvf(op1, rndCns); + + bool shiftOvf; + + (result, shiftOvf) = ShiftOvf(result, shift); + + if (addOvf) + { + <#= type.unsigned #> shiftedCarry = ShiftOvf((<#= type.unsigned #>)1, 8 * sizeof(<#= type.unsigned #>) + shift).val; + result = (<#= type.unsigned #>)(result | shiftedCarry); + } + + if (saturating) + { + if (shiftOvf) + { + result = <#= type.unsigned #>.MaxValue; + } + } + return result; } + private static <#= type.name #> UnsignedShift(<#= type.name #> op1, <#= type.name #> op2, bool rounding = false, bool saturating = false) => (<#= type.name #>)UnsignedShift((<#= type.unsigned #>)op1, op2, rounding, saturating); + + private static (<#= type.name #> val, bool ovf) AddOvf(<#= type.name #> op1, <#= type.name #> op2) + { + <#= type.name #> result = (<#= type.name #>)(op1 + op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 > 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 < 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (<#= type.unsigned #> val, bool ovf) AddOvf(<#= type.unsigned #> op1, <#= type.unsigned #> op2) + { + <#= type.unsigned #> result = (<#= type.unsigned #>)(op1 + op2); + + bool ovf = (result < op1); + + return (result, ovf); + } + + private static (<#= type.name #> val, bool ovf) SubtractOvf(<#= type.name #> op1, <#= type.name #> op2) + { + <#= type.name #> result = (<#= type.name #>)(op1 - op2); + + bool ovf = false; + + if ((op1 > 0) && (op2 < 0)) + { + ovf = (result < 0); + } + else if ((op1 < 0) && (op2 > 0)) + { + ovf = (result > 0); + } + + return (result, ovf); + } + + private static (<#= type.unsigned #> val, bool ovf) SubtractOvf(<#= type.unsigned #> op1, <#= type.unsigned #> op2) + { + <#= type.unsigned #> result = (<#= type.unsigned #>)(op1 - op2); + + bool ovf = (op1 < op2); + + return (result, ovf); + } + + public static <#= type.name #> AddSaturate(<#= type.name #> op1, <#= type.name #> op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? (result > 0 ? <#= type.name #>.MinValue : <#= type.name #>.MaxValue) : result; + } + + public static <#= type.unsigned #> AddSaturate(<#= type.unsigned #> op1, <#= type.unsigned #> op2) + { + var (result, ovf) = AddOvf(op1, op2); + return ovf ? <#= type.unsigned #>.MaxValue : result; + } + + public static <#= type.name #> SubtractSaturate(<#= type.name #> op1, <#= type.name #> op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? (result > 0 ? <#= type.name #>.MinValue : <#= type.name #>.MaxValue) : result; + } + + public static <#= type.unsigned #> SubtractSaturate(<#= type.unsigned #> op1, <#= type.unsigned #> op2) + { + var (result, ovf) = SubtractOvf(op1, op2); + return ovf ? <#= type.unsigned #>.MinValue : result; + } + +<# + } + + foreach (string typeName in new string[] { "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong" }) + { +#> + + private static (<#= typeName #> val, bool ovf) ShiftOvf(<#= typeName #> value, int shift) + { + <#= typeName #> result = value; + + bool ovf = false; + <#= typeName #> msb = 1; + msb = (<#= typeName #>)(msb << (8 * sizeof(<#= typeName #>) - 1)); + + for (int i = 0; i < shift; i++) + { + ovf = ovf || ((result & msb) != 0); + result <<= 1; + } + + for (int i = 0; i > shift; i--) + { + result >>= 1; + } + + if ((value > 0) && (result < 0)) + { + ovf = true; + } + + return (result, ovf); + } + + <# } @@ -680,51 +1114,100 @@ namespace JIT.HardwareIntrinsics.Arm public static float MinNumberAcross(float[] op1) => Reduce(MinNumber, op1); + private struct poly128_t + { + public ulong lo; + public ulong hi; + + public static poly128_t operator ^(poly128_t op1, poly128_t op2) + { + op1.lo ^= op2.lo; + op1.hi ^= op2.hi; + + return op1; + } + + public static poly128_t operator <<(poly128_t val, int shiftAmount) + { + for (int i = 0; i < shiftAmount; i++) + { + val.hi <<= 1; + + if ((val.lo & 0x8000000000000000U) != 0) + { + val.hi |= 1; + } + + val.lo <<= 1; + } + + return val; + } + + public static implicit operator poly128_t(ulong lo) + { + poly128_t result = new poly128_t(); + result.lo = lo; + return result; + } + + public static explicit operator poly128_t(long lo) + { + poly128_t result = new poly128_t(); + result.lo = (ulong)lo; + return result; + } + } + <# - foreach (string typeName in new string[] { "sbyte", "byte" }) + foreach (var type in new[] { (name: "byte", wide: "ushort"), + (name: "sbyte", wide: "short"), + (name: "ulong", wide: "poly128_t"), + (name: "long", wide: "poly128_t") }) { #> - private static ulong PolynomialMult(<#= typeName #> op1, <#= typeName #> op2) + private static <#= type.wide #> PolynomialMult(<#= type.name #> op1, <#= type.name #> op2) { - ulong result = 0; - ulong extendedOp2 = (ulong)op2; + <#= type.wide #> result = default(<#= type.wide #>); + <#= type.wide #> extendedOp2 = (<#= type.wide #>)op2; - for (int i = 0; i < 8 * sizeof(<#= typeName #>); i++) + for (int i = 0; i < 8 * sizeof(<#= type.name #>); i++) { - if ((op1 & (1 << i)) != 0) + if ((op1 & ((<#= type.name #>)1 << i)) != 0) { - result ^= (extendedOp2 << i); + result = (<#= type.wide #>)(result ^ (extendedOp2 << i)); } } return result; } - public static <#= typeName #> PolynomialMultiply(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)PolynomialMult(op1, op2); - <# } - foreach (var type in new[] { (small: "sbyte", wide: "short"), - (small: "short", wide: "int"), - (small: "int", wide: "long"), - (small: "byte", wide: "ushort"), - (small: "ushort", wide: "uint"), - (small: "uint", wide: "ulong") }) + foreach (var type in new[] { (name: "byte", wide: "ushort"), + (name: "sbyte", wide: "short") }) { + #> - public static bool ExtractAndNarrowHigh(int i, <#= type.small #>[] left, - <#= type.wide #>[] right, - <#= type.small #>[] result) - { - if (i < left.Length) - return left[i] != result[i]; - else - return (<#= type.small #>)right[i - left.Length] != result[i]; - } + public static <#= type.name #> PolynomialMultiply(<#= type.name #> op1, <#= type.name #> op2) => (<#= type.name #>)PolynomialMult(op1, op2); + + public static <#= type.wide #> PolynomialMultiplyWidening(<#= type.name #> op1, <#= type.name #> op2) => PolynomialMult(op1, op2); + + public static <#= type.wide #> PolynomialMultiplyWideningUpper(<#= type.name #>[] op1, <#= type.name #>[] op2, int i) => PolynomialMultiplyWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); + <# } +#> + public static ulong PolynomialMultiplyWideningLo64(ulong op1, ulong op2) => PolynomialMult(op1, op2).lo; + public static long PolynomialMultiplyWideningLo64(long op1, long op2) => (long)PolynomialMult(op1, op2).lo; + + public static ulong PolynomialMultiplyWideningHi64(ulong op1, ulong op2) => PolynomialMult(op1, op2).hi; + + public static long PolynomialMultiplyWideningHi64(long op1, long op2) => (long)PolynomialMult(op1, op2).hi; + +<# foreach (string typeName in new string[] { "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "double" }) { #> diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmBinaryOpTestTemplate.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmBinaryOpTestTemplate.template new file mode 100644 index 0000000000000..be123b5522add --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmBinaryOpTestTemplate.template @@ -0,0 +1,409 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void {TestName}() + { + var test = new ImmBinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ImmBinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(ImmBinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, {Imm}); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly byte Imm = {Imm}; + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private static {Op1VectorType}<{Op1BaseType}> _clsVar1; + private static {Op2VectorType}<{Op2BaseType}> _clsVar2; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + + private DataTable _dataTable; + + static ImmBinaryOpTest__{TestName}() + { + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _clsVar1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _clsVar2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + } + + public ImmBinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = {Isa}.{Method}( + _clsVar1, + _clsVar2, + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var secondOp = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(firstOp, secondOp, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)); + var secondOp = {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)); + var result = {Isa}.{Method}(firstOp, secondOp, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, secondOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new ImmBinaryOpTest__{TestName}(); + var result = {Isa}.{Method}(test._fld1, test._fld2, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> firstOp, {Op2VectorType}<{Op2BaseType}> secondOp, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), secondOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* firstOp, void* secondOp, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(secondOp), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>.{Imm}, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmOpTestTemplate.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmOpTestTemplate.template new file mode 100644 index 0000000000000..77a6503ac0c0f --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmOpTestTemplate.template @@ -0,0 +1,171 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void {TestName}() + { + var test = new {TemplateName}OpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario(); + + // Validates calling via reflection works + test.RunReflectionScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}OpTest__{TestName} + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({RetBaseType}[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private DataTable _dataTable; + + public {TemplateName}OpTest__{TestName}() + { + Succeeded = true; + + _dataTable = new DataTable(new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario)); + + var result = {Isa}.{Method}( + ({Op1BaseType}){Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunReflectionScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}) }) + .Invoke(null, new object[] { + ({Op1BaseType}){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult(void* result, [CallerMemberName] string method = "") + { + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + ValidateResult(outArray, method); + } + + private void ValidateResult({RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Imm}): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmUnaryOpTestTemplate.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmUnaryOpTestTemplate.template new file mode 100644 index 0000000000000..a670c6e795d26 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_ImmUnaryOpTestTemplate.template @@ -0,0 +1,493 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void {TestName}() + { + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates calling via reflection works, using Load + test.RunReflectionScenario_Load(); + } + + // Validates passing a static member works + test.RunClsVarScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing a static member works, using pinning and Load + test.RunClsVarScenario_Load(); + } + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing a local works, using Load + test.RunLclVarScenario_Load(); + } + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing the field of a local class works, using pinning and Load + test.RunClassLclFldScenario_Load(); + } + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing an instance member of a class works, using pinning and Load + test.RunClassFldScenario_Load(); + } + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing the field of a local struct works, using pinning and Load + test.RunStructLclFldScenario_Load(); + } + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + if ({LoadIsa}.IsSupported) + { + // Validates passing an instance member of a struct works, using pinning and Load + test.RunStructFldScenario_Load(); + } + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}UnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray; + private byte[] outArray; + + private GCHandle inHandle; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray = inArray.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle = GCHandle.Alloc(this.inArray, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArrayPtr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), (uint)sizeOfinArray); + } + + public void* inArrayPtr => Align((byte*)(inHandle.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}UnaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld, {Imm}); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + + public void RunStructFldScenario_Load({TemplateName}UnaryOpTest__{TestName} testClass) + { + fixed ({Op1VectorType}<{Op1BaseType}>* pFld = &_fld) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld)), + {Imm} + ); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly byte Imm = {Imm}; + + private static {Op1BaseType}[] _data = new {Op1BaseType}[Op1ElementCount]; + + private static {Op1VectorType}<{Op1BaseType}> _clsVar; + + private {Op1VectorType}<{Op1BaseType}> _fld; + + private DataTable _dataTable; + + static {TemplateName}UnaryOpTest__{TestName}() + { + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _clsVar), ref Unsafe.As<{Op1BaseType}, byte>(ref _data[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + } + + public {TemplateName}UnaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = {Isa}.{Method}( + _clsVar, + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load)); + + fixed ({Op1VectorType}<{Op1BaseType}>* pClsVar = &_clsVar) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pClsVar)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var firstOp = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr); + var result = {Isa}.{Method}(firstOp, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load)); + + var firstOp = {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)); + var result = {Isa}.{Method}(firstOp, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(firstOp, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new {TemplateName}UnaryOpTest__{TestName}(); + var result = {Isa}.{Method}(test._fld, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); + + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + fixed ({Op1VectorType}<{Op1BaseType}>* pFld = &test._fld) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load)); + + fixed ({Op1VectorType}<{Op1BaseType}>* pFld = &_fld) + { + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(pFld)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(&test._fld)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunStructFldScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario_Load)); + + var test = TestStruct.Create(); + test.RunStructFldScenario_Load(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> firstOp, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), firstOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray[0]), ref Unsafe.AsRef(firstOp), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Imm}): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_UnaryOpScalarTestTemplate.template b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_UnaryOpScalarTestTemplate.template new file mode 100644 index 0000000000000..b80651df1c8e3 --- /dev/null +++ b/src/coreclr/tests/src/JIT/HardwareIntrinsics/Arm/Shared/_UnaryOpScalarTestTemplate.template @@ -0,0 +1,286 @@ +// 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. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + private static void {TestName}() + { + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a static member works + test.RunClsVarScenario(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing the field of a local class works + test.RunClassLclFldScenario(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}UnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] outArray; + + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({RetBaseType}[] outArray, int alignment) + { + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.outArray = new byte[alignment * 2]; + + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + } + + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1BaseType} _fld; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + testStruct._fld = {NextValueOp1}; + return testStruct; + } + + public void RunStructFldScenario({TemplateName}UnaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld); + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType} _data; + + private static {Op1BaseType} _clsVar; + + private {Op1BaseType} _fld; + + private DataTable _dataTable; + + static {TemplateName}UnaryOpTest__{TestName}() + { + _clsVar = {NextValueOp1}; + } + + public {TemplateName}UnaryOpTest__{TestName}() + { + Succeeded = true; + + _fld = {NextValueOp1}; + _data = {NextValueOp1}; + + _dataTable = new DataTable(new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data)) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_data, _dataTable.outArrayPtr); + } + + public void RunClsVarScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); + + var result = {Isa}.{Method}( + _clsVar + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_clsVar, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data)); + var result = {Isa}.{Method}(data); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(data, _dataTable.outArrayPtr); + } + + public void RunClassLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); + + var test = new {TemplateName}UnaryOpTest__{TestName}(); + var result = {Isa}.{Method}(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1BaseType} data, void* result, [CallerMemberName] string method = "") + { + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + ValidateResult(data, outArray, method); + } + + private void ValidateResult({Op1BaseType} data, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}): {Method} failed:"); + TestLibrary.TestFramework.LogInformation($" data: {data}"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.cs new file mode 100644 index 0000000000000..eb28530e54270 --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.cs @@ -0,0 +1,35 @@ +// 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; + +public class GitHub_36905 +{ + public static int Main() + { + bool success = true; + + Vector3 a = new Vector3(1.0f, 2.0f, 3.0f); + Vector3 b = new Vector3(1.0f, 2.0f, 3.0f); + + success &= ValidateResult(a == b, expected: true); + success &= ValidateResult(a != b, expected: false); + + Vector3 c = new Vector3(1.0f, 2.0f, 3.0f); + Vector3 d = new Vector3(10.0f, 2.0f, 3.0f); + + success &= ValidateResult(c == d, expected: false); + success &= ValidateResult(c != d, expected: true); + + return success ? 100 : 0; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static bool ValidateResult(bool actual, bool expected) + { + return actual == expected; + } +} diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj new file mode 100644 index 0000000000000..19781e26c20d8 --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj @@ -0,0 +1,10 @@ + + + Exe + + True + + + + + diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.cs new file mode 100644 index 0000000000000..4624bc4def35f --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.cs @@ -0,0 +1,60 @@ +// 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; + +class C0 +{ + public sbyte F4; +} + +#pragma warning disable 0649 + +struct S1 +{ + public C0 F0; + public bool F8; + public int F9; +} + +public class Runtime_36468 +{ + static S1 s_3; + public static int Main() + { + int result = -1; + try + { + M0(); + } + catch (NullReferenceException) + { + result = 100; + } + + return result; + } + + static void M0() + { + ulong var0 = 0; + try + { + if (M2(ref s_3, s_3)) + { + var0 -= 0; + } + } + finally + { + int var1 = s_3.F9; + } + } + + static bool M2(ref S1 arg0, S1 arg1) + { + sbyte var0 = arg1.F0.F4--; + return arg0.F8; + } +} diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj new file mode 100644 index 0000000000000..5d49e8d49736f --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj @@ -0,0 +1,13 @@ + + + Exe + + + + True + True + + + + + diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.cs new file mode 100644 index 0000000000000..bdc98c0cedf2e --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.cs @@ -0,0 +1,56 @@ +// 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; + +// Finally cloning creates new throw merge candidates that +// need to be properly counted. + +class Runtime_36584 +{ + static int x; + + static void ThrowHelper() + { + throw new Exception(); + } + + public static int Main() + { + x = 100; + + if (x != 100) + { + ThrowHelper(); + } + + if (x != 100) + { + ThrowHelper(); + } + + if (x != 100) + { + try + { + x++; + } + // This finally will be cloned + finally + { + if (x != 100) + { + ThrowHelper(); + } + + if (x != 100) + { + ThrowHelper(); + } + } + } + + return x; + } +} diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj new file mode 100644 index 0000000000000..5d49e8d49736f --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj @@ -0,0 +1,13 @@ + + + Exe + + + + True + True + + + + + diff --git a/src/coreclr/tests/src/JIT/opt/InstructionCombining/ArrayLengthArithmetic.cs b/src/coreclr/tests/src/JIT/opt/InstructionCombining/ArrayLengthArithmetic.cs new file mode 100644 index 0000000000000..4ac6ef069a3dd --- /dev/null +++ b/src/coreclr/tests/src/JIT/opt/InstructionCombining/ArrayLengthArithmetic.cs @@ -0,0 +1,143 @@ +// 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; + +public class ArrayLengthArithmeticTests +{ + private static int returnCode = 100; + + public static int Main(string[] args) + { + for (int arrayLength = 0; arrayLength < 100; arrayLength++) + { + var array = new int[arrayLength]; + + if (arrayLength == 0) + { + Expect(() => ArrayLengthDiv_cns0(array)); + Expect(() => ArrayLengthDiv_var0(array)); + Expect(() => ArrayLengthMod_cns0(array)); + Expect(() => ArrayLengthMod_var0(array)); + } + + // Array.Length / cns == Array.Length / ToVar(cns) + CompareResults(ArrayLengthDiv_cns1(array), ArrayLengthDiv_var1(array)); + CompareResults(ArrayLengthDiv_cns2(array), ArrayLengthDiv_var2(array)); + CompareResults(ArrayLengthDiv_cns3(array), ArrayLengthDiv_var3(array)); + CompareResults(ArrayLengthDiv_cns4(array), ArrayLengthDiv_var4(array)); + CompareResults(ArrayLengthDiv_cns5(array), ArrayLengthDiv_var5(array)); + CompareResults(ArrayLengthDiv_cns8(array), ArrayLengthDiv_var8(array)); + CompareResults(ArrayLengthDiv_cns10(array), ArrayLengthDiv_var10(array)); + CompareResults(ArrayLengthDiv_cnsMaxValuen1(array), ArrayLengthDiv_varMaxValuen1(array)); + CompareResults(ArrayLengthDiv_cnsMaxValue(array), ArrayLengthDiv_varMaxValue(array)); + CompareResults(ArrayLengthDiv_cnsn1(array), ArrayLengthDiv_varn1(array)); + CompareResults(ArrayLengthDiv_cnsn2(array), ArrayLengthDiv_varn2(array)); + CompareResults(ArrayLengthDiv_cnsMinValue(array), ArrayLengthDiv_varMinValue(array)); + + // Array.Length % cns == Array.Length % ToVar(cns) + CompareResults(ArrayLengthMod_cns1(array), ArrayLengthMod_var1(array)); + CompareResults(ArrayLengthMod_cns2(array), ArrayLengthMod_var2(array)); + CompareResults(ArrayLengthMod_cns3(array), ArrayLengthMod_var3(array)); + CompareResults(ArrayLengthMod_cns4(array), ArrayLengthMod_var4(array)); + CompareResults(ArrayLengthMod_cns5(array), ArrayLengthMod_var5(array)); + CompareResults(ArrayLengthMod_cns8(array), ArrayLengthMod_var8(array)); + CompareResults(ArrayLengthMod_cns10(array), ArrayLengthMod_var10(array)); + CompareResults(ArrayLengthMod_cnsMaxValuen1(array), ArrayLengthMod_varMaxValuen1(array)); + CompareResults(ArrayLengthMod_cnsMaxValue(array), ArrayLengthMod_varMaxValue(array)); + CompareResults(ArrayLengthMod_cnsn1(array), ArrayLengthMod_varn1(array)); + CompareResults(ArrayLengthMod_cnsn2(array), ArrayLengthMod_varn2(array)); + CompareResults(ArrayLengthMod_cnsMinValue(array), ArrayLengthMod_varMinValue(array)); + } + + return returnCode; + } + + // Array.Length / cns + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns0(int[] array) => array.Length / 0; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns1(int[] array) => array.Length / 1; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns2(int[] array) => array.Length / 2; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns3(int[] array) => array.Length / 3; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns4(int[] array) => array.Length / 4; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns5(int[] array) => array.Length / 5; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns8(int[] array) => array.Length / 8; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cns10(int[] array) => array.Length / 10; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cnsMaxValuen1(int[] array) => array.Length / (int.MaxValue - 1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cnsMaxValue(int[] array) => array.Length / int.MaxValue; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cnsn1(int[] array) => array.Length / -1; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cnsn2(int[] array) => array.Length / -2; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_cnsMinValue(int[] array) => array.Length / int.MinValue; + + // Array.Length / variable + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var0(int[] array) => array.Length / ToVar(0); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var1(int[] array) => array.Length / ToVar(1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var2(int[] array) => array.Length / ToVar(2); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var3(int[] array) => array.Length / ToVar(3); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var4(int[] array) => array.Length / ToVar(4); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var5(int[] array) => array.Length / ToVar(5); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var8(int[] array) => array.Length / ToVar(8); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_var10(int[] array) => array.Length / ToVar(10); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_varMaxValuen1(int[] array) => array.Length / ToVar(int.MaxValue - 1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_varMaxValue(int[] array) => array.Length / ToVar(int.MaxValue); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_varn1(int[] array) => array.Length / ToVar(-1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_varn2(int[] array) => array.Length / ToVar(-2); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthDiv_varMinValue(int[] array) => array.Length / ToVar(int.MinValue); + + // Array.Length % cns + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns0(int[] array) => array.Length % 0; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns1(int[] array) => array.Length % 1; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns2(int[] array) => array.Length % 2; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns3(int[] array) => array.Length % 3; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns4(int[] array) => array.Length % 4; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns5(int[] array) => array.Length % 5; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns8(int[] array) => array.Length % 8; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cns10(int[] array) => array.Length % 10; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cnsMaxValuen1(int[] array) => array.Length % (int.MaxValue - 1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cnsMaxValue(int[] array) => array.Length % int.MaxValue; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cnsn1(int[] array) => array.Length % -1; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cnsn2(int[] array) => array.Length % -2; + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_cnsMinValue(int[] array) => array.Length % int.MinValue; + + // Array.Length % variable + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var0(int[] array) => array.Length % ToVar(0); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var1(int[] array) => array.Length % ToVar(1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var2(int[] array) => array.Length % ToVar(2); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var3(int[] array) => array.Length % ToVar(3); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var4(int[] array) => array.Length % ToVar(4); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var5(int[] array) => array.Length % ToVar(5); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var8(int[] array) => array.Length % ToVar(8); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_var10(int[] array) => array.Length % ToVar(10); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_varMaxValuen1(int[] array) => array.Length % ToVar(int.MaxValue - 1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_varMaxValue(int[] array) => array.Length % ToVar(int.MaxValue); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_varn1(int[] array) => array.Length % ToVar(-1); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_varn2(int[] array) => array.Length % ToVar(-2); + [MethodImpl(MethodImplOptions.NoInlining)] private static int ArrayLengthMod_varMinValue(int[] array) => array.Length % ToVar(int.MinValue); + + private static void Expect(Action action, [CallerLineNumber] int line = 0) where T : Exception + { + try + { + action(); + } + catch (T) + { + return; + } + Console.WriteLine($"{typeof(T).Name} was expected, L{line}"); + returnCode++; + } + + private static void CompareResults(int a, int b, [CallerLineNumber] int line = 0) + { + if (a != b) + { + Console.WriteLine($"{a} != {b}, L{line}"); + returnCode++; + } + } + + // cns to var + [MethodImpl(MethodImplOptions.NoInlining)] private static T ToVar(T t) => t; +} \ No newline at end of file diff --git a/src/coreclr/tests/src/JIT/opt/InstructionCombining/ArrayLengthArithmetic.csproj b/src/coreclr/tests/src/JIT/opt/InstructionCombining/ArrayLengthArithmetic.csproj new file mode 100644 index 0000000000000..10e5a51b6a338 --- /dev/null +++ b/src/coreclr/tests/src/JIT/opt/InstructionCombining/ArrayLengthArithmetic.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflow.cs b/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflow.cs index 2cb9aa6ae82f4..3a4a363c7425b 100644 --- a/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflow.cs +++ b/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflow.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; using System.Threading; +using System.Runtime.CompilerServices; namespace TestStackOverflow { @@ -67,39 +68,47 @@ struct LargeStruct65536 } class Program { + [MethodImpl(MethodImplOptions.NoInlining)] static void InfiniteRecursionA() { InfiniteRecursionB(); } + [MethodImpl(MethodImplOptions.NoInlining)] static void InfiniteRecursionB() { InfiniteRecursionC(); } + + [MethodImpl(MethodImplOptions.NoInlining)] static void InfiniteRecursionC() { InfiniteRecursionA(); } + [MethodImpl(MethodImplOptions.NoInlining)] static void InfiniteRecursionA2() { LargeStruct65536 s; InfiniteRecursionB2(); } + [MethodImpl(MethodImplOptions.NoInlining)] static void InfiniteRecursionB2() { LargeStruct65536 s; InfiniteRecursionC2(); } + [MethodImpl(MethodImplOptions.NoInlining)] static void InfiniteRecursionC2() { LargeStruct65536 s; InfiniteRecursionA2(); } - static void MainThreadTest(bool smallframe) + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test(bool smallframe) { if (smallframe) { @@ -116,16 +125,7 @@ static void SecondaryThreadsTest(bool smallframe) Thread[] threads = new Thread[32]; for (int i = 0; i < threads.Length; i++) { - threads[i] = new Thread(() => { - if (smallframe) - { - InfiniteRecursionA(); - } - else - { - InfiniteRecursionA2(); - } - }); + threads[i] = new Thread(() => Test(smallframe)); threads[i].Start(); } @@ -144,7 +144,7 @@ static void Main(string[] args) } else if (args[1] == "main") { - MainThreadTest(smallframe); + Test(smallframe); } } } diff --git a/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflowtester.cs b/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflowtester.cs index f30305658c100..d8326ff6666bf 100644 --- a/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflowtester.cs +++ b/src/coreclr/tests/src/baseservices/exceptions/stackoverflow/stackoverflowtester.cs @@ -77,6 +77,12 @@ static bool TestStackOverflowSmallFrameMainThread() return false; } + if (!lines.Exists(elem => elem.EndsWith("TestStackOverflow.Program.Test(Boolean)"))) + { + Console.WriteLine("Missing \"Test\" method frame"); + return false; + } + if (!lines.Exists(elem => elem.EndsWith("at TestStackOverflow.Program.InfiniteRecursionA()"))) { Console.WriteLine("Missing \"InfiniteRecursionA\" method frame"); @@ -112,9 +118,9 @@ static bool TestStackOverflowLargeFrameMainThread() return false; } - if (!lines.Exists(elem => elem.EndsWith("TestStackOverflow.Program.MainThreadTest(Boolean)"))) + if (!lines.Exists(elem => elem.EndsWith("TestStackOverflow.Program.Test(Boolean)"))) { - Console.WriteLine("Missing \"MainThreadTest\" method frame"); + Console.WriteLine("Missing \"Test\" method frame"); return false; } @@ -147,9 +153,9 @@ static bool TestStackOverflowSmallFrameSecondaryThread() List lines; if (TestStackOverflow("stackoverflow", "smallframe secondary", out lines)) { - if (!lines[lines.Count - 1].EndsWith("at System.Threading.ThreadHelper.ThreadStart()")) + if (!lines.Exists(elem => elem.EndsWith("at TestStackOverflow.Program.Test(Boolean)"))) { - Console.WriteLine("Missing \"System.Threading.ThreadHelper.ThreadStart\" method frame at the last line"); + Console.WriteLine("Missing \"TestStackOverflow.Program.Test\" method frame"); return false; } @@ -182,9 +188,9 @@ static bool TestStackOverflowLargeFrameSecondaryThread() List lines; if (TestStackOverflow("stackoverflow", "largeframe secondary", out lines)) { - if (!lines[lines.Count - 1].EndsWith("at System.Threading.ThreadHelper.ThreadStart()")) + if (!lines.Exists(elem => elem.EndsWith("at TestStackOverflow.Program.Test(Boolean)"))) { - Console.WriteLine("Missing \"System.Threading.ThreadHelper.ThreadStart\" method frame at the last line"); + Console.WriteLine("Missing \"TestStackOverflow.Program.Test\" method frame"); return false; } diff --git a/src/coreclr/tests/src/baseservices/mono/runningmono.cs b/src/coreclr/tests/src/baseservices/mono/runningmono.cs new file mode 100644 index 0000000000000..1a6a4151a38b6 --- /dev/null +++ b/src/coreclr/tests/src/baseservices/mono/runningmono.cs @@ -0,0 +1,26 @@ +// 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; + +namespace TestRunningMono +{ + class Program + { + public static int Main(string[] args) + { + const int Pass = 100, Fail = 1; + bool isMono = typeof(object).Assembly.GetType("Mono.RuntimeStructs") != null; + + if(isMono) + { + return Pass; + } + else + { + return Fail; + } + } + } +} + diff --git a/src/coreclr/tests/src/baseservices/mono/runningmono.csproj b/src/coreclr/tests/src/baseservices/mono/runningmono.csproj new file mode 100644 index 0000000000000..c560a028e3b8c --- /dev/null +++ b/src/coreclr/tests/src/baseservices/mono/runningmono.csproj @@ -0,0 +1,11 @@ + + + Exe + false + 0 + + + + + + diff --git a/src/coreclr/tests/src/profiler/common/ProfilerTestRunner.cs b/src/coreclr/tests/src/profiler/common/ProfilerTestRunner.cs index d425d4f544cf6..6b5bb26e0fa59 100644 --- a/src/coreclr/tests/src/profiler/common/ProfilerTestRunner.cs +++ b/src/coreclr/tests/src/profiler/common/ProfilerTestRunner.cs @@ -15,7 +15,7 @@ namespace Profiler.Tests public enum ProfileeOptions { None = 0, - DisableTieredCompilation, + OptimizationSensitive, NoStartupAttach } @@ -41,10 +41,12 @@ public class ProfilerTestRunner envVars.Add("CORECLR_PROFILER", "{" + profilerClsid + "}"); } - if (profileeOptions.HasFlag(ProfileeOptions.DisableTieredCompilation)) + if (profileeOptions.HasFlag(ProfileeOptions.OptimizationSensitive)) { - Console.WriteLine("Disabling tiered compilation."); + Console.WriteLine("Disabling tiered compilation, jitstress, and minopts."); envVars.Add("COMPlus_TieredCompilation", "0"); + envVars.Add("COMPlus_JitStress", "0"); + envVars.Add("COMPlus_JITMinOpts", "0"); } string profilerPath = GetProfilerPath(); diff --git a/src/coreclr/tests/src/profiler/rejit/rejit.cs b/src/coreclr/tests/src/profiler/rejit/rejit.cs index da7ff60f9f731..ec5cddc1bf9f0 100644 --- a/src/coreclr/tests/src/profiler/rejit/rejit.cs +++ b/src/coreclr/tests/src/profiler/rejit/rejit.cs @@ -100,7 +100,7 @@ public static int Main(string[] args) return ProfilerTestRunner.Run(profileePath: System.Reflection.Assembly.GetExecutingAssembly().Location, testName: "ReJITWithInlining", profilerClsid: ReJitProfilerGuid, - profileeOptions: ProfileeOptions.DisableTieredCompilation); + profileeOptions: ProfileeOptions.OptimizationSensitive); } } } diff --git a/src/coreclr/tests/src/runtest.proj b/src/coreclr/tests/src/runtest.proj index 09ab3ad67cf22..b6615b50e8efd 100644 --- a/src/coreclr/tests/src/runtest.proj +++ b/src/coreclr/tests/src/runtest.proj @@ -286,7 +286,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). if (infraEx != null) { - Assert.True(false, "Test Infrastructure Failure: " + infraEx.Message)%3B + Assert.True(false, "Test Infrastructure Failure: " + infraEx.ToString())%3B } else { @@ -299,7 +299,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). catch (Exception ex) { testOutput.Add("Unable to read error file: " + errorFile)%3B - testOutput.Add(ex.Message)%3B + testOutput.Add(ex.ToString())%3B } testOutput.Add(string.Empty)%3B @@ -314,7 +314,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). catch(Exception ex) { testOutput.Add("Unable to read output file: " + outputFile)%3B - testOutput.Add(ex.Message)%3B + testOutput.Add(ex.ToString())%3B } testOutput.Add("To run the test:")%3B @@ -349,7 +349,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). - + diff --git a/src/coreclr/tests/src/tracing/eventpipe/common/Reverse.cs b/src/coreclr/tests/src/tracing/eventpipe/common/Reverse.cs new file mode 100644 index 0000000000000..c4f1c9464e609 --- /dev/null +++ b/src/coreclr/tests/src/tracing/eventpipe/common/Reverse.cs @@ -0,0 +1,178 @@ +// 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.IO; +using System.IO.Pipes; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Tracing.Tests.Common +{ + /** + * ==ADVERTISE PROTOCOL== + * Before standard IPC Protocol communication can occur on a client-mode connection + * the runtime must advertise itself over the connection. ALL SUBSEQUENT COMMUNICATION + * IS STANDARD DIAGNOSTICS IPC PROTOCOL COMMUNICATION. + * + * The flow for Advertise is a one-way burst of 32 bytes consisting of + * 8 bytes - "ADVR_V1\0" (ASCII chars + null byte) + * 16 bytes - CLR Instance Cookie (little-endian) + * 8 bytes - PID (little-endian) + * 2 bytes - unused for futureproofing + */ + + public class IpcAdvertise + { + public static int Size_V1 => 34; + public static byte[] Magic_V1 => System.Text.Encoding.ASCII.GetBytes("ADVR_V1" + '\0'); + public static int MagicSize_V1 => 8; + + public byte[] Magic = Magic_V1; + public UInt64 ProcessId; + public Guid RuntimeInstanceCookie; + public UInt16 Unused; + + /// + /// + /// + /// (pid, clrInstanceId) + public static IpcAdvertise Parse(Stream stream) + { + var binaryReader = new BinaryReader(stream); + var advertise = new IpcAdvertise() + { + Magic = binaryReader.ReadBytes(Magic_V1.Length), + RuntimeInstanceCookie = new Guid(binaryReader.ReadBytes(16)), + ProcessId = binaryReader.ReadUInt64(), + Unused = binaryReader.ReadUInt16() + }; + + for (int i = 0; i < Magic_V1.Length; i++) + if (advertise.Magic[i] != Magic_V1[i]) + throw new Exception("Invalid advertise message from client connection"); + + // FUTURE: switch on incoming magic and change if version ever increments + return advertise; + } + + override public string ToString() + { + return $"{{ Magic={Magic}; ClrInstanceId={RuntimeInstanceCookie}; ProcessId={ProcessId}; Unused={Unused}; }}"; + } + } + public class ReverseServer + { + public static string MakeServerAddress() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return "DOTNET_TRACE_TESTS_" + Path.GetRandomFileName(); + } + else + { + return Path.Combine(Path.GetTempPath(), "DOTNET_TRACE_TESTS_" + Path.GetRandomFileName()); + } + } + + private object _server; // _server ::= socket | NamedPipeServerStream + private Socket _clientSocket; // only used on non-Windows + private string _serverAddress; + + public ReverseServer(string serverAddress, int bufferSize = 16 * 1024) + { + _serverAddress = serverAddress; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + _server = new NamedPipeServerStream( + serverAddress, + PipeDirection.InOut, + NamedPipeServerStream.MaxAllowedServerInstances, + PipeTransmissionMode.Byte, + PipeOptions.None, + bufferSize, + bufferSize); + } + else + { + if (File.Exists(serverAddress)) + File.Delete(serverAddress); + var remoteEP = new UnixDomainSocketEndPoint(serverAddress); + + var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); + // socket(7) states that SO_RCVBUF has a minimum of 128 and SO_SNDBUF has minimum of 1024 + socket.SendBufferSize = Math.Max(bufferSize, 1024); + socket.ReceiveBufferSize = Math.Max(bufferSize, 128); + socket.Bind(remoteEP); + socket.Listen(255); + socket.LingerState.Enabled = false; + _server = socket; + } + } + + public async Task AcceptAsync() + { + switch (_server) + { + case NamedPipeServerStream serverStream: + await serverStream.WaitForConnectionAsync(); + return serverStream; + case Socket socket: + _clientSocket = await socket.AcceptAsync(); + return new NetworkStream(_clientSocket); + default: + throw new ArgumentException("Invalid server type"); + } + } + + public void Shutdown() + { + switch (_server) + { + case NamedPipeServerStream serverStream: + try + { + serverStream.Disconnect(); + } + catch {} + finally + { + serverStream.Dispose(); + } + break; + case Socket socket: + try + { + socket.Shutdown(SocketShutdown.Both); + } + catch {} + finally + { + _clientSocket?.Close(); + socket.Close(); + socket.Dispose(); + _clientSocket?.Dispose(); + if (File.Exists(_serverAddress)) + File.Delete(_serverAddress); + } + break; + default: + throw new ArgumentException("Invalid server type"); + } + } + + // Creates the server, listens, and closes the server + public static async Task CreateServerAndReceiveAdvertisement(string serverAddress) + { + var server = new ReverseServer(serverAddress); + Logger.logger.Log("Waiting for connection"); + Stream stream = await server.AcceptAsync(); + Logger.logger.Log("Got a connection"); + IpcAdvertise advertise = IpcAdvertise.Parse(stream); + server.Shutdown(); + return advertise; + } + } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/tracing/eventpipe/common/common.csproj b/src/coreclr/tests/src/tracing/eventpipe/common/common.csproj index 0df38b391df23..a0b36c8336dcc 100644 --- a/src/coreclr/tests/src/tracing/eventpipe/common/common.csproj +++ b/src/coreclr/tests/src/tracing/eventpipe/common/common.csproj @@ -9,5 +9,6 @@ + diff --git a/src/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs b/src/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs new file mode 100644 index 0000000000000..5fdc7ca11a235 --- /dev/null +++ b/src/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs @@ -0,0 +1,339 @@ +// 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.Tracing; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.Diagnostics.Tools.RuntimeClient; +using Tracing.Tests.Common; +using System.Threading; +using System.IO; +using Microsoft.Diagnostics.Tracing; + +namespace Tracing.Tests.ReverseValidation +{ + public class ReverseValidation + { + // The runtime will do an exponential falloff by a factor of 1.25 starting at 10ms with a max of 500ms + // We can time tests out after waiting 30s which should have sufficient attempts + private static int _maxPollTimeMS = 30_000; + + private static async Task WaitTillTimeout(Task task, TimeSpan timeout) + { + using var cts = new CancellationTokenSource(); + var completedTask = await Task.WhenAny(task, Task.Delay(timeout, cts.Token)); + if (completedTask == task) + { + cts.Cancel(); + return await task; + } + else + { + throw new TimeoutException("Task timed out"); + } + } + + public static async Task RunSubprocess(string serverName, Func beforeExecution = null, Func duringExecution = null, Func afterExecution = null) + { + using (var process = new Process()) + { + if (beforeExecution != null) + await beforeExecution(); + + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.Environment.Add("DOTNET_DiagnosticsMonitorAddress", serverName); + process.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName; + process.StartInfo.Arguments = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath + " 0"; + Logger.logger.Log($"running sub-process: {process.StartInfo.FileName} {process.StartInfo.Arguments}"); + bool fSuccess = process.Start(); + Logger.logger.Log($"subprocess started: {fSuccess}"); + Logger.logger.Log($"subprocess PID: {process.Id}"); + + while (!EventPipeClient.ListAvailablePorts().Contains(process.Id)) + await Task.Delay(100); + try + { + if (duringExecution != null) + await duringExecution(process.Id); + } + finally + { + process.Kill(); + } + + + if (afterExecution != null) + await afterExecution(); + } + } + + public static async Task TEST_RuntimeIsResilientToServerClosing() + { + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + await RunSubprocess( + serverName: serverName, + duringExecution: async (_) => + { + var ad1 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad1.ToString()); + var ad2 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad2.ToString()); + var ad3 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad3.ToString()); + var ad4 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad4.ToString()); + } + ); + + return true; + } + + public static async Task TEST_RuntimeConnectsToExistingServer() + { + string serverName = ReverseServer.MakeServerAddress(); + Task advertiseTask = ReverseServer.CreateServerAndReceiveAdvertisement(serverName); + Logger.logger.Log($"Server name is `{serverName}`"); + await RunSubprocess( + serverName: serverName, + duringExecution: async (_) => + { + IpcAdvertise advertise = await WaitTillTimeout(advertiseTask, TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(advertise.ToString()); + } + ); + + return true; + } + + + public static async Task TEST_CanConnectServerAndClientAtSameTime() + { + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + var server = new ReverseServer(serverName); + await RunSubprocess( + serverName: serverName, + duringExecution: async (int pid) => + { + Task reverseTask = Task.Run(async () => + { + Logger.logger.Log($"Waiting for reverse connection"); + Stream reverseStream = await server.AcceptAsync(); + Logger.logger.Log("Got reverse connection"); + IpcAdvertise advertise = IpcAdvertise.Parse(reverseStream); + Logger.logger.Log(advertise.ToString()); + }); + + Task regularTask = Task.Run(async () => + { + var config = new SessionConfiguration( + circularBufferSizeMB: 1000, + format: EventPipeSerializationFormat.NetTrace, + providers: new List { + new Provider("Microsoft-DotNETCore-SampleProfiler") + }); + Logger.logger.Log("Starting EventPipeSession over standard connection"); + using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId); + Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); + using var source = new EventPipeEventSource(stream); + Task readerTask = Task.Run(() => source.Process()); + await Task.Delay(500); + Logger.logger.Log("Stopping EventPipeSession over standard connection"); + EventPipeClient.StopTracing(pid, sessionId); + await readerTask; + Logger.logger.Log("Stopped EventPipeSession over standard connection"); + }); + + await Task.WhenAll(reverseTask, regularTask); + } + ); + + server.Shutdown(); + + return true; + } + + public static async Task TEST_ServerWorksIfClientDoesntAccept() + { + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + var server = new ReverseServer(serverName); + await RunSubprocess( + serverName: serverName, + duringExecution: async (int pid) => + { + var config = new SessionConfiguration( + circularBufferSizeMB: 10, + format: EventPipeSerializationFormat.NetTrace, + providers: new List { + new Provider("Microsoft-DotNETCore-SampleProfiler") + }); + Logger.logger.Log("Starting EventPipeSession over standard connection"); + using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId); + Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); + using var source = new EventPipeEventSource(stream); + Task readerTask = Task.Run(() => source.Process()); + await Task.Delay(500); + Logger.logger.Log("Stopping EventPipeSession over standard connection"); + EventPipeClient.StopTracing(pid, sessionId); + await readerTask; + Logger.logger.Log("Stopped EventPipeSession over standard connection"); + } + ); + + server.Shutdown(); + + return true; + } + + public static async Task TEST_ServerIsResilientToNoBufferAgent() + { + // N.B. - this test is only testing behavior on Windows since Unix Domain Sockets get their buffer size from the + // system configuration and isn't set here. Tests passing on Windows should indicate it would pass on Unix systems as well. + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + var server = new ReverseServer(serverName, 0); + await RunSubprocess( + serverName: serverName, + duringExecution: async (int pid) => + { + var config = new SessionConfiguration( + circularBufferSizeMB: 10, + format: EventPipeSerializationFormat.NetTrace, + providers: new List { + new Provider("Microsoft-DotNETCore-SampleProfiler") + }); + Logger.logger.Log("Starting EventPipeSession over standard connection"); + using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId); + Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); + using var source = new EventPipeEventSource(stream); + Task readerTask = Task.Run(() => source.Process()); + await Task.Delay(500); + Logger.logger.Log("Stopping EventPipeSession over standard connection"); + EventPipeClient.StopTracing(pid, sessionId); + await readerTask; + Logger.logger.Log("Stopped EventPipeSession over standard connection"); + } + ); + + server.Shutdown(); + + return true; + } + + public static async Task TEST_ReverseConnectionCanRecycleWhileTracing() + { + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + await RunSubprocess( + serverName: serverName, + duringExecution: async (int pid) => + { + Task regularTask = Task.Run(async () => + { + var config = new SessionConfiguration( + circularBufferSizeMB: 1000, + format: EventPipeSerializationFormat.NetTrace, + providers: new List { + new Provider("Microsoft-DotNETCore-SampleProfiler") + }); + Logger.logger.Log("Starting EventPipeSession over standard connection"); + using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId); + Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); + using var source = new EventPipeEventSource(stream); + Task readerTask = Task.Run(() => source.Process()); + await Task.Delay(500); + Logger.logger.Log("Stopping EventPipeSession over standard connection"); + EventPipeClient.StopTracing(pid, sessionId); + await readerTask; + Logger.logger.Log("Stopped EventPipeSession over standard connection"); + }); + + Task reverseTask = Task.Run(async () => + { + var ad1 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad1.ToString()); + var ad2 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad2.ToString()); + var ad3 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad3.ToString()); + var ad4 = await WaitTillTimeout(ReverseServer.CreateServerAndReceiveAdvertisement(serverName), TimeSpan.FromMilliseconds(_maxPollTimeMS)); + Logger.logger.Log(ad4.ToString()); + }); + + await Task.WhenAll(reverseTask, regularTask); + } + ); + + return true; + } + + public static async Task TEST_StandardConnectionStillWorksIfReverseConnectionIsBroken() + { + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + await RunSubprocess( + serverName: serverName, + duringExecution: async (int pid) => + { + var config = new SessionConfiguration( + circularBufferSizeMB: 1000, + format: EventPipeSerializationFormat.NetTrace, + providers: new List { + new Provider("Microsoft-DotNETCore-SampleProfiler") + }); + Logger.logger.Log("Starting EventPipeSession over standard connection"); + using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId); + Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); + using var source = new EventPipeEventSource(stream); + Task readerTask = Task.Run(() => source.Process()); + await Task.Delay(500); + Logger.logger.Log("Stopping EventPipeSession over standard connection"); + EventPipeClient.StopTracing(pid, sessionId); + await readerTask; + Logger.logger.Log("Stopped EventPipeSession over standard connection"); + } + ); + + return true; + } + + public static async Task Main(string[] args) + { + if (args.Length >= 1) + { + await Task.Delay(TimeSpan.FromMinutes(10)); // will be killed in test + return 1; + } + + bool fSuccess = true; + IEnumerable tests = typeof(ReverseValidation).GetMethods().Where(mi => mi.Name.StartsWith("TEST_")); + foreach (var test in tests) + { + Logger.logger.Log($"::== Running test: {test.Name}"); + bool result = true; + try + { + result = await (Task)test.Invoke(null, new object[] {}); + } + catch (Exception e) + { + result = false; + Logger.logger.Log(e.ToString()); + } + fSuccess &= result; + Logger.logger.Log($"Test passed: {result}"); + Logger.logger.Log($""); + + } + return fSuccess ? 100 : -1; + } + } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/tracing/eventpipe/reverse/reverse.csproj b/src/coreclr/tests/src/tracing/eventpipe/reverse/reverse.csproj new file mode 100644 index 0000000000000..2c10c6ed46533 --- /dev/null +++ b/src/coreclr/tests/src/tracing/eventpipe/reverse/reverse.csproj @@ -0,0 +1,15 @@ + + + .NETCoreApp + exe + BuildAndRun + true + 0 + true + true + + + + + + \ No newline at end of file diff --git a/src/coreclr/tests/testenvironment.proj b/src/coreclr/tests/testenvironment.proj index caed6ae7e1ee8..199382c46df9b 100644 --- a/src/coreclr/tests/testenvironment.proj +++ b/src/coreclr/tests/testenvironment.proj @@ -45,6 +45,7 @@ COMPlus_TC_QuickJitForLoops; COMPlus_TC_OnStackReplacement_InitialCounter; COMPlus_OSR_HitLimit; + COMPlus_TieredPGO; COMPlus_JitEnableGuardedDevirtualization; COMPlus_EnableEHWriteThru; COMPlus_JitObjectStackAllocation @@ -135,6 +136,7 @@ + @@ -174,11 +176,13 @@ <_TestEnvFileLine Include="@(_COMPlusVariable->'set %(Identity)=%(Value)')" /> + <_TestEnvFileLine Include="set MONO_ENV_OPTIONS=--interpreter" Condition="'$(Scenario)' == 'interpreter'" /> <_TestEnvFileLine Include="#!/usr/bin/env bash" /> <_TestEnvFileLine Include="@(_COMPlusVariable->'export %(Identity)=%(Value)')" /> + <_TestEnvFileLine Include="export MONO_ENV_OPTIONS=--interpreter" Condition="'$(Scenario)' == 'interpreter'" /> diff --git a/src/installer/Directory.Build.props b/src/installer/Directory.Build.props index db4b337749323..d1edd4ec5388f 100644 --- a/src/installer/Directory.Build.props +++ b/src/installer/Directory.Build.props @@ -29,12 +29,6 @@ $(InstallerProjectRoot)signing\ - - .NETCoreApp - $(NETCoreAppFrameworkIdentifier),Version=v$(NETCoreAppFrameworkVersion) - .NET $(NETCoreAppFrameworkVersion) - - true @@ -86,6 +80,8 @@ osx-$(TargetArchitecture) linux-$(TargetArchitecture) freebsd-$(TargetArchitecture) + netbsd-$(TargetArchitecture) + sunos-$(TargetArchitecture) ios-$(TargetArchitecture) tvos-$(TargetArchitecture) android-$(TargetArchitecture) @@ -128,8 +124,8 @@ false true - - true + + true $(AssetOutputPath)sharedfx_$(OutputRid)_$(Configuration)_version_badge.svg @@ -217,6 +213,7 @@ true true + true @@ -288,6 +285,18 @@ true + + + true + true + + + + + true + true + + true @@ -362,7 +371,7 @@ .map .ni.pdb - + diff --git a/src/installer/Microsoft.DotNet.CoreSetup.sln b/src/installer/Microsoft.DotNet.CoreSetup.sln index e3b39fe6aff62..9e432a1616caa 100644 --- a/src/installer/Microsoft.DotNet.CoreSetup.sln +++ b/src/installer/Microsoft.DotNet.CoreSetup.sln @@ -9,8 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.Config = NuGet.Config EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.PlatformAbstractions", "managed\Microsoft.DotNet.PlatformAbstractions\Microsoft.DotNet.PlatformAbstractions.csproj", "{04D84DC8-A509-43FE-B846-16B770D9E3AA}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostActivation.Tests", "test\HostActivation.Tests\HostActivation.Tests.csproj", "{23F4AB97-D15C-4C51-A641-DF5C5D5EF70F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtils", "test\TestUtils\TestUtils.csproj", "{D6676666-D14D-4DFA-88FB-76E3E823E2E1}" @@ -41,22 +39,6 @@ Global RelWithDebInfo|x64 = RelWithDebInfo|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Debug|x64.ActiveCfg = Debug|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Debug|x64.Build.0 = Debug|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.MinSizeRel|Any CPU.ActiveCfg = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.MinSizeRel|Any CPU.Build.0 = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.MinSizeRel|x64.ActiveCfg = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.MinSizeRel|x64.Build.0 = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Release|Any CPU.Build.0 = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Release|x64.ActiveCfg = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.Release|x64.Build.0 = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {04D84DC8-A509-43FE-B846-16B770D9E3AA}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {23F4AB97-D15C-4C51-A641-DF5C5D5EF70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {23F4AB97-D15C-4C51-A641-DF5C5D5EF70F}.Debug|Any CPU.Build.0 = Debug|Any CPU {23F4AB97-D15C-4C51-A641-DF5C5D5EF70F}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/src/installer/corehost/CMakeLists.txt b/src/installer/corehost/CMakeLists.txt index 43a59a1a6955d..4fa7f45b42ab0 100644 --- a/src/installer/corehost/CMakeLists.txt +++ b/src/installer/corehost/CMakeLists.txt @@ -9,6 +9,10 @@ if(MSVC) # Host components don't try to handle asynchronous exceptions add_compile_options(/EHsc) +elseif (CMAKE_CXX_COMPILER_ID MATCHES GNU) + # Prevents libc from calling pthread_cond_destroy on static objects in + # dlopen()'ed library which we dlclose() in pal::unload_library. + add_compile_options(-fno-use-cxa-atexit) endif() add_subdirectory(cli) diff --git a/src/installer/corehost/Windows/probe-win.ps1 b/src/installer/corehost/Windows/probe-win.ps1 index 353db37bfc63b..8641741c6c79e 100644 --- a/src/installer/corehost/Windows/probe-win.ps1 +++ b/src/installer/corehost/Windows/probe-win.ps1 @@ -34,7 +34,7 @@ function GetCMakeInfo($regKey) function LocateCMake { - $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from http://www.cmake.org/download/ and ensure it is on your path." + $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from https://cmake.org/download/ and ensure it is on your path." $inPathPath = (get-command cmake.exe -ErrorAction SilentlyContinue) if ($inPathPath -ne $null) { # Resolve the first version of CMake if multiple commands are found diff --git a/src/installer/corehost/build.proj b/src/installer/corehost/build.proj index 0d6d91ea43e08..79f4c0a5f0e7d 100644 --- a/src/installer/corehost/build.proj +++ b/src/installer/corehost/build.proj @@ -6,7 +6,7 @@ package's targets into the build. --> - $(NETCoreAppFramework) + $(NetCoreAppCurrent) diff --git a/src/installer/corehost/cli/bundle/file_entry.cpp b/src/installer/corehost/cli/bundle/file_entry.cpp index 775117fb9a1f6..25e2cd01ce3fc 100644 --- a/src/installer/corehost/cli/bundle/file_entry.cpp +++ b/src/installer/corehost/cli/bundle/file_entry.cpp @@ -38,10 +38,9 @@ bool file_entry_t::needs_extraction() const { switch (m_type) { - // Once the runtime can load assemblies from bundle, - // file_type_t::assembly should be in this category case file_type_t::deps_json: case file_type_t::runtime_config_json: + case file_type_t::assembly: return false; default: diff --git a/src/installer/corehost/cli/bundle/runner.cpp b/src/installer/corehost/cli/bundle/runner.cpp index 19fc8bcd47576..dec93009e4683 100644 --- a/src/installer/corehost/cli/bundle/runner.cpp +++ b/src/installer/corehost/cli/bundle/runner.cpp @@ -79,8 +79,7 @@ bool runner_t::probe(const pal::string_t& relative_path, int64_t* offset, int64_ return true; } - -bool runner_t::locate(const pal::string_t& relative_path, pal::string_t& full_path) const +bool runner_t::locate(const pal::string_t& relative_path, pal::string_t& full_path, bool& extracted_to_disk) const { const bundle::file_entry_t* entry = probe(relative_path); @@ -90,11 +89,9 @@ bool runner_t::locate(const pal::string_t& relative_path, pal::string_t& full_pa return false; } - // Currently, all files except deps.json and runtimeconfig.json are extracted to disk. - // The json files are not queried by the host using this method. - assert(entry->needs_extraction()); + extracted_to_disk = entry->needs_extraction(); + full_path.assign(extracted_to_disk ? extraction_path() : base_path()); - full_path.assign(extraction_path()); append_path(&full_path, relative_path.c_str()); return true; diff --git a/src/installer/corehost/cli/bundle/runner.h b/src/installer/corehost/cli/bundle/runner.h index 39c6b6b1190b0..f632814df8f81 100644 --- a/src/installer/corehost/cli/bundle/runner.h +++ b/src/installer/corehost/cli/bundle/runner.h @@ -21,26 +21,31 @@ namespace bundle { public: runner_t(const pal::char_t* bundle_path, - const pal::char_t *app_path, - int64_t header_offset) + const pal::char_t* app_path, + int64_t header_offset) : info_t(bundle_path, app_path, header_offset) {} const pal::string_t& extraction_path() const { return m_extraction_path; } bool probe(const pal::string_t& relative_path, int64_t* offset, int64_t* size) const; - bool locate(const pal::string_t& relative_path, pal::string_t& full_path) const; + const file_entry_t* probe(const pal::string_t& relative_path) const; + bool locate(const pal::string_t& relative_path, pal::string_t& full_path, bool& extracted_to_disk) const; + bool locate(const pal::string_t& relative_path, pal::string_t& full_path) const + { + bool extracted_to_disk; + return locate(relative_path, full_path, extracted_to_disk); + } static StatusCode process_manifest_and_extract() { return ((runner_t*) the_app)->extract(); } - + static const runner_t* app() { return (const runner_t*)the_app; } private: StatusCode extract(); - const file_entry_t* probe(const pal::string_t& relative_path) const; manifest_t m_manifest; pal::string_t m_extraction_path; diff --git a/src/installer/corehost/cli/common.cmake b/src/installer/corehost/cli/common.cmake index 5f9289659684c..1ad7ee619abd8 100644 --- a/src/installer/corehost/cli/common.cmake +++ b/src/installer/corehost/cli/common.cmake @@ -38,7 +38,7 @@ endif() # This is required to map a symbol reference to a matching definition local to the module (.so) # containing the reference instead of using definitions from other modules. -if(CLR_CMAKE_TARGET_LINUX) +if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_SUNOS) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic") endif() diff --git a/src/installer/corehost/cli/deps_entry.cpp b/src/installer/corehost/cli/deps_entry.cpp index 449403fa038e2..85c845047da4c 100644 --- a/src/installer/corehost/cli/deps_entry.cpp +++ b/src/installer/corehost/cli/deps_entry.cpp @@ -38,11 +38,12 @@ static pal::string_t normalize_dir_separator(const pal::string_t& path) // Returns: // If the file exists in the path relative to the "base" directory within the // single-file or on disk. -bool deps_entry_t::to_path(const pal::string_t& base, const pal::string_t& ietf_dir, bool look_in_base, bool look_in_bundle, pal::string_t* str) const +bool deps_entry_t::to_path(const pal::string_t& base, const pal::string_t& ietf_dir, bool look_in_base, bool look_in_bundle, pal::string_t* str, bool &loaded_from_bundle) const { pal::string_t& candidate = *str; candidate.clear(); + loaded_from_bundle = false; // Base directory must be present to obtain full path if (base.empty()) @@ -67,9 +68,11 @@ bool deps_entry_t::to_path(const pal::string_t& base, const pal::string_t& ietf_ { // If sub_path is found in the single-file bundle, // app::locate() will set candidate to the full-path to the assembly extracted out to disk. - if (app->locate(sub_path, candidate)) + bool extracted_to_disk = false; + if (app->locate(sub_path, candidate, extracted_to_disk)) { - trace::verbose(_X(" %s found in bundle [%s]"), sub_path.c_str(), candidate.c_str()); + loaded_from_bundle = !extracted_to_disk; + trace::verbose(_X(" %s found in bundle [%s] %s"), sub_path.c_str(), candidate.c_str(), extracted_to_disk ? _X("(extracted)") : _X("")); return true; } else @@ -112,7 +115,7 @@ bool deps_entry_t::to_path(const pal::string_t& base, const pal::string_t& ietf_ // Returns: // If the file exists in the path relative to the "base" directory. // -bool deps_entry_t::to_dir_path(const pal::string_t& base, bool look_in_bundle, pal::string_t* str) const +bool deps_entry_t::to_dir_path(const pal::string_t& base, bool look_in_bundle, pal::string_t* str, bool& loaded_from_bundle) const { pal::string_t ietf_dir; @@ -134,7 +137,7 @@ bool deps_entry_t::to_dir_path(const pal::string_t& base, bool look_in_bundle, p base.c_str(), ietf_dir.c_str(), asset.name.c_str()); } - return to_path(base, ietf_dir, true, look_in_bundle, str); + return to_path(base, ietf_dir, true, look_in_bundle, str, loaded_from_bundle); } // ----------------------------------------------------------------------------- @@ -150,7 +153,10 @@ bool deps_entry_t::to_dir_path(const pal::string_t& base, bool look_in_bundle, p // bool deps_entry_t::to_rel_path(const pal::string_t& base, bool look_in_bundle, pal::string_t* str) const { - return to_path(base, _X(""), false, look_in_bundle, str); + bool loaded_from_bundle; + bool result = to_path(base, _X(""), false, look_in_bundle, str, loaded_from_bundle); + assert(!loaded_from_bundle); + return result; } // ----------------------------------------------------------------------------- diff --git a/src/installer/corehost/cli/deps_entry.h b/src/installer/corehost/cli/deps_entry.h index 2c66b1f055273..a8e994bef5b21 100644 --- a/src/installer/corehost/cli/deps_entry.h +++ b/src/installer/corehost/cli/deps_entry.h @@ -53,7 +53,7 @@ struct deps_entry_t bool is_rid_specific; // Given a "base" dir, yield the file path within this directory or single-file bundle. - bool to_dir_path(const pal::string_t& base, bool look_in_bundle, pal::string_t* str) const; + bool to_dir_path(const pal::string_t& base, bool look_in_bundle, pal::string_t* str, bool& loaded_from_bundle) const; // Given a "base" dir, yield the relative path in the package layout. bool to_rel_path(const pal::string_t& base, bool look_in_bundle, pal::string_t* str) const; @@ -64,7 +64,7 @@ struct deps_entry_t private: // Given a "base" dir, yield the filepath within this directory or relative to this directory based on "look_in_base" // Returns a path within the single-file bundle, or a file on disk, - bool to_path(const pal::string_t& base, const pal::string_t& ietf_code, bool look_in_base, bool look_in_bundle, pal::string_t* str) const; + bool to_path(const pal::string_t& base, const pal::string_t& ietf_code, bool look_in_base, bool look_in_bundle, pal::string_t* str, bool & loaded_from_bundle) const; }; #endif // __DEPS_ENTRY_H_ diff --git a/src/installer/corehost/cli/fxr/hostfxr.cpp b/src/installer/corehost/cli/fxr/hostfxr.cpp index 1fdfa21048935..23418b03da032 100644 --- a/src/installer/corehost/cli/fxr/hostfxr.cpp +++ b/src/installer/corehost/cli/fxr/hostfxr.cpp @@ -438,7 +438,7 @@ namespace if (startup_info.dotnet_root.empty()) { pal::string_t mod_path; - if (!pal::get_own_module_path(&mod_path)) + if (!pal::get_method_module_path(&mod_path, (void*)&hostfxr_set_error_writer)) return StatusCode::CoreHostCurHostFindFailure; startup_info.dotnet_root = get_dotnet_root_from_fxr_path(mod_path); diff --git a/src/installer/corehost/cli/hostmisc/pal.h b/src/installer/corehost/cli/hostmisc/pal.h index 5c8fa68a27881..1e1f4cf5f5c4f 100644 --- a/src/installer/corehost/cli/hostmisc/pal.h +++ b/src/installer/corehost/cli/hostmisc/pal.h @@ -249,7 +249,6 @@ namespace pal inline void err_flush() { std::fflush(stderr); } inline void out_flush() { std::fflush(stdout); } - // Based upon https://github.com/dotnet/core-setup/blob/master/src/Microsoft.DotNet.PlatformAbstractions/Native/PlatformApis.cs string_t get_current_os_rid_platform(); inline string_t get_current_os_fallback_rid() { @@ -272,6 +271,7 @@ namespace pal bool get_own_executable_path(string_t* recv); bool get_own_module_path(string_t* recv); + bool get_method_module_path(string_t* recv, void* method); bool get_module_path(dll_t mod, string_t* recv); bool get_current_module(dll_t *mod); bool getenv(const char_t* name, string_t* recv); diff --git a/src/installer/corehost/cli/hostmisc/pal.unix.cpp b/src/installer/corehost/cli/hostmisc/pal.unix.cpp index 20612a16f6fcf..a17487636d60b 100644 --- a/src/installer/corehost/cli/hostmisc/pal.unix.cpp +++ b/src/installer/corehost/cli/hostmisc/pal.unix.cpp @@ -41,6 +41,16 @@ #define DT_LNK 10 #endif +#ifdef __linux__ +#define PAL_CWD_SIZE 0 +#elif defined(MAXPATHLEN) +#define PAL_CWD_SIZE MAXPATHLEN +#elif defined(PATH_MAX) +#define PAL_CWD_SIZE PATH_MAX +#else +#error "Don't know how to obtain max path on this platform" +#endif + pal::string_t pal::to_lower(const pal::string_t& in) { pal::string_t ret = in; @@ -118,7 +128,7 @@ void* pal::mmap_copy_on_write(const string_t& path, size_t* length) bool pal::getcwd(pal::string_t* recv) { recv->clear(); - pal::char_t* buf = ::getcwd(nullptr, 0); + pal::char_t* buf = ::getcwd(nullptr, PAL_CWD_SIZE); if (buf == nullptr) { if (errno == ENOENT) @@ -129,6 +139,7 @@ bool pal::getcwd(pal::string_t* recv) trace::error(_X("getcwd() failed: %s"), strerror(errno)); return false; } + recv->assign(buf); ::free(buf); return true; @@ -768,6 +779,28 @@ bool pal::get_own_executable_path(pal::string_t* recv) } return false; } +#elif defined(__sun) +bool pal::get_own_executable_path(pal::string_t* recv) +{ + const char *path; + if ((path = getexecname()) == NULL) + { + return false; + } + else if (*path != '/') + { + if (!getcwd(recv)) + { + return false; + } + + recv->append("/").append(path); + return true; + } + + recv->assign(path); + return true; +} #else bool pal::get_own_executable_path(pal::string_t* recv) { @@ -788,6 +821,16 @@ bool pal::get_own_module_path(string_t* recv) return true; } +bool pal::get_method_module_path(string_t* recv, void* method) +{ + Dl_info info; + if (dladdr(method, &info) == 0) + return false; + + recv->assign(info.dli_fname); + return true; +} + bool pal::get_module_path(dll_t module, string_t* recv) { return false; diff --git a/src/installer/corehost/cli/hostmisc/pal.windows.cpp b/src/installer/corehost/cli/hostmisc/pal.windows.cpp index 81f538bed4414..1c724611d72c6 100644 --- a/src/installer/corehost/cli/hostmisc/pal.windows.cpp +++ b/src/installer/corehost/cli/hostmisc/pal.windows.cpp @@ -553,6 +553,16 @@ bool pal::get_own_module_path(string_t* recv) return GetModuleFileNameWrapper(hmod, recv); } +bool pal::get_method_module_path(string_t* recv, void* method) +{ + HMODULE hmod; + if (!GetModuleHandleFromAddress(method, &hmod)) + return false; + + return GetModuleFileNameWrapper(hmod, recv); +} + + bool pal::get_module_path(dll_t mod, string_t* recv) { return GetModuleFileNameWrapper(mod, recv); diff --git a/src/installer/corehost/cli/hostpolicy/deps_resolver.cpp b/src/installer/corehost/cli/hostpolicy/deps_resolver.cpp index 21060eab4bdfb..de3762cb13098 100644 --- a/src/installer/corehost/cli/hostpolicy/deps_resolver.cpp +++ b/src/installer/corehost/cli/hostpolicy/deps_resolver.cpp @@ -281,10 +281,13 @@ void deps_resolver_t::setup_additional_probes(const std::vector& * -- When servicing directories are looked up, look up only if the deps file marks the entry as serviceable. * -- When a deps json based probe is performed, the deps entry's package name and version must match. * -- When looking into a published dir, for rid specific assets lookup rid split folders; for non-rid assets lookup the layout dir. + * The path to the resolved file is returned in candidate out parameter + * If the candidate is embedded within the single-file bundle (rather than an actual file on disk), loaded_from_bundle will be set to true. */ -bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::string_t& deps_dir, int fx_level, pal::string_t* candidate) +bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::string_t& deps_dir, int fx_level, pal::string_t* candidate, bool & loaded_from_bundle) { candidate->clear(); + loaded_from_bundle = false; for (const auto& config : m_probes) { @@ -316,8 +319,9 @@ bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::str // If the deps json has the package name and version, then someone has already done rid selection and // put the right asset in the dir. So checking just package name and version would suffice. // No need to check further for the exact asset relative sub path. - if (config.probe_deps_json->has_package(entry.library_name, entry.library_version) && entry.to_dir_path(probe_dir, false, candidate)) + if (config.probe_deps_json->has_package(entry.library_name, entry.library_version) && entry.to_dir_path(probe_dir, false, candidate, loaded_from_bundle)) { + assert(!loaded_from_bundle); trace::verbose(_X(" Probed deps json and matched '%s'"), candidate->c_str()); return true; } @@ -343,7 +347,7 @@ bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::str else { // Non-rid assets, lookup in the published dir. - if (entry.to_dir_path(deps_dir, true, candidate)) + if (entry.to_dir_path(deps_dir, true, candidate, loaded_from_bundle)) { trace::verbose(_X(" Probed deps dir and matched '%s'"), candidate->c_str()); return true; @@ -437,10 +441,17 @@ bool deps_resolver_t::resolve_tpa_list( name_to_resolved_asset_map_t::iterator existing = items.find(entry.asset.name); if (existing == items.end()) { - if (probe_deps_entry(entry, deps_dir, fx_level, &resolved_path)) + bool loaded_from_bundle = false; + if (probe_deps_entry(entry, deps_dir, fx_level, &resolved_path, loaded_from_bundle)) { - deps_resolved_asset_t resolved_asset(entry.asset, resolved_path); - add_tpa_asset(resolved_asset, &items); + // Assemblies loaded directly from the bundle are not added to the TPA list. + // The runtime directly probes the bundle-manifest using a host-callback. + if (!loaded_from_bundle) + { + deps_resolved_asset_t resolved_asset(entry.asset, resolved_path); + add_tpa_asset(resolved_asset, &items); + } + return true; } @@ -468,7 +479,8 @@ bool deps_resolver_t::resolve_tpa_list( if (entry.asset.assembly_version > existing_entry->asset.assembly_version || (entry.asset.assembly_version == existing_entry->asset.assembly_version && entry.asset.file_version >= existing_entry->asset.file_version)) { - if (probe_deps_entry(entry, deps_dir, fx_level, &resolved_path)) + bool loaded_from_bundle = false; + if (probe_deps_entry(entry, deps_dir, fx_level, &resolved_path, loaded_from_bundle)) { // If the path is the same, then no need to replace if (resolved_path != existing_entry->resolved_path) @@ -480,9 +492,12 @@ bool deps_resolver_t::resolve_tpa_list( existing_entry = nullptr; items.erase(existing); - deps_asset_t asset(entry.asset.name, entry.asset.relative_path, entry.asset.assembly_version, entry.asset.file_version); - deps_resolved_asset_t resolved_asset(asset, resolved_path); - add_tpa_asset(resolved_asset, &items); + if (!loaded_from_bundle) + { + deps_asset_t asset(entry.asset.name, entry.asset.relative_path, entry.asset.assembly_version, entry.asset.file_version); + deps_resolved_asset_t resolved_asset(asset, resolved_path); + add_tpa_asset(resolved_asset, &items); + } } } else if (fx_level != 0) @@ -505,9 +520,17 @@ bool deps_resolver_t::resolve_tpa_list( // First add managed assembly to the TPA. // TODO: Remove: the deps should contain the managed DLL. // Workaround for: csc.deps.json doesn't have the csc.dll - deps_asset_t asset(get_filename_without_ext(m_managed_app), get_filename(m_managed_app), version_t(), version_t()); - deps_resolved_asset_t resolved_asset(asset, m_managed_app); - add_tpa_asset(resolved_asset, &items); + + // If this is a single-file bundle, app.dll is expected to be within the bundle, unless it is explicitly excluded from the bundle. + // In all other cases, add its path to the TPA list. + pal::string_t managed_app_name = get_filename(m_managed_app); + if (!bundle::info_t::is_single_file_bundle() || + bundle::runner_t::app()->probe(managed_app_name) == nullptr) + { + deps_asset_t asset(get_filename_without_ext(m_managed_app), managed_app_name, version_t(), version_t()); + deps_resolved_asset_t resolved_asset(asset, m_managed_app); + add_tpa_asset(resolved_asset, &items); + } // Add the app's entries const auto& deps_entries = get_deps().get_entries(deps_entry_t::asset_types::runtime); @@ -783,10 +806,14 @@ bool deps_resolver_t::resolve_probe_dirs( trace::verbose(_X("Processing native/culture for deps entry [%s, %s, %s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.asset.relative_path.c_str()); - if (probe_deps_entry(entry, deps_dir, fx_level, &candidate)) + bool loaded_from_bundle = false; + if (probe_deps_entry(entry, deps_dir, fx_level, &candidate, loaded_from_bundle)) { - init_known_entry_path(entry, candidate); - add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing); + if (!loaded_from_bundle) + { + init_known_entry_path(entry, candidate); + add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing); + } } else { diff --git a/src/installer/corehost/cli/hostpolicy/deps_resolver.h b/src/installer/corehost/cli/hostpolicy/deps_resolver.h index cb033f5c6d698..8471d94b44c12 100644 --- a/src/installer/corehost/cli/hostpolicy/deps_resolver.h +++ b/src/installer/corehost/cli/hostpolicy/deps_resolver.h @@ -228,7 +228,8 @@ class deps_resolver_t const deps_entry_t& entry, const pal::string_t& deps_dir, int fx_level, - pal::string_t* candidate); + pal::string_t* candidate, + bool &loaded_from_bundle); fx_definition_vector_t& m_fx_definitions; diff --git a/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp b/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp index 5a0a32394e9a1..ed6801342c465 100644 --- a/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp +++ b/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp @@ -113,17 +113,24 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a // Get path in which CoreCLR is present. clr_dir = get_directory(clr_path); + // If this is a self-contained single-file bundle, + // System.Private.CoreLib.dll is expected to be within the bundle, unless it is explicitly excluded from the bundle. + // In all other cases, // System.Private.CoreLib.dll is expected to be next to CoreCLR.dll - add its path to the TPA list. - pal::string_t corelib_path = clr_dir; - append_path(&corelib_path, CORELIB_NAME); - - // Append CoreLib path - if (!probe_paths.tpa.empty() && probe_paths.tpa.back() != PATH_SEPARATOR) + if (!bundle::info_t::is_single_file_bundle() || + bundle::runner_t::app()->probe(CORELIB_NAME) == nullptr) { - probe_paths.tpa.push_back(PATH_SEPARATOR); - } + pal::string_t corelib_path = clr_dir; + append_path(&corelib_path, CORELIB_NAME); + + // Append CoreLib path + if (!probe_paths.tpa.empty() && probe_paths.tpa.back() != PATH_SEPARATOR) + { + probe_paths.tpa.push_back(PATH_SEPARATOR); + } - probe_paths.tpa.append(corelib_path); + probe_paths.tpa.append(corelib_path); + } const fx_definition_vector_t &fx_definitions = resolver.get_fx_definitions(); diff --git a/src/installer/corehost/cli/json_parser.h b/src/installer/corehost/cli/json_parser.h index 16ed21bd03307..344d03647774f 100644 --- a/src/installer/corehost/cli/json_parser.h +++ b/src/installer/corehost/cli/json_parser.h @@ -5,6 +5,14 @@ #ifndef __JSON_PARSER_H__ #define __JSON_PARSER_H__ +#ifdef __sun +// This optimization relies on zeros in higher 16-bits, whereas SunOS has 1s. More details at +// https://github.com/Tencent/rapidjson/issues/1596. +// The impact here was that runtimeOptions key available in hwapp.runtimeconfig.json was not +// located by RapidJson's FindMember() API from runtime_config_t::ensure_parsed(). +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif + #include "pal.h" #include "rapidjson/document.h" #include "rapidjson/fwd.h" diff --git a/src/installer/managed/CommonManaged.props b/src/installer/managed/CommonManaged.props index 5195cc2c4dd56..c96859a92e4a5 100644 --- a/src/installer/managed/CommonManaged.props +++ b/src/installer/managed/CommonManaged.props @@ -16,15 +16,6 @@ true $(NoWarn);CS1591 - - @@ -34,20 +25,6 @@ true - - true - - - - git - git://github.com/dotnet/core-setup - - - - - - - (TValue value, IEqualityComparer comparer) - { - var hashCode = value != null ? comparer.GetHashCode(value) : 0; - Add(hashCode); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static HashCodeCombiner Start() - { - return new HashCodeCombiner(0x1505L); - } - } -} \ No newline at end of file diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Microsoft.DotNet.PlatformAbstractions.csproj b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Microsoft.DotNet.PlatformAbstractions.csproj deleted file mode 100644 index 93d5362c72e23..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Microsoft.DotNet.PlatformAbstractions.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Abstractions for making code that uses file system and environment testable. - net45;netstandard1.3;netstandard2.0 - netstandard1.3;netstandard2.0 - true - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Darwin.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Darwin.cs deleted file mode 100644 index 0e0b7c0c576d6..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Darwin.cs +++ /dev/null @@ -1,56 +0,0 @@ -// 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.InteropServices; - -namespace Microsoft.DotNet.PlatformAbstractions.Native -{ - internal static partial class NativeMethods - { - public static class Darwin - { - private const int CTL_KERN = 1; - private const int KERN_OSRELEASE = 2; - - public unsafe static string GetKernelRelease() - { - const uint BUFFER_LENGTH = 32; - - var name = stackalloc int[2]; - name[0] = CTL_KERN; - name[1] = KERN_OSRELEASE; - - var buf = stackalloc byte[(int)BUFFER_LENGTH]; - var len = stackalloc uint[1]; - *len = BUFFER_LENGTH; - - try - { - // If the buffer isn't big enough, it seems sysctl still returns 0 and just sets len to the - // necessary buffer size. This appears to be contrary to the man page, but it's easy to detect - // by simply checking len against the buffer length. - if (sysctl(name, 2, buf, len, IntPtr.Zero, 0) == 0 && *len < BUFFER_LENGTH) - { - return Marshal.PtrToStringAnsi((IntPtr)buf, (int)*len); - } - } - catch (Exception ex) - { - throw new PlatformNotSupportedException("Error reading Darwin Kernel Version", ex); - } - throw new PlatformNotSupportedException("Unknown error reading Darwin Kernel Version"); - } - - [DllImport("libc")] - private unsafe static extern int sysctl( - int* name, - uint namelen, - byte* oldp, - uint* oldlenp, - IntPtr newp, - uint newlen); - } - } -} diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Unix.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Unix.cs deleted file mode 100644 index c1976308260f1..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Unix.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -#if NET45 - -using System; -using System.Runtime.InteropServices; - -namespace Microsoft.DotNet.PlatformAbstractions.Native -{ - internal static partial class NativeMethods - { - public static class Unix - { - public unsafe static string GetUname() - { - // Utsname shouldn't be larger than 2K - var buf = stackalloc byte[2048]; - - try - { - if (uname((IntPtr)buf) == 0) - { - return Marshal.PtrToStringAnsi((IntPtr)buf); - } - } - catch (Exception ex) - { - throw new PlatformNotSupportedException("Error reading Unix name", ex); - } - throw new PlatformNotSupportedException("Unknown error reading Unix name"); - } - - [DllImport("libc")] - private static extern int uname(IntPtr utsname); - } - } -} -#endif \ No newline at end of file diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Windows.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Windows.cs deleted file mode 100644 index 58c31603a0e1f..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/NativeMethods.Windows.cs +++ /dev/null @@ -1,44 +0,0 @@ -// 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.Runtime.InteropServices; - -namespace Microsoft.DotNet.PlatformAbstractions.Native -{ - internal static partial class NativeMethods - { - public static class Windows - { - [StructLayout(LayoutKind.Sequential)] - internal struct RTL_OSVERSIONINFOEX - { - internal uint dwOSVersionInfoSize; - internal uint dwMajorVersion; - internal uint dwMinorVersion; - internal uint dwBuildNumber; - internal uint dwPlatformId; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] - internal string szCSDVersion; - } - - // This call avoids the shimming Windows does to report old versions - [DllImport("ntdll")] - private static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation); - - internal static string RtlGetVersion() - { - RTL_OSVERSIONINFOEX osvi = new RTL_OSVERSIONINFOEX(); - osvi.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osvi); - if (RtlGetVersion(out osvi) == 0) - { - return $"{osvi.dwMajorVersion}.{osvi.dwMinorVersion}.{osvi.dwBuildNumber}"; - } - else - { - return null; - } - } - } - } -} diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/PlatformApis.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/PlatformApis.cs deleted file mode 100644 index 1a344034304e7..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Native/PlatformApis.cs +++ /dev/null @@ -1,236 +0,0 @@ -// 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.IO; -using System.Runtime.InteropServices; - -namespace Microsoft.DotNet.PlatformAbstractions.Native -{ - internal static class PlatformApis - { - private class DistroInfo - { - public string Id; - public string VersionId; - } - - private static readonly Lazy _platform = new Lazy(DetermineOSPlatform); - private static readonly Lazy _distroInfo = new Lazy(LoadDistroInfo); - - public static string GetOSName() - { - switch (GetOSPlatform()) - { - case Platform.Windows: - return "Windows"; - case Platform.Linux: - return GetDistroId() ?? "Linux"; - case Platform.Darwin: - return "Mac OS X"; - case Platform.FreeBSD: - return "FreeBSD"; - default: - return "Unknown"; - } - } - - public static string GetOSVersion() - { - switch (GetOSPlatform()) - { - case Platform.Windows: - return NativeMethods.Windows.RtlGetVersion() ?? string.Empty; - case Platform.Linux: - return GetDistroVersionId() ?? string.Empty; - case Platform.Darwin: - return GetDarwinVersion() ?? string.Empty; - case Platform.FreeBSD: - return GetFreeBSDVersion() ?? string.Empty; - default: - return string.Empty; - } - } - - private static string GetDarwinVersion() - { - Version version; - var kernelRelease = NativeMethods.Darwin.GetKernelRelease(); - if (!Version.TryParse(kernelRelease, out version) || version.Major < 5) - { - // 10.0 covers all versions prior to Darwin 5 - // Similarly, if the version is not a valid version number, but we have still detected that it is Darwin, we just assume - // it is OS X 10.0 - return "10.0"; - } - else - { - // Mac OS X 10.1 mapped to Darwin 5.x, and the mapping continues that way - // So just subtract 4 from the Darwin version. - // https://en.wikipedia.org/wiki/Darwin_%28operating_system%29 - return $"10.{version.Major - 4}"; - } - } - - private static string GetFreeBSDVersion() - { - // This is same as sysctl kern.version - // FreeBSD 11.0-RELEASE-p1 FreeBSD 11.0-RELEASE-p1 #0 r306420: Thu Sep 29 01:43:23 UTC 2016 root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC - // What we want is major release as minor releases should be compatible. - String version = RuntimeInformation.OSDescription; - try - { - // second token up to first dot - return RuntimeInformation.OSDescription.Split()[1].Split('.')[0]; - } - catch - { - } - return string.Empty; - } - - public static Platform GetOSPlatform() - { - return _platform.Value; - } - - private static string GetDistroId() - { - return _distroInfo.Value?.Id; - } - - private static string GetDistroVersionId() - { - return _distroInfo.Value?.VersionId; - } - - private static DistroInfo LoadDistroInfo() - { - DistroInfo result = null; - - // Sample os-release file: - // NAME="Ubuntu" - // VERSION = "14.04.3 LTS, Trusty Tahr" - // ID = ubuntu - // ID_LIKE = debian - // PRETTY_NAME = "Ubuntu 14.04.3 LTS" - // VERSION_ID = "14.04" - // HOME_URL = "http://www.ubuntu.com/" - // SUPPORT_URL = "http://help.ubuntu.com/" - // BUG_REPORT_URL = "http://bugs.launchpad.net/ubuntu/" - // We use ID and VERSION_ID - - if (File.Exists("/etc/os-release")) - { - var lines = File.ReadAllLines("/etc/os-release"); - result = new DistroInfo(); - foreach (var line in lines) - { - if (line.StartsWith("ID=", StringComparison.Ordinal)) - { - result.Id = line.Substring(3).Trim('"', '\''); - } - else if (line.StartsWith("VERSION_ID=", StringComparison.Ordinal)) - { - result.VersionId = line.Substring(11).Trim('"', '\''); - } - } - } - - if (result != null) - { - result = NormalizeDistroInfo(result); - } - - return result; - } - - // For some distros, we don't want to use the full version from VERSION_ID. One example is - // Red Hat Enterprise Linux, which includes a minor version in their VERSION_ID but minor - // versions are backwards compatable. - // - // In this case, we'll normalized RIDs like 'rhel.7.2' and 'rhel.7.3' to a generic - // 'rhel.7'. This brings RHEL in line with other distros like CentOS or Debian which - // don't put minor version numbers in their VERSION_ID fields because all minor versions - // are backwards compatible. - private static DistroInfo NormalizeDistroInfo(DistroInfo distroInfo) - { - // Handle if VersionId is null by just setting the index to -1. - int lastVersionNumberSeparatorIndex = distroInfo.VersionId?.IndexOf('.') ?? -1; - - if (lastVersionNumberSeparatorIndex != -1 && distroInfo.Id == "alpine") - { - // For Alpine, the version reported has three components, so we need to find the second version separator - lastVersionNumberSeparatorIndex = distroInfo.VersionId.IndexOf('.', lastVersionNumberSeparatorIndex + 1); - } - - if (lastVersionNumberSeparatorIndex != -1 && (distroInfo.Id == "rhel" || distroInfo.Id == "alpine")) - { - distroInfo.VersionId = distroInfo.VersionId.Substring(0, lastVersionNumberSeparatorIndex); - } - - return distroInfo; - } - - // I could probably have just done one method signature and put the #if inside the body but the implementations - // are just completely different so I wanted to make that clear by putting the whole thing inside the #if. -#if NET45 - private static Platform DetermineOSPlatform() - { - var platform = (int)Environment.OSVersion.Platform; - var isWindows = (platform != 4) && (platform != 6) && (platform != 128); - - if (isWindows) - { - return Platform.Windows; - } - else - { - try - { - var uname = NativeMethods.Unix.GetUname(); - if (string.Equals(uname, "Darwin", StringComparison.OrdinalIgnoreCase)) - { - return Platform.Darwin; - } - if (string.Equals(uname, "Linux", StringComparison.OrdinalIgnoreCase)) - { - return Platform.Linux; - } - if (string.Equals(uname, "FreeBSD", StringComparison.OrdinalIgnoreCase)) - { - return Platform.FreeBSD; - } - } - catch - { - } - return Platform.Unknown; - } - } -#else - private static Platform DetermineOSPlatform() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return Platform.Windows; - } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return Platform.Linux; - } - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return Platform.Darwin; - } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD"))) - { - return Platform.FreeBSD; - } - - return Platform.Unknown; - } -#endif - } -} diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Platform.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Platform.cs deleted file mode 100644 index a8d7477ec55c2..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Platform.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright(c) .NET Foundation and contributors.All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.DotNet.PlatformAbstractions -{ - public enum Platform - { - Unknown = 0, - Windows = 1, - Linux = 2, - Darwin = 3, - FreeBSD = 4 - } -} diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Properties/Properties.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Properties/Properties.cs deleted file mode 100644 index ffc81f49b41fe..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/Properties/Properties.cs +++ /dev/null @@ -1,4 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -[assembly: AssemblyMetadataAttribute("Serviceable", "True")] diff --git a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/RuntimeEnvironment.cs b/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/RuntimeEnvironment.cs deleted file mode 100644 index ffece180eb960..0000000000000 --- a/src/installer/managed/Microsoft.DotNet.PlatformAbstractions/RuntimeEnvironment.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright(c) .NET Foundation and contributors.All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Runtime.InteropServices; -using Microsoft.DotNet.PlatformAbstractions.Native; - -namespace Microsoft.DotNet.PlatformAbstractions -{ - public static class RuntimeEnvironment - { - private static readonly string OverrideEnvironmentVariableName = "DOTNET_RUNTIME_ID"; - - public static Platform OperatingSystemPlatform { get; } = PlatformApis.GetOSPlatform(); - - public static string OperatingSystemVersion { get; } = PlatformApis.GetOSVersion(); - - public static string OperatingSystem { get; } = PlatformApis.GetOSName(); - - public static string RuntimeArchitecture { get; } = GetArch(); - - private static string GetArch() - { -#if NET45 - return Environment.Is64BitProcess ? "x64" : "x86"; -#else - return RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); -#endif - } - - public static string GetRuntimeIdentifier() - { - return - Environment.GetEnvironmentVariable(OverrideEnvironmentVariableName) ?? - (GetRIDOS() + GetRIDVersion() + GetRIDArch()); - } - - private static string GetRIDArch() - { - return $"-{RuntimeArchitecture}"; - } - - private static string GetRIDVersion() - { - // Windows RIDs do not separate OS name and version by "." due to legacy - // Others do, that's why we have the "." prefix on them below - switch (OperatingSystemPlatform) - { - case Platform.Windows: - return GetWindowsProductVersion(); - case Platform.Linux: - if (string.IsNullOrEmpty(OperatingSystemVersion)) - { - return string.Empty; - } - - return $".{OperatingSystemVersion}"; - case Platform.Darwin: - return $".{OperatingSystemVersion}"; - case Platform.FreeBSD: - return $".{OperatingSystemVersion}"; - default: - return string.Empty; // Unknown Platform? Unknown Version! - } - } - - private static string GetWindowsProductVersion() - { - var ver = Version.Parse(OperatingSystemVersion); - if (ver.Major == 6) - { - if (ver.Minor == 1) - { - return "7"; - } - else if (ver.Minor == 2) - { - return "8"; - } - else if (ver.Minor == 3) - { - return "81"; - } - } - else if (ver.Major >= 10) - { - // Return the major version for use in RID computation without applying any cap. - return ver.Major.ToString(); - } - return string.Empty; // Unknown version - } - - private static string GetRIDOS() - { - switch (OperatingSystemPlatform) - { - case Platform.Windows: - return "win"; - case Platform.Linux: - return OperatingSystem.ToLowerInvariant(); - case Platform.Darwin: - return "osx"; - case Platform.FreeBSD: - return "freebsd"; - default: - return "unknown"; - } - } - } -} diff --git a/src/installer/pkg/packaging/pack-managed.proj b/src/installer/pkg/packaging/pack-managed.proj index 5db5f08264bdc..acefdfff86d10 100644 --- a/src/installer/pkg/packaging/pack-managed.proj +++ b/src/installer/pkg/packaging/pack-managed.proj @@ -2,7 +2,7 @@ - $(NETCoreAppFramework) + $(NetCoreAppCurrent) diff --git a/src/installer/pkg/packaging/vs-insertion-packages.proj b/src/installer/pkg/packaging/vs-insertion-packages.proj index f36b24f9d1cac..fd69aea557f75 100644 --- a/src/installer/pkg/packaging/vs-insertion-packages.proj +++ b/src/installer/pkg/packaging/vs-insertion-packages.proj @@ -2,7 +2,7 @@ - $(NETCoreAppFramework) + $(NetCoreAppCurrent) diff --git a/src/installer/pkg/projects/Directory.Build.props b/src/installer/pkg/projects/Directory.Build.props index 40403c6fcd07f..9d6ae93d467c3 100644 --- a/src/installer/pkg/projects/Directory.Build.props +++ b/src/installer/pkg/projects/Directory.Build.props @@ -81,9 +81,9 @@ null-refs when this isn't set and an analyzer is in the packages --> unused - $(NETCoreAppFrameworkMoniker) - $(NETCoreAppFramework) - $(NETCoreAppFramework) + $(NetCoreAppCurrentTargetFrameworkMoniker) + $(NetCoreAppCurrent) + $(NetCoreAppCurrent) $(CrossGenRootPath)$(MSBuildProjectName)\ true true @@ -92,7 +92,7 @@ $(PackageTargetFramework) - $(NETCoreAppFramework) + $(NetCoreAppCurrent) diff --git a/src/installer/pkg/projects/Directory.Build.targets b/src/installer/pkg/projects/Directory.Build.targets index 3617dde42ecad..cfe8c6400779c 100644 --- a/src/installer/pkg/projects/Directory.Build.targets +++ b/src/installer/pkg/projects/Directory.Build.targets @@ -3,8 +3,8 @@ - - + + $(Version) + true - + @@ -324,7 +331,8 @@ FileClassifications="@(FrameworkListFileClass)" TargetFile="$(FrameworkListFile)" TargetFilePrefixes="ref/;runtimes/" - RootAttributes="@(FrameworkListRootAttributes)" /> + RootAttributes="@(FrameworkListRootAttributes)" + SingleFileHostIncludeFilenames="@(SingleFileHostIncludeFilename)" /> @@ -371,7 +379,7 @@ + ExcludeAssets="All" /> diff --git a/src/installer/pkg/projects/netcoreapp/Directory.Build.props b/src/installer/pkg/projects/netcoreapp/Directory.Build.props index 32f632cbe656f..59ac9e4269092 100644 --- a/src/installer/pkg/projects/netcoreapp/Directory.Build.props +++ b/src/installer/pkg/projects/netcoreapp/Directory.Build.props @@ -14,6 +14,8 @@ Android Browser FreeBSD + NetBSD + SunOS $(CoreCLRTargetOS) diff --git a/src/installer/pkg/projects/netcoreapp/pkg/Directory.Build.props b/src/installer/pkg/projects/netcoreapp/pkg/Directory.Build.props index a34488f1be6c3..e616a7cfc1f9a 100644 --- a/src/installer/pkg/projects/netcoreapp/pkg/Directory.Build.props +++ b/src/installer/pkg/projects/netcoreapp/pkg/Directory.Build.props @@ -6,12 +6,39 @@ - $(NETCoreAppFrameworkBrandName) - $(NETCoreAppFrameworkIdentifier) - $(NETCoreAppFrameworkVersion) + $(NetCoreAppCurrentBrandName) + $(NetCoreAppCurrentIdentifier) + $(NetCoreAppCurrentVersion) $(SharedFrameworkName) + + + + + + + + + + + + + + + + + + + + + + + + + + + true - build/$(NETCoreAppFramework)/ + build/$(NetCoreAppCurrent)/ false @@ -17,7 +17,7 @@ + TargetFramework="$(NetCoreAppCurrent)" /> diff --git a/src/installer/pkg/projects/netcoreapp/pkg/legacy/Microsoft.NETCore.App.Internal.pkgproj b/src/installer/pkg/projects/netcoreapp/pkg/legacy/Microsoft.NETCore.App.Internal.pkgproj index bf4c13e02e050..a46f80401902f 100644 --- a/src/installer/pkg/projects/netcoreapp/pkg/legacy/Microsoft.NETCore.App.Internal.pkgproj +++ b/src/installer/pkg/projects/netcoreapp/pkg/legacy/Microsoft.NETCore.App.Internal.pkgproj @@ -20,8 +20,8 @@ - - + + diff --git a/src/installer/pkg/projects/netcoreapp/sfx/Microsoft.NETCore.App.SharedFx.sfxproj b/src/installer/pkg/projects/netcoreapp/sfx/Microsoft.NETCore.App.SharedFx.sfxproj index d12d993a3ff61..f1aab81eb8a4b 100644 --- a/src/installer/pkg/projects/netcoreapp/sfx/Microsoft.NETCore.App.SharedFx.sfxproj +++ b/src/installer/pkg/projects/netcoreapp/sfx/Microsoft.NETCore.App.SharedFx.sfxproj @@ -45,6 +45,30 @@ + + + + + + + + + + + + + + + + + + + + x86 @@ -34,6 +36,7 @@ + armel diff --git a/src/installer/publish/Directory.Build.props b/src/installer/publish/Directory.Build.props index adae9ea9ed0af..de832e525302d 100644 --- a/src/installer/publish/Directory.Build.props +++ b/src/installer/publish/Directory.Build.props @@ -3,7 +3,7 @@ - $(NETCoreAppFramework) + $(NetCoreAppCurrent) diff --git a/src/installer/signing/Directory.Build.props b/src/installer/signing/Directory.Build.props index 8fcaf35bd68f9..7c45d0300be12 100644 --- a/src/installer/signing/Directory.Build.props +++ b/src/installer/signing/Directory.Build.props @@ -3,7 +3,7 @@ - $(NETCoreAppFramework) + $(NetCoreAppCurrent) true diff --git a/src/installer/signing/SignBinaries.proj b/src/installer/signing/SignBinaries.proj index d1f8fb542904e..8b1f6811f442f 100644 --- a/src/installer/signing/SignBinaries.proj +++ b/src/installer/signing/SignBinaries.proj @@ -1,7 +1,7 @@ - + diff --git a/src/installer/signing/SignBurnBundleFiles.proj b/src/installer/signing/SignBurnBundleFiles.proj index 52cac286090a1..55c7a8c5810de 100644 --- a/src/installer/signing/SignBurnBundleFiles.proj +++ b/src/installer/signing/SignBurnBundleFiles.proj @@ -4,7 +4,7 @@ diff --git a/src/installer/signing/SignBurnEngineFiles.proj b/src/installer/signing/SignBurnEngineFiles.proj index dc610b685cfb3..382eb202318fb 100644 --- a/src/installer/signing/SignBurnEngineFiles.proj +++ b/src/installer/signing/SignBurnEngineFiles.proj @@ -1,7 +1,7 @@ - + diff --git a/src/installer/signing/SignMsiFiles.proj b/src/installer/signing/SignMsiFiles.proj index 55804e6c46c4e..55dd18dca6732 100644 --- a/src/installer/signing/SignMsiFiles.proj +++ b/src/installer/signing/SignMsiFiles.proj @@ -1,7 +1,7 @@ - + - + diff --git a/src/installer/test/Assets/TestUtils/TestProjects.targets b/src/installer/test/Assets/TestUtils/TestProjects.targets index 1ee0e9450058d..32180ba2f700d 100644 --- a/src/installer/test/Assets/TestUtils/TestProjects.targets +++ b/src/installer/test/Assets/TestUtils/TestProjects.targets @@ -4,12 +4,4 @@ provides basic info needed for restore and build with the vanilla SDK. --> - - - $(MajorVersion).$(MinorVersion) - - diff --git a/src/installer/test/Directory.Build.targets b/src/installer/test/Directory.Build.targets index 82a7c6d4e6010..7d93a09399835 100644 --- a/src/installer/test/Directory.Build.targets +++ b/src/installer/test/Directory.Build.targets @@ -81,7 +81,7 @@ - + diff --git a/src/installer/test/HostActivation.Tests/HostActivation.Tests.csproj b/src/installer/test/HostActivation.Tests/HostActivation.Tests.csproj index 892ad3cafb63f..95b8cfd9a9f6e 100644 --- a/src/installer/test/HostActivation.Tests/HostActivation.Tests.csproj +++ b/src/installer/test/HostActivation.Tests/HostActivation.Tests.csproj @@ -17,8 +17,7 @@ - - + diff --git a/src/installer/test/HostActivation.Tests/HostVersionCompatibility.cs b/src/installer/test/HostActivation.Tests/HostVersionCompatibility.cs index 67a4f70b9c9b7..afb0862fecde9 100644 --- a/src/installer/test/HostActivation.Tests/HostVersionCompatibility.cs +++ b/src/installer/test/HostActivation.Tests/HostVersionCompatibility.cs @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. using Microsoft.DotNet.Cli.Build.Framework; -using Microsoft.DotNet.PlatformAbstractions; using System; using System.IO; +using System.Runtime.InteropServices; using Xunit; namespace Microsoft.DotNet.CoreSetup.Test.HostActivation @@ -137,13 +137,11 @@ private void Old_Host_Is_Forward_Compatible_With_Latest_Runtime(TestProjectFixtu private static bool IsRidSupported() { - Platform platform = RuntimeEnvironment.OperatingSystemPlatform; - // Some current Linux RIDs are not supported in 2.0\2.1; just test for Ubuntu 16. return ( - platform == Platform.Windows || - platform == Platform.Darwin || - (platform == Platform.Linux && RuntimeEnvironment.GetRuntimeIdentifier() == "ubuntu.16.04-x64") + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || + (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && RuntimeInformation.RuntimeIdentifier == "ubuntu.16.04-x64") ); } diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs index 26dbc3a00ef83..8f9e97415285b 100644 --- a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs +++ b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs @@ -30,7 +30,7 @@ private void Bundle_Extraction_To_Specific_Path_Succeeds() // Publish the bundle string singleFile; - Bundler bundler = BundleHelper.BundleApp(fixture, out singleFile); + Bundler bundler = BundleHelper.BundleApp(fixture, out singleFile, options: BundleOptions.BundleNativeBinaries); // Verify expected files in the bundle directory var bundleDir = BundleHelper.GetBundleDir(fixture); @@ -157,7 +157,6 @@ private void Bundle_extraction_can_recover_missing_files() extractDir.Should().HaveFiles(extractedFiles); } - public class SharedTestState : IDisposable { public TestProjectFixture TestFixture { get; set; } diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleRename.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleRename.cs index 581a1155c98f9..8decb64146690 100644 --- a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleRename.cs +++ b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleRename.cs @@ -7,6 +7,7 @@ using Xunit; using Microsoft.DotNet.Cli.Build.Framework; using Microsoft.DotNet.CoreSetup.Test; +using Microsoft.NET.HostModel.Bundle; using BundleTests.Helpers; using System.Threading; @@ -22,38 +23,30 @@ public BundleRename(SharedTestState fixture) } [Theory] - [InlineData(true)] // Test renaming the single-exe during the initial run, when contents are extracted - [InlineData(false)] // Test renaming the single-exe during subsequent runs, when contents are reused - private void Bundle_can_be_renamed_while_running(bool renameFirstRun) + [InlineData(true)] // Test renaming the single-exe when contents are extracted + [InlineData(false)] // Test renaming the single-exe when contents are not extracted + private void Bundle_can_be_renamed_while_running(bool testExtraction) { var fixture = sharedTestState.TestFixture.Copy(); - string singleFile = BundleHelper.BundleApp(fixture); + BundleOptions options = testExtraction ? BundleOptions.BundleAllContent : BundleOptions.None; + string singleFile = BundleHelper.BundleApp(fixture, options); string outputDir = Path.GetDirectoryName(singleFile); string renameFile = Path.Combine(outputDir, Path.GetRandomFileName()); string waitFile = Path.Combine(outputDir, "wait"); string resumeFile = Path.Combine(outputDir, "resume"); - if (!renameFirstRun) - { - Command.Create(singleFile) - .CaptureStdErr() - .CaptureStdOut() - .Execute() - .Should() - .Pass() - .And - .HaveStdOutContaining("Hello World!"); - } - // Once the App starts running, it creates the waitFile, and waits until resumeFile file is created. var singleExe = Command.Create(singleFile, waitFile, resumeFile) .CaptureStdErr() .CaptureStdOut() .Start(); - while (!File.Exists(waitFile) && !singleExe.Process.HasExited) + const int twoMitutes = 120000 /*milliseconds*/; + int waitTime = 0; + while (!File.Exists(waitFile) && !singleExe.Process.HasExited && waitTime < twoMitutes) { Thread.Sleep(100); + waitTime += 100; } Assert.True(File.Exists(waitFile)); @@ -61,7 +54,7 @@ private void Bundle_can_be_renamed_while_running(bool renameFirstRun) File.Move(singleFile, renameFile); File.Create(resumeFile).Close(); - var result = singleExe.WaitForExit(fExpectedToFail: false); + var result = singleExe.WaitForExit(fExpectedToFail: false, twoMitutes); result .Should() diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs index 33e05b5c0504d..ff15ee6fb80f1 100644 --- a/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs +++ b/src/installer/test/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs @@ -32,9 +32,7 @@ private void RunTheApp(string path) .HaveStdOutContaining("Wow! We now say hello to the big world and you."); } - // BundleOptions.BundleNativeBinaries: Test when the payload data files are unbundled, and beside the single-file app. - // BundleOptions.BundleAllContent: Test when the payload data files are bundled and extracted to temporary directory. - // Once the runtime can load assemblies from the bundle, BundleOptions.None can be used in place of BundleOptions.BundleNativeBinaries. + [InlineData(BundleOptions.None)] [InlineData(BundleOptions.BundleNativeBinaries)] [InlineData(BundleOptions.BundleAllContent)] [Theory] @@ -50,6 +48,7 @@ public void Bundled_Framework_dependent_App_Run_Succeeds(BundleOptions options) RunTheApp(singleFile); } + [InlineData(BundleOptions.None)] [InlineData(BundleOptions.BundleNativeBinaries)] [InlineData(BundleOptions.BundleAllContent)] [Theory] @@ -65,6 +64,7 @@ public void Bundled_Self_Contained_App_Run_Succeeds(BundleOptions options) RunTheApp(singleFile); } + [InlineData(BundleOptions.None)] [InlineData(BundleOptions.BundleNativeBinaries)] [InlineData(BundleOptions.BundleAllContent)] [Theory] diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/Helpers/BundleHelper.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/Helpers/BundleHelper.cs index c5f7717943676..def3a46956399 100644 --- a/src/installer/test/Microsoft.NET.HostModel.Tests/Helpers/BundleHelper.cs +++ b/src/installer/test/Microsoft.NET.HostModel.Tests/Helpers/BundleHelper.cs @@ -53,8 +53,7 @@ public static string[] GetBundledFiles(TestProjectFixture fixture) public static string[] GetExtractedFiles(TestProjectFixture fixture) { - string appBaseName = GetAppBaseName(fixture); - return new string[] { $"{appBaseName}.dll" }; + return new string[] { Path.GetFileName(fixture.TestProject.CoreClrDll) }; } public static string[] GetFilesNeverExtracted(TestProjectFixture fixture) @@ -62,6 +61,7 @@ public static string[] GetFilesNeverExtracted(TestProjectFixture fixture) string appBaseName = GetAppBaseName(fixture); return new string[] { $"{appBaseName}.deps.json", $"{appBaseName}.runtimeconfig.json", + $"{appBaseName}.dll", Path.GetFileName(fixture.TestProject.HostFxrDll), Path.GetFileName(fixture.TestProject.HostPolicyDll) }; } @@ -139,7 +139,7 @@ public static string GenerateBundle(Bundler bundler, string sourceDir, string ou // which may not (yet) be available in the SDK. public static Bundler BundleApp(TestProjectFixture fixture, out string singleFile, - BundleOptions options = BundleOptions.BundleNativeBinaries, + BundleOptions options = BundleOptions.None, Version targetFrameworkVersion = null, bool copyExcludedFiles = true) { @@ -153,11 +153,8 @@ public static string GenerateBundle(Bundler bundler, string sourceDir, string ou return bundler; } - // The defaut option for Bundling apps is BundleOptions.BundleNativeBinaries - // Until CoreCLR runtime can learn how to process assemblies from the bundle. - // This is because CoreCLR expects System.Private.Corelib.dll to be beside CoreCLR.dll public static string BundleApp(TestProjectFixture fixture, - BundleOptions options = BundleOptions.BundleNativeBinaries, + BundleOptions options = BundleOptions.None, Version targetFrameworkVersion = null) { string singleFile; diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleAndRun.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleAndRun.cs index e4949b47750da..bf9ff14cf5b0f 100644 --- a/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleAndRun.cs +++ b/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleAndRun.cs @@ -32,7 +32,7 @@ private void RunTheApp(string path) .HaveStdOutContaining("Wow! We now say hello to the big world and you."); } - private void BundleRun(TestProjectFixture fixture, string publishPath, string singleFileDir) + private void BundleRun(TestProjectFixture fixture, string publishPath) { var hostName = BundleHelper.GetHostName(fixture); @@ -56,33 +56,24 @@ private string RelativePath(string path) public void TestWithAbsolutePaths() { var fixture = sharedTestState.TestFixture.Copy(); - string publishDir = BundleHelper.GetPublishPath(fixture); - string outputDir = BundleHelper.GetBundleDir(fixture).FullName; - - BundleRun(fixture, publishDir, outputDir); + BundleRun(fixture, publishDir); } [Fact] public void TestWithRelativePaths() { var fixture = sharedTestState.TestFixture.Copy(); - string publishDir = RelativePath(BundleHelper.GetPublishPath(fixture)); - string outputDir = RelativePath(BundleHelper.GetBundleDir(fixture).FullName); - - BundleRun(fixture, publishDir, outputDir); + BundleRun(fixture, publishDir); } [Fact] public void TestWithRelativePathsDirSeparator() { var fixture = sharedTestState.TestFixture.Copy(); - string publishDir = RelativePath(BundleHelper.GetPublishPath(fixture)) + Path.DirectorySeparatorChar; - string outputDir = RelativePath(BundleHelper.GetBundleDir(fixture).FullName) + Path.DirectorySeparatorChar; - - BundleRun(fixture, publishDir, outputDir); + BundleRun(fixture, publishDir); } public class SharedTestState : IDisposable diff --git a/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs b/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs index 7b9d6863607d2..1690be766e33a 100644 --- a/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs +++ b/src/installer/test/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundleLegacy.cs @@ -27,8 +27,7 @@ public void TestNetCoreApp3xApp(int minorVersion) { var fixture = (minorVersion == 0) ? sharedTestState.TestFixture30.Copy() : sharedTestState.TestFixture31.Copy(); - // Targetting netcoreap3.x implies BundleOption.BundleAllContent - var singleFile = BundleHelper.BundleApp(fixture, BundleOptions.None, new Version(3, minorVersion)); + var singleFile = BundleHelper.BundleApp(fixture, targetFrameworkVersion: new Version(3, minorVersion)); Command.Create(singleFile) .CaptureStdErr() @@ -50,7 +49,6 @@ private static TestProjectFixture CreatePublishedFixture(string netCoreAppFramew return fixture; } - public class SharedTestState : IDisposable { public TestProjectFixture TestFixture30 { get; set; } diff --git a/src/installer/test/TestUtils/TestProjectFixture.cs b/src/installer/test/TestUtils/TestProjectFixture.cs index b1a67453d716d..5ab37de8f80ff 100644 --- a/src/installer/test/TestUtils/TestProjectFixture.cs +++ b/src/installer/test/TestUtils/TestProjectFixture.cs @@ -233,7 +233,7 @@ private void ValidateRequiredDirectories(RepoDirectoriesProvider repoDirectories } storeArgs.Add($"/p:MNAVersion={RepoDirProvider.MicrosoftNETCoreAppVersion}"); - storeArgs.Add($"/p:NETCoreAppFramework={Framework}"); + storeArgs.Add($"/p:NetCoreAppCurrent={Framework}"); // Ensure the project's OutputType isn't 'Exe', since that causes issues with 'dotnet store' storeArgs.Add("/p:OutputType=Library"); @@ -286,7 +286,7 @@ private void ValidateRequiredDirectories(RepoDirectoriesProvider repoDirectories { publishArgs.Add("--framework"); publishArgs.Add(framework); - publishArgs.Add($"/p:NETCoreAppFramework={framework}"); + publishArgs.Add($"/p:NetCoreAppCurrent={framework}"); } if (selfContained != null) @@ -333,7 +333,7 @@ public TestProjectFixture RestoreProject(string[] fallbackSources, string extraM restoreArgs.Add("--disable-parallel"); restoreArgs.Add($"/p:MNAVersion={RepoDirProvider.MicrosoftNETCoreAppVersion}"); - restoreArgs.Add($"/p:NETCoreAppFramework={Framework}"); + restoreArgs.Add($"/p:NetCoreAppCurrent={Framework}"); if (extraMSBuildProperties != null) { diff --git a/src/installer/test/TestUtils/TestUtils.csproj b/src/installer/test/TestUtils/TestUtils.csproj index 5419bc266a1fb..35cb3e19e9d77 100644 --- a/src/installer/test/TestUtils/TestUtils.csproj +++ b/src/installer/test/TestUtils/TestUtils.csproj @@ -13,7 +13,6 @@ - diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs new file mode 100644 index 0000000000000..1c312dca820e0 --- /dev/null +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -0,0 +1,181 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + public const int SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2; + public const int SEC_WINNT_AUTH_IDENTITY_VERSION = 0x200; + public const string MICROSOFT_KERBEROS_NAME_W = "Kerberos"; + public const uint LDAP_SASL_QUIET = 2; + public const string KerberosDefaultMechanism = "GSSAPI"; +} + +namespace System.DirectoryServices.Protocols +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal class Luid + { + private readonly int _lowPart; + private readonly int _highPart; + + public int LowPart => _lowPart; + public int HighPart => _highPart; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal sealed class SEC_WINNT_AUTH_IDENTITY_EX + { + public int version; + public int length; + public string user; + public int userLength; + public string domain; + public int domainLength; + public string password; + public int passwordLength; + public int flags; + public string packageList; + public int packageListLength; + } + + internal enum BindMethod : uint // Not Supported in Linux + { + LDAP_AUTH_OTHERKIND = 0x86, + LDAP_AUTH_SICILY = LDAP_AUTH_OTHERKIND | 0x0200, + LDAP_AUTH_MSN = LDAP_AUTH_OTHERKIND | 0x0800, + LDAP_AUTH_NTLM = LDAP_AUTH_OTHERKIND | 0x1000, + LDAP_AUTH_DPA = LDAP_AUTH_OTHERKIND | 0x2000, + LDAP_AUTH_NEGOTIATE = LDAP_AUTH_OTHERKIND | 0x0400, + LDAP_AUTH_SSPI = LDAP_AUTH_NEGOTIATE, + LDAP_AUTH_DIGEST = LDAP_AUTH_OTHERKIND | 0x4000, + LDAP_AUTH_EXTERNAL = LDAP_AUTH_OTHERKIND | 0x0020, + LDAP_AUTH_KRBV4 = 0xFF, + LDAP_AUTH_SIMPLE = 0x80 + } + + internal enum LdapOption + { + LDAP_OPT_DESC = 0x01, + LDAP_OPT_DEREF = 0x02, + LDAP_OPT_SIZELIMIT = 0x03, + LDAP_OPT_TIMELIMIT = 0x04, + LDAP_OPT_REFERRALS = 0x08, + LDAP_OPT_RESTART = 0x09, + LDAP_OPT_SSL = 0x0a, // Not Supported in Linux + LDAP_OPT_REFERRAL_HOP_LIMIT = 0x10, // Not Supported in Linux + LDAP_OPT_VERSION = 0x11, + LDAP_OPT_SERVER_CONTROLS = 0x12, // Not Supported in Windows + LDAP_OPT_CLIENT_CONTROLS = 0x13, // Not Supported in Windows + LDAP_OPT_API_FEATURE_INFO = 0x15, + LDAP_OPT_HOST_NAME = 0x30, + LDAP_OPT_ERROR_NUMBER = 0x31, + LDAP_OPT_ERROR_STRING = 0x32, + LDAP_OPT_SERVER_ERROR = 0x33, + LDAP_OPT_SERVER_EXT_ERROR = 0x34, // Not Supported in Linux + LDAP_OPT_HOST_REACHABLE = 0x3E, // Not Supported in Linux + LDAP_OPT_PING_KEEP_ALIVE = 0x36, // Not Supported in Linux + LDAP_OPT_PING_WAIT_TIME = 0x37, // Not Supported in Linux + LDAP_OPT_PING_LIMIT = 0x38, // Not Supported in Linux + LDAP_OPT_DNSDOMAIN_NAME = 0x3B, // Not Supported in Linux + LDAP_OPT_GETDSNAME_FLAGS = 0x3D, // Not Supported in Linux + LDAP_OPT_PROMPT_CREDENTIALS = 0x3F, // Not Supported in Linux + LDAP_OPT_TCP_KEEPALIVE = 0x40, // Not Supported in Linux + LDAP_OPT_FAST_CONCURRENT_BIND = 0x41, // Not Supported in Linux + LDAP_OPT_SEND_TIMEOUT = 0x42, // Not Supported in Linux + LDAP_OPT_REFERRAL_CALLBACK = 0x70, // Not Supported in Linux + LDAP_OPT_CLIENT_CERTIFICATE = 0x80, // Not Supported in Linux + LDAP_OPT_SERVER_CERTIFICATE = 0x81, // Not Supported in Linux + LDAP_OPT_AUTO_RECONNECT = 0x91, // Not Supported in Linux + LDAP_OPT_SSPI_FLAGS = 0x92, + LDAP_OPT_SSL_INFO = 0x93, // Not Supported in Linux + LDAP_OPT_SIGN = 0x95, + LDAP_OPT_ENCRYPT = 0x96, + LDAP_OPT_SASL_METHOD = 0x97, + LDAP_OPT_AREC_EXCLUSIVE = 0x98, // Not Supported in Linux + LDAP_OPT_SECURITY_CONTEXT = 0x99, + LDAP_OPT_ROOTDSE_CACHE = 0x9a, // Not Supported in Linux + LDAP_OPT_X_SASL_REALM = 0x6101, + LDAP_OPT_X_SASL_AUTHCID = 0x6102, + LDAP_OPT_X_SASL_AUTHZID = 0x6103 + } + + internal enum ResultAll + { + LDAP_MSG_ALL = 1, + LDAP_MSG_RECEIVED = 2, + LDAP_MSG_POLLINGALL = 3 // Not Supported in Linux + } + + [StructLayout(LayoutKind.Sequential)] + internal sealed class LDAP_TIMEVAL + { + public int tv_sec; + public int tv_usec; + } + + [StructLayout(LayoutKind.Sequential)] + internal sealed class berval + { + public int bv_len = 0; + public IntPtr bv_val = IntPtr.Zero; + + public berval() { } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal sealed class LdapControl + { + public IntPtr ldctl_oid = IntPtr.Zero; + public berval ldctl_value = null; + public bool ldctl_iscritical = false; + + public LdapControl() { } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct LdapReferralCallback + { + public int sizeofcallback; + public QUERYFORCONNECTIONInternal query; + public NOTIFYOFNEWCONNECTIONInternal notify; + public DEREFERENCECONNECTIONInternal dereference; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct CRYPTOAPI_BLOB + { + public int cbData; + public IntPtr pbData; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct SecPkgContext_IssuerListInfoEx + { + public IntPtr aIssuers; + public int cIssuers; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal sealed class LdapMod + { + public int type = 0; + public IntPtr attribute = IntPtr.Zero; + public IntPtr values = IntPtr.Zero; + + ~LdapMod() + { + if (attribute != IntPtr.Zero) + { + Marshal.FreeHGlobal(attribute); + } + + if (values != IntPtr.Zero) + { + Marshal.FreeHGlobal(values); + } + } + } +} diff --git a/src/libraries/Common/src/Interop/Interop.Libraries.cs b/src/libraries/Common/src/Interop/Interop.Libraries.cs index 4fee38ad35bd2..d58d6a2126a4d 100644 --- a/src/libraries/Common/src/Interop/Interop.Libraries.cs +++ b/src/libraries/Common/src/Interop/Interop.Libraries.cs @@ -6,6 +6,10 @@ internal static partial class Interop { internal static partial class Libraries { - internal const string GlobalizationNative = "libSystem.Globalization.Native"; +#if MONO + internal const string GlobalizationNative = "__Internal"; +#else + internal const string GlobalizationNative = "QCall"; +#endif } } diff --git a/src/libraries/Common/src/Interop/Linux/Interop.Libraries.cs b/src/libraries/Common/src/Interop/Linux/Interop.Libraries.cs index 25f0ce0a445e9..e7bc0d31f0d86 100644 --- a/src/libraries/Common/src/Interop/Linux/Interop.Libraries.cs +++ b/src/libraries/Common/src/Interop/Linux/Interop.Libraries.cs @@ -7,6 +7,7 @@ internal static partial class Interop internal static partial class Libraries { internal const string Odbc32 = "libodbc.so.2"; + internal const string OpenLdap = "libldap-2.4.so.2"; internal const string MsQuic = "msquic"; } } diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs new file mode 100644 index 0000000000000..4a059e35dacdb --- /dev/null +++ b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs @@ -0,0 +1,52 @@ +// 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.InteropServices; +using System.DirectoryServices.Protocols; + +internal static partial class Interop +{ + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_alloc_t", CharSet = CharSet.Ansi)] + public static extern IntPtr ber_alloc(int option); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_init", CharSet = CharSet.Ansi)] + public static extern IntPtr ber_init(berval value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_free", CharSet = CharSet.Ansi)] + public static extern IntPtr ber_free([In] IntPtr berelement, int option); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)] + public static extern int ber_printf_emptyarg(SafeBerHandle berElement, string format); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)] + public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)] + public static extern int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)] + public static extern int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_flatten", CharSet = CharSet.Ansi)] + public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_bvfree", CharSet = CharSet.Ansi)] + public static extern int ber_bvfree(IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_bvecfree", CharSet = CharSet.Ansi)] + public static extern int ber_bvecfree(IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)] + public static extern int ber_scanf(SafeBerHandle berElement, string format); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)] + public static extern int ber_scanf_int(SafeBerHandle berElement, string format, ref int value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)] + public static extern int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)] + public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value); +} diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs new file mode 100644 index 0000000000000..02fea9754b9c7 --- /dev/null +++ b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs @@ -0,0 +1,199 @@ +// 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.InteropServices; +using System.DirectoryServices.Protocols; + +namespace System.DirectoryServices.Protocols +{ + /// + /// Structure that will get passed into the Sasl interactive callback in case + /// the authentication process emits challenges to validate information. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct SaslDefaultCredentials + { + public string mech; + public string realm; + public string authcid; + public string passwd; + public string authzid; + } + + /// + /// Structure that will represent a Sasl Interactive challenge during a + /// Sasl interactive bind, which will contain the challenge and it is also + /// where we will have to resolve the result. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + internal class SaslInteractiveChallenge + { + public ulong saslChallengeType; + public string challenge; + public string prompt; + public string defresult; + public IntPtr result; + public uint len; + } + + internal enum SaslChallengeType + { + SASL_CB_LIST_END = 0, + SASL_CB_GETOPT = 1, + SASL_CB_LOG = 2, + SASL_CB_GETPATH = 3, + SASL_CB_VERIFYFILE = 4, + SASL_CB_GETCONFPATH = 5, + SASL_CB_USER = 0x4001, + SASL_CB_AUTHNAME = 0x4002, + SASL_CB_LANGUAGE = 0x4003, + SASL_CB_PASS = 0x4004, + SASL_CB_ECHOPROMPT = 0x4005, + SASL_CB_NOECHOPROMPT = 0x4006, + SASL_CB_CNONCE = 0x4007, + SASL_CB_GETREALM = 0x4008, + SASL_CB_PROXY_POLICY = 0x8001, + } +} + +internal delegate int LDAP_SASL_INTERACT_PROC(IntPtr ld, uint flags, IntPtr defaults, IntPtr interact); + +internal static partial class Interop +{ + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_initialize", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int ldap_initialize(out IntPtr ld, string hostname); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_init", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr ldap_init(string hostName, int portNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_unbind_ext_s", CharSet = CharSet.Ansi)] + public static extern int ldap_unbind_ext_s(IntPtr ld, ref IntPtr serverctrls, ref IntPtr clientctrls); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_dn", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)] + public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)] + public static extern int ldap_get_option_sechandle([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref SecurityHandle outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)] + public static extern int ldap_get_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)] + public static extern int ldap_get_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_values_len", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_get_values_len([In] ConnectionHandle ldapHandle, [In] IntPtr result, string name); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_result", SetLastError = true, CharSet = CharSet.Ansi)] + public static extern int ldap_result([In] ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Mesage); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_result2error", CharSet = CharSet.Ansi)] + public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_search_ext", CharSet = CharSet.Ansi)] + public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)] + public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)] + public static extern int ldap_set_option_servercert([In] ConnectionHandle ldapHandle, [In] LdapOption option, VERIFYSERVERCERT outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int ldap_set_option_int([In] ConnectionHandle ld, [In] LdapOption option, ref int inValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)] + public static extern int ldap_set_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr inValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)] + public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_start_tls_s", CharSet = CharSet.Ansi)] + public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_result", CharSet = CharSet.Ansi)] + public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_result", CharSet = CharSet.Ansi)] + public static extern int ldap_parse_result_referral([In] ConnectionHandle ldapHandle, [In] IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_extended_result", CharSet = CharSet.Ansi)] + public static extern int ldap_parse_extended_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_reference", CharSet = CharSet.Ansi)] + public static extern int ldap_parse_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr referrals, IntPtr ServerControls, byte freeIt); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_sasl_interactive_bind_s", CharSet = CharSet.Ansi)] + internal static extern int ldap_sasl_interactive_bind([In] ConnectionHandle ld, string dn, string mechanism, IntPtr serverctrls, IntPtr clientctrls, uint flags, [MarshalAs(UnmanagedType.FunctionPtr)] LDAP_SASL_INTERACT_PROC proc, IntPtr defaults); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_simple_bind_s", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int ldap_simple_bind([In] ConnectionHandle ld, string who, string passwd); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_bind_s", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int ldap_bind_s([In] ConnectionHandle ld, string who, string passwd, int method); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_err2string", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_err2string(int err); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_extended_operation", CharSet = CharSet.Ansi)] + public static extern int ldap_extended_operation([In] ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_first_attribute", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_first_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr address); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_first_entry", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_first_reference", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_create_sort_control", CharSet = CharSet.Ansi)] + public static extern int ldap_create_sort_control(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_control_free", CharSet = CharSet.Ansi)] + public static extern int ldap_control_free(IntPtr control); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_controls_free", CharSet = CharSet.Ansi)] + public static extern int ldap_controls_free([In] IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_value_free", CharSet = CharSet.Ansi)] + public static extern int ldap_value_free([In] IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_value_free_len([In] IntPtr berelement); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_memfree", CharSet = CharSet.Ansi)] + public static extern void ldap_memfree([In] IntPtr value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_modify_ext", CharSet = CharSet.Ansi)] + public static extern int ldap_modify([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_next_attribute", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_next_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, [In, Out] IntPtr address); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_next_entry", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_next_reference", CharSet = CharSet.Ansi)] + public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_abandon", CharSet = CharSet.Ansi)] + public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_add_ext", CharSet = CharSet.Ansi)] + public static extern int ldap_add([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_delete_ext", CharSet = CharSet.Ansi)] + public static extern int ldap_delete_ext([In] ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_rename", CharSet = CharSet.Ansi)] + public static extern int ldap_rename([In] ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_compare_ext", CharSet = CharSet.Ansi)] + public static extern int ldap_compare([In] ConnectionHandle ldapHandle, string dn, string attributeName, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); +} diff --git a/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs b/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs index abb7baa63a673..f2417e20881bd 100644 --- a/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs +++ b/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs @@ -348,7 +348,7 @@ internal static bool TryFindCGroupPathForSubsystem(CGroupVersion cgroupVersion, // cgroup v2: Find the first entry that matches the cgroup v2 hierarchy: // 0::$PATH - if ((lineParts[0] == "0") && (lineParts[1] == string.Empty)) + if ((lineParts[0] == "0") && (lineParts[1].Length == 0)) { path = lineParts[2]; return true; diff --git a/src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs b/src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs index 84bf6d6398da8..9ba6608df1212 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs @@ -9,13 +9,14 @@ internal static partial class Libraries internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"; internal const string CoreServicesLibrary = "/System/Library/Frameworks/CoreServices.framework/CoreServices"; internal const string CFNetworkLibrary = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork"; - internal const string libproc = "libproc"; + internal const string libobjc = "/usr/lib/libobjc.dylib"; + internal const string libproc = "/usr/lib/libproc.dylib"; internal const string LibSystemCommonCrypto = "/usr/lib/system/libcommonCrypto"; internal const string LibSystemKernel = "/usr/lib/system/libsystem_kernel"; internal const string Odbc32 = "libodbc.2.dylib"; + internal const string OpenLdap = "libldap"; internal const string SystemConfigurationLibrary = "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"; internal const string AppleCryptoNative = "System.Security.Cryptography.Native.Apple"; internal const string MsQuic = "msquic"; - } } diff --git a/src/libraries/Common/src/Interop/OSX/Interop.libobjc.cs b/src/libraries/Common/src/Interop/OSX/Interop.libobjc.cs new file mode 100644 index 0000000000000..d76c59bac334e --- /dev/null +++ b/src/libraries/Common/src/Interop/OSX/Interop.libobjc.cs @@ -0,0 +1,61 @@ +// 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. + +#nullable enable + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class libobjc + { +#if TARGET_ARM64 + private const string MessageSendStructReturnEntryPoint = "objc_msgSend"; +#else + private const string MessageSendStructReturnEntryPoint = "objc_msgSend_stret"; +#endif + + [StructLayout(LayoutKind.Sequential)] + private struct NSOperatingSystemVersion + { + public nint majorVersion; + public nint minorVersion; + public nint patchVersion; + } + + [DllImport(Libraries.libobjc)] + private static extern IntPtr objc_getClass(string className); + [DllImport(Libraries.libobjc)] + private static extern IntPtr sel_getUid(string selector); + [DllImport(Libraries.libobjc)] + private static extern IntPtr objc_msgSend(IntPtr basePtr, IntPtr selector); + + internal static Version GetOperatingSystemVersion() + { + int major = 0; + int minor = 0; + int patch = 0; + + IntPtr processInfo = objc_msgSend(objc_getClass("NSProcessInfo"), sel_getUid("processInfo")); + + if (processInfo != IntPtr.Zero) + { + NSOperatingSystemVersion osVersion = get_operatingSystemVersion(processInfo, sel_getUid("operatingSystemVersion")); + + checked + { + major = (int)osVersion.majorVersion; + minor = (int)osVersion.minorVersion; + patch = (int)osVersion.patchVersion; + } + } + + return new Version(major, minor, patch); + } + + [DllImport(Libraries.libobjc, EntryPoint = MessageSendStructReturnEntryPoint)] + private static extern NSOperatingSystemVersion get_operatingSystemVersion(IntPtr basePtr, IntPtr selector); + } +} diff --git a/src/libraries/Common/src/Interop/Unix/Interop.Errors.cs b/src/libraries/Common/src/Interop/Unix/Interop.Errors.cs index dad796280e71a..e6de6c91723c3 100644 --- a/src/libraries/Common/src/Interop/Unix/Interop.Errors.cs +++ b/src/libraries/Common/src/Interop/Unix/Interop.Errors.cs @@ -182,6 +182,16 @@ internal static unsafe string StrError(int platformErrno) return Marshal.PtrToStringAnsi((IntPtr)message)!; } +#if SERIAL_PORTS + [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_ConvertErrorPlatformToPal")] + internal static extern Error ConvertErrorPlatformToPal(int platformErrno); + + [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_ConvertErrorPalToPlatform")] + internal static extern int ConvertErrorPalToPlatform(Error error); + + [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_StrErrorR")] + private static extern unsafe byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize); +#else [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPlatformToPal")] internal static extern Error ConvertErrorPlatformToPal(int platformErrno); @@ -190,6 +200,7 @@ internal static unsafe string StrError(int platformErrno) [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StrErrorR")] private static extern unsafe byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize); +#endif } } diff --git a/src/libraries/Common/src/Interop/Unix/Interop.Poll.Structs.cs b/src/libraries/Common/src/Interop/Unix/Interop.Poll.Structs.cs new file mode 100644 index 0000000000000..34ca249bcdc95 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/Interop.Poll.Structs.cs @@ -0,0 +1,28 @@ +// 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.InteropServices; + +internal static partial class Interop +{ + [Flags] + internal enum PollEvents : short + { + POLLNONE = 0x0000, // No events occurred. + POLLIN = 0x0001, // non-urgent readable data available + POLLPRI = 0x0002, // urgent readable data available + POLLOUT = 0x0004, // data can be written without blocked + POLLERR = 0x0008, // an error occurred + POLLHUP = 0x0010, // the file descriptor hung up + POLLNVAL = 0x0020, // the requested events were invalid + } + + internal struct PollEvent + { + internal int FileDescriptor; // The file descriptor to poll + internal PollEvents Events; // The events to poll for + internal PollEvents TriggeredEvents; // The events that occurred which triggered the poll + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Poll.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Poll.cs index 549617257de44..895ce720e31a3 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Poll.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Poll.cs @@ -10,25 +10,6 @@ internal static partial class Interop { internal static partial class Sys { - [Flags] - internal enum PollEvents : short - { - POLLNONE = 0x0000, // No events occurred. - POLLIN = 0x0001, // non-urgent readable data available - POLLPRI = 0x0002, // urgent readable data available - POLLOUT = 0x0004, // data can be written without blocked - POLLERR = 0x0008, // an error occurred - POLLHUP = 0x0010, // the file descriptor hung up - POLLNVAL = 0x0020, // the requested events were invalid - } - - internal struct PollEvent - { - internal int FileDescriptor; // The file descriptor to poll - internal PollEvents Events; // The events to poll for - internal PollEvents TriggeredEvents; // The events that occurred which triggered the poll - } - /// /// Polls a set of file descriptors for signals and returns what signals have been set /// diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs new file mode 100644 index 0000000000000..8f3cdbf9db07a --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs @@ -0,0 +1,16 @@ +// 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.Net.Sockets; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Receive")] + internal static extern unsafe Error Receive(SafeHandle socket, byte* buffer, int bufferLen, SocketFlags flags, int* received); + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs new file mode 100644 index 0000000000000..b4a7e1c9bc832 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs @@ -0,0 +1,16 @@ +// 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.Net.Sockets; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Send")] + internal static extern unsafe Error Send(SafeHandle socket, byte* buffer, int bufferLen, SocketFlags flags, int* sent); + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs index c80283f5f218b..b86d5caaeb350 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs @@ -127,12 +127,11 @@ internal static partial class NetSecurityNative ref GssBuffer token); [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_Wrap")] - private static extern Status Wrap( + private static extern unsafe Status Wrap( out Status minorStatus, SafeGssContextHandle? contextHandle, bool isEncrypt, - byte[] inputBytes, - int offset, + byte* inputBytes, int count, ref GssBuffer outBuffer); @@ -145,20 +144,17 @@ internal static partial class NetSecurityNative int count, ref GssBuffer outBuffer); - internal static Status WrapBuffer( + internal static unsafe Status WrapBuffer( out Status minorStatus, SafeGssContextHandle? contextHandle, bool isEncrypt, - byte[] inputBytes, - int offset, - int count, + ReadOnlySpan inputBytes, ref GssBuffer outBuffer) { - Debug.Assert(inputBytes != null, "inputBytes must be valid value"); - Debug.Assert(offset >= 0 && offset <= inputBytes.Length, "offset must be valid"); - Debug.Assert(count >= 0 && count <= (inputBytes.Length - offset), "count must be valid"); - - return Wrap(out minorStatus, contextHandle, isEncrypt, inputBytes, offset, count, ref outBuffer); + fixed (byte* inputBytesPtr = inputBytes) + { + return Wrap(out minorStatus, contextHandle, isEncrypt, inputBytesPtr, inputBytes.Length, ref outBuffer); + } } internal static Status UnwrapBuffer( diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs index bb9da06c11d48..3caac3041f920 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs @@ -16,7 +16,7 @@ internal static partial class Advapi32 { // Note: RegCreateKeyEx won't set the last error on failure - it returns // an error code if it fails. - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW", ExactSpelling = true)] internal static extern int RegCreateKeyEx( SafeRegistryHandle hKey, string lpSubKey, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs index 487caf8b6d79d..2fff3b1ed5164 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs @@ -13,7 +13,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteKeyExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteKeyExW", ExactSpelling = true)] internal static extern int RegDeleteKeyEx(SafeRegistryHandle hKey, string lpSubKey, int samDesired, int Reserved); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs index 43cf683c2bddf..7bb376930fa75 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs @@ -14,7 +14,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW", ExactSpelling = true)] internal static extern int RegDeleteValue(SafeRegistryHandle hKey, string? lpValueName); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs index 11165cc91a966..d618b50cd1cd8 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs @@ -14,7 +14,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW", ExactSpelling = true)] internal static extern unsafe int RegEnumKeyEx( SafeRegistryHandle hKey, int dwIndex, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumValue.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumValue.cs index e2ab45dea1933..02a7ad9692844 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumValue.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegEnumValue.cs @@ -15,7 +15,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW", ExactSpelling = true)] internal static extern unsafe int RegEnumValue( SafeRegistryHandle hKey, int dwIndex, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs index 5f5b6b6e372ed..0bc2cdce3c836 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs @@ -15,7 +15,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW", ExactSpelling = true)] internal static extern int RegOpenKeyEx( SafeRegistryHandle hKey, string? lpSubKey, @@ -24,7 +24,7 @@ internal static partial class Advapi32 out SafeRegistryHandle hkResult); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW", ExactSpelling = true)] internal static extern int RegOpenKeyEx( IntPtr hKey, string? lpSubKey, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs index 72b8aa8f7bcf1..bde703ad18632 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs @@ -14,7 +14,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -23,7 +23,7 @@ internal static partial class Advapi32 [Out] byte[]? lpData, ref int lpcbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -32,7 +32,7 @@ internal static partial class Advapi32 ref int lpData, ref int lpcbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -41,7 +41,7 @@ internal static partial class Advapi32 ref long lpData, ref int lpcbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, string? lpValueName, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs index 847d28fa1c577..72cee21e1a17b 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs @@ -14,7 +14,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -23,7 +23,7 @@ internal static partial class Advapi32 byte[]? lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -32,7 +32,7 @@ internal static partial class Advapi32 char[]? lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -41,7 +41,7 @@ internal static partial class Advapi32 ref int lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, string? lpValueName, @@ -50,7 +50,7 @@ internal static partial class Advapi32 ref long lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] + [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, string? lpValueName, diff --git a/src/libraries/Common/src/Interop/Windows/Interop.Libraries.cs b/src/libraries/Common/src/Interop/Windows/Interop.Libraries.cs index 1c1b3db6a0b76..2672c4cc489e5 100644 --- a/src/libraries/Common/src/Interop/Windows/Interop.Libraries.cs +++ b/src/libraries/Common/src/Interop/Windows/Interop.Libraries.cs @@ -34,6 +34,7 @@ internal static partial class Libraries internal const string WebSocket = "websocket.dll"; internal const string WinHttp = "winhttp.dll"; internal const string WinMM = "winmm.dll"; + internal const string Wldap32 = "wldap32.dll"; internal const string Ws2_32 = "ws2_32.dll"; internal const string Wtsapi32 = "wtsapi32.dll"; internal const string CompressionNative = "clrcompression.dll"; diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs index c3adfadb53d54..e4b0904b76ba1 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs @@ -20,10 +20,10 @@ internal static partial class Kernel32 [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool ResetEvent(SafeWaitHandle handle); - [DllImport(Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern SafeWaitHandle CreateEventEx(IntPtr lpSecurityAttributes, string? name, uint flags, uint desiredAccess); - [DllImport(Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern SafeWaitHandle OpenEvent(uint desiredAccess, bool inheritHandle, string name); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs index fbd5da84b8e0a..94a3714644e12 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "ExpandEnvironmentStringsW", CharSet = CharSet.Unicode, SetLastError = true)] + [DllImport(Libraries.Kernel32, EntryPoint = "ExpandEnvironmentStringsW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] internal static extern uint ExpandEnvironmentStrings(string lpSrc, ref char lpDst, uint nSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs index 6ab52b4d0e9e2..a7cd35262d50d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs @@ -15,7 +15,7 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use FindFirstFile. /// - [DllImport(Libraries.Kernel32, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] private static extern SafeFindHandle FindFirstFileExPrivate(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, ref WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags); internal static SafeFindHandle FindFirstFile(string fileName, ref WIN32_FIND_DATA data) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs index 2eda58f250426..14ba39b044b9f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs @@ -16,7 +16,7 @@ internal static partial class Kernel32 private const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; private const int ERROR_INSUFFICIENT_BUFFER = 0x7A; - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true)] + [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true, ExactSpelling = true)] private static extern unsafe int FormatMessage( int dwFlags, IntPtr lpSource, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs index c222db8ef91b5..f325c281df8cf 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "FreeEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, EntryPoint = "FreeEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] internal static extern unsafe bool FreeEnvironmentStrings(char* lpszEnvironmentBlock); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs index 011430da5c7e8..92cfb955a4cba 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs @@ -10,7 +10,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetComputerNameW")] + [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetComputerNameW", ExactSpelling = true)] private static extern unsafe int GetComputerName(ref char lpBuffer, ref uint nSize); // maximum length of the NETBIOS name (not including NULL) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs index 4e30a8be4328a..bf283df9c4046 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "GetCurrentDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, EntryPoint = "GetCurrentDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] internal static extern uint GetCurrentDirectory(uint nBufferLength, ref char lpBuffer); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs index 5594fe7a4cb8e..cdbd01ca50208 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] internal static extern unsafe char* GetEnvironmentStrings(); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs index 43463e52304cb..0c14b3dd40398 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs @@ -17,7 +17,7 @@ internal static unsafe int GetEnvironmentVariable(string lpName, Span buff } } - [DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] private static extern unsafe int GetEnvironmentVariable(string lpName, char* lpBuffer, int nSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs index aed8919cd03e9..84cd7326b39fe 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs @@ -13,7 +13,7 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use GetFileAttributesEx. /// - [DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] private static extern bool GetFileAttributesExPrivate(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); internal static bool GetFileAttributesEx(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs index 197f6f5eadcdb..b247a509c40d8 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] internal static extern uint GetSystemDirectoryW(ref char lpBuffer, uint uSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs index d7f9b828c0c03..5c3140b82ea66 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, ExactSpelling = true)] internal static extern uint GetTempFileNameW(ref char lpPathName, string lpPrefixString, uint uUnique, ref char lpTempFileName); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempPathW.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempPathW.cs index 8d2b0b199edd0..654a3b57011cd 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempPathW.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetTempPathW.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] internal static extern uint GetTempPathW(int bufferLen, ref char buffer); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs index a77cf49179382..3e3d1d34a81a7 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs @@ -12,7 +12,7 @@ internal static partial class Kernel32 internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002; internal const int LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800; - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "LoadLibraryExW", SetLastError = true)] + [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "LoadLibraryExW", SetLastError = true, ExactSpelling = true)] internal static extern IntPtr LoadLibraryEx(string libFilename, IntPtr reserved, int flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Mutex.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Mutex.cs index 6adaf98737040..ad1d649fe9da8 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Mutex.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Mutex.cs @@ -13,10 +13,10 @@ internal static partial class Kernel32 { internal const uint CREATE_MUTEX_INITIAL_OWNER = 0x1; - [DllImport(Libraries.Kernel32, EntryPoint = "OpenMutexW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "OpenMutexW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern SafeWaitHandle OpenMutex(uint desiredAccess, bool inheritHandle, string name); - [DllImport(Libraries.Kernel32, EntryPoint = "CreateMutexExW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "CreateMutexExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern SafeWaitHandle CreateMutexEx(IntPtr lpMutexAttributes, string? name, uint flags, uint desiredAccess); [DllImport(Libraries.Kernel32, SetLastError = true)] diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Semaphore.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Semaphore.cs index 4f6d8de8768a3..c83db1f934c00 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Semaphore.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Semaphore.cs @@ -11,10 +11,10 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "OpenSemaphoreW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "OpenSemaphoreW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern SafeWaitHandle OpenSemaphore(uint desiredAccess, bool inheritHandle, string name); - [DllImport(Libraries.Kernel32, EntryPoint = "CreateSemaphoreExW", SetLastError = true, CharSet = CharSet.Unicode)] + [DllImport(Libraries.Kernel32, EntryPoint = "CreateSemaphoreExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSecurityAttributes, int initialCount, int maximumCount, string? name, uint flags, uint desiredAccess); [DllImport(Libraries.Kernel32, SetLastError = true)] diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs index d268d4daa6f77..17360399a7c0d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "SetCurrentDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, EntryPoint = "SetCurrentDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] internal static extern bool SetCurrentDirectory(string path); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs index 243bd6562e034..ab3a6d34cd42b 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "SetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] + [DllImport(Libraries.Kernel32, EntryPoint = "SetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] internal static extern bool SetEnvironmentVariable(string lpName, string? lpValue); } } diff --git a/src/libraries/Common/src/Interop/Windows/Secur32/Interop.GetUserNameExW.cs b/src/libraries/Common/src/Interop/Windows/Secur32/Interop.GetUserNameExW.cs index e88864cd9e747..7001cd6df09ea 100644 --- a/src/libraries/Common/src/Interop/Windows/Secur32/Interop.GetUserNameExW.cs +++ b/src/libraries/Common/src/Interop/Windows/Secur32/Interop.GetUserNameExW.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Secur32 { - [DllImport(Libraries.Secur32, CharSet = CharSet.Unicode, SetLastError = true)] + [DllImport(Libraries.Secur32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] internal static extern BOOLEAN GetUserNameExW(int NameFormat, ref char lpNameBuffer, ref uint lpnSize); internal const int NameSamCompatible = 2; diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadString.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadString.cs index 6ff50442eb428..8824f7c3dfa02 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadString.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadString.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class User32 { - [DllImport(Libraries.User32, SetLastError = true, EntryPoint = "LoadStringW", CharSet = CharSet.Unicode)] + [DllImport(Libraries.User32, SetLastError = true, EntryPoint = "LoadStringW", CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern unsafe int LoadString(IntPtr hInstance, uint uID, char* lpBuffer, int cchBufferMax); } } diff --git a/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs new file mode 100644 index 0000000000000..5f87ea57938b0 --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs @@ -0,0 +1,52 @@ +// 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.DirectoryServices.Protocols; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_free", CharSet = CharSet.Unicode)] + public static extern IntPtr ber_free([In] IntPtr berelement, int option); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_alloc_t", CharSet = CharSet.Unicode)] + public static extern IntPtr ber_alloc(int option); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] + public static extern int ber_printf_emptyarg(SafeBerHandle berElement, string format); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] + public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] + public static extern int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] + public static extern int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)] + public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_init", CharSet = CharSet.Unicode)] + public static extern IntPtr ber_init(berval value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] + public static extern int ber_scanf(SafeBerHandle berElement, string format); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] + public static extern int ber_scanf_int(SafeBerHandle berElement, string format, ref int value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] + public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] + public static extern int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)] + public static extern int ber_bvfree(IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvecfree", CharSet = CharSet.Unicode)] + public static extern int ber_bvecfree(IntPtr value); +} diff --git a/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ldap.cs new file mode 100644 index 0000000000000..a73cd89996e2d --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ldap.cs @@ -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. + +using System; +using System.DirectoryServices.Protocols; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_bind_sW", CharSet = CharSet.Unicode)] + public static extern int ldap_bind_s([In]ConnectionHandle ldapHandle, string dn, SEC_WINNT_AUTH_IDENTITY_EX credentials, BindMethod method); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_initW", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_init(string hostName, int portNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_connect", CharSet = CharSet.Unicode)] + public static extern int ldap_connect([In] ConnectionHandle ldapHandle, LDAP_TIMEVAL timeout); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_unbind", CharSet = CharSet.Unicode)] + public static extern int ldap_unbind([In] IntPtr ldapHandle); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_get_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_set_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int inValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_get_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_set_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr inValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_get_option_sechandle([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref SecurityHandle outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] + public static extern int ldap_set_option_servercert([In] ConnectionHandle ldapHandle, [In] LdapOption option, VERIFYSERVERCERT outValue); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LdapGetLastError")] + public static extern int LdapGetLastError(); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "cldap_openW", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr cldap_open(string hostName, int portNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_simple_bind_sW", CharSet = CharSet.Unicode)] + public static extern int ldap_simple_bind_s([In] ConnectionHandle ldapHandle, string distinguishedName, string password); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_delete_extW", CharSet = CharSet.Unicode)] + public static extern int ldap_delete_ext([In] ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern int ldap_result([In] ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Mesage); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)] + public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)] + public static extern int ldap_parse_result_referral([In] ConnectionHandle ldapHandle, [In] IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_memfreeW", CharSet = CharSet.Unicode)] + public static extern void ldap_memfree([In] IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_freeW", CharSet = CharSet.Unicode)] + public static extern int ldap_value_free([In] IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_controls_freeW", CharSet = CharSet.Unicode)] + public static extern int ldap_controls_free([In] IntPtr value); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_abandon", CharSet = CharSet.Unicode)] + public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_start_tls_sW", CharSet = CharSet.Unicode)] + public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_stop_tls_s", CharSet = CharSet.Unicode)] + public static extern byte ldap_stop_tls(ConnectionHandle ldapHandle); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_rename_extW", CharSet = CharSet.Unicode)] + public static extern int ldap_rename([In] ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_compare_extW", CharSet = CharSet.Unicode)] + public static extern int ldap_compare([In] ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_add_extW", CharSet = CharSet.Unicode)] + public static extern int ldap_add([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_modify_extW", CharSet = CharSet.Unicode)] + public static extern int ldap_modify([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_extended_operationW", CharSet = CharSet.Unicode)] + public static extern int ldap_extended_operation([In] ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_extended_resultW", CharSet = CharSet.Unicode)] + public static extern int ldap_parse_extended_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_msgfree", CharSet = CharSet.Unicode)] + public static extern int ldap_msgfree([In] IntPtr result); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_search_extW", CharSet = CharSet.Unicode)] + public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_entry", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_entry", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_reference", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_reference", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_dnW", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_attributeW", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_first_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr address); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_attributeW", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_next_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, [In, Out] IntPtr address); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_values_lenW", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_get_values_len([In] ConnectionHandle ldapHandle, [In] IntPtr result, string name); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Unicode)] + public static extern IntPtr ldap_value_free_len([In] IntPtr berelement); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_referenceW", CharSet = CharSet.Unicode)] + public static extern int ldap_parse_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr referrals); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_create_sort_controlW", CharSet = CharSet.Unicode)] + public static extern int ldap_create_sort_control(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_control_freeW", CharSet = CharSet.Unicode)] + public static extern int ldap_control_free(IntPtr control); + + [DllImport("Crypt32.dll", EntryPoint = "CertFreeCRLContext", CharSet = CharSet.Unicode)] + public static extern int CertFreeCRLContext(IntPtr certContext); + + [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result2error", CharSet = CharSet.Unicode)] + public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt); +} diff --git a/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs b/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs index 71b23e1f7cd3f..a7b047119d5d5 100644 --- a/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs +++ b/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs @@ -42,7 +42,7 @@ public ArrayBufferWriter() public ArrayBufferWriter(int initialCapacity) { if (initialCapacity <= 0) - throw new ArgumentException(nameof(initialCapacity)); + throw new ArgumentException(null, nameof(initialCapacity)); _buffer = new T[initialCapacity]; _index = 0; @@ -101,7 +101,7 @@ public void Clear() public void Advance(int count) { if (count < 0) - throw new ArgumentException(nameof(count)); + throw new ArgumentException(null, nameof(count)); if (_index > _buffer.Length - count) ThrowInvalidOperationException_AdvancedTooFar(_buffer.Length); diff --git a/src/libraries/Common/src/System/Collections/Generic/BidirectionalDictionary.cs b/src/libraries/Common/src/System/Collections/Generic/BidirectionalDictionary.cs index 6b5923d8f46dc..5e3dec7e8268d 100644 --- a/src/libraries/Common/src/System/Collections/Generic/BidirectionalDictionary.cs +++ b/src/libraries/Common/src/System/Collections/Generic/BidirectionalDictionary.cs @@ -4,6 +4,7 @@ #nullable enable using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Collections.Generic { @@ -36,12 +37,12 @@ public void Add(T1 item1, T2 item2) _backward.Add(item2, item1); } - public bool TryGetForward(T1 item1, out T2 item2) + public bool TryGetForward(T1 item1, [MaybeNullWhen(false)] out T2 item2) { return _forward.TryGetValue(item1, out item2); } - public bool TryGetBackward(T2 item2, out T1 item1) + public bool TryGetBackward(T2 item2, [MaybeNullWhen(false)] out T1 item1) { return _backward.TryGetValue(item2, out item1); } diff --git a/src/libraries/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs b/src/libraries/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs index 38c3a40d64884..eed8ccb978a81 100644 --- a/src/libraries/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs +++ b/src/libraries/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs @@ -33,7 +33,6 @@ private void Trace() ~DebugCriticalHandleMinusOneIsInvalid() { - DebugThreadTracking.SetThreadSource(ThreadKinds.Finalization); if (NetEventSource.IsEnabled) NetEventSource.Info(this, _trace); } } diff --git a/src/libraries/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs b/src/libraries/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs index 33bca4dee3f70..0d993cd60d738 100644 --- a/src/libraries/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs +++ b/src/libraries/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs @@ -33,7 +33,6 @@ private void Trace() ~DebugCriticalHandleZeroOrMinusOneIsInvalid() { - DebugThreadTracking.SetThreadSource(ThreadKinds.Finalization); if (NetEventSource.IsEnabled) NetEventSource.Info(this, _trace); } } diff --git a/src/libraries/Common/src/System/Net/DebugSafeHandleMinusOneIsInvalid.cs b/src/libraries/Common/src/System/Net/DebugSafeHandleMinusOneIsInvalid.cs index 5cf3352115cdd..4fd2c5b4e9850 100644 --- a/src/libraries/Common/src/System/Net/DebugSafeHandleMinusOneIsInvalid.cs +++ b/src/libraries/Common/src/System/Net/DebugSafeHandleMinusOneIsInvalid.cs @@ -33,7 +33,6 @@ private void Trace() ~DebugSafeHandleMinusOneIsInvalid() { - DebugThreadTracking.SetThreadSource(ThreadKinds.Finalization); if (NetEventSource.IsEnabled) NetEventSource.Info(this, _trace); } } diff --git a/src/libraries/Common/src/System/Net/Http/aspnetcore/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs index 0b9893333d715..dd42af8ff6142 100644 --- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs +++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs @@ -142,8 +142,6 @@ static MsQuicApi() // - Otherwise, dial this in to reflect actual minimum requirements and add some sort of platform // error code mapping when creating exceptions. - OperatingSystem ver = Environment.OSVersion; - // TODO: try to initialize TLS 1.3 in SslStream. try diff --git a/src/libraries/Common/src/System/Net/Logging/DebugThreadTracking.cs b/src/libraries/Common/src/System/Net/Logging/DebugThreadTracking.cs deleted file mode 100644 index eba97da8e3b20..0000000000000 --- a/src/libraries/Common/src/System/Net/Logging/DebugThreadTracking.cs +++ /dev/null @@ -1,158 +0,0 @@ -// 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. - -#nullable enable -using System.Collections.Generic; - -namespace System.Net -{ - internal static class DebugThreadTracking - { - [ThreadStatic] - private static Stack? t_threadKindStack; - - private static Stack ThreadKindStack => t_threadKindStack ?? (t_threadKindStack = new Stack()); - - internal static ThreadKinds CurrentThreadKind => ThreadKindStack.Count > 0 ? ThreadKindStack.Peek() : ThreadKinds.Other; - - internal static IDisposable? SetThreadKind(ThreadKinds kind) - { - if ((kind & ThreadKinds.SourceMask) != ThreadKinds.Unknown) - { - throw new InternalException(kind); - } - - // Ignore during shutdown. - if (Environment.HasShutdownStarted) - { - return null; - } - - ThreadKinds threadKind = CurrentThreadKind; - ThreadKinds source = threadKind & ThreadKinds.SourceMask; - - // Special warnings when doing dangerous things on a thread. - if ((threadKind & ThreadKinds.User) != 0 && (kind & ThreadKinds.System) != 0) - { - if (NetEventSource.IsEnabled) NetEventSource.Error(null, "Thread changed from User to System; user's thread shouldn't be hijacked."); - } - - if ((threadKind & ThreadKinds.Async) != 0 && (kind & ThreadKinds.Sync) != 0) - { - if (NetEventSource.IsEnabled) NetEventSource.Error(null, "Thread changed from Async to Sync, may block an Async thread."); - } - else if ((threadKind & (ThreadKinds.Other | ThreadKinds.CompletionPort)) == 0 && (kind & ThreadKinds.Sync) != 0) - { - if (NetEventSource.IsEnabled) NetEventSource.Error(null, "Thread from a limited resource changed to Sync, may deadlock or bottleneck."); - } - - ThreadKindStack.Push( - (((kind & ThreadKinds.OwnerMask) == 0 ? threadKind : kind) & ThreadKinds.OwnerMask) | - (((kind & ThreadKinds.SyncMask) == 0 ? threadKind : kind) & ThreadKinds.SyncMask) | - (kind & ~(ThreadKinds.OwnerMask | ThreadKinds.SyncMask)) | - source); - - if (CurrentThreadKind != threadKind) - { - if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Thread becomes:({CurrentThreadKind})"); - } - - return new ThreadKindFrame(); - } - - private class ThreadKindFrame : IDisposable - { - private readonly int _frameNumber; - - internal ThreadKindFrame() - { - _frameNumber = ThreadKindStack.Count; - } - - void IDisposable.Dispose() - { - // Ignore during shutdown. - if (Environment.HasShutdownStarted) - { - return; - } - - if (_frameNumber != ThreadKindStack.Count) - { - throw new InternalException(_frameNumber); - } - - ThreadKinds previous = ThreadKindStack.Pop(); - - if (CurrentThreadKind != previous && NetEventSource.IsEnabled) - { - if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Thread reverts:({CurrentThreadKind})"); - } - } - } - - internal static void SetThreadSource(ThreadKinds source) - { - if ((source & ThreadKinds.SourceMask) != source || source == ThreadKinds.Unknown) - { - throw new ArgumentException("Must specify the thread source.", nameof(source)); - } - - if (ThreadKindStack.Count == 0) - { - ThreadKindStack.Push(source); - return; - } - - if (ThreadKindStack.Count > 1) - { - if (NetEventSource.IsEnabled) NetEventSource.Error(null, "SetThreadSource must be called at the base of the stack, or the stack has been corrupted."); - while (ThreadKindStack.Count > 1) - { - ThreadKindStack.Pop(); - } - } - - if (ThreadKindStack.Peek() != source) - { - if (NetEventSource.IsEnabled) NetEventSource.Error(null, "The stack has been corrupted."); - ThreadKinds last = ThreadKindStack.Pop() & ThreadKinds.SourceMask; - if (last != source && last != ThreadKinds.Other && NetEventSource.IsEnabled) - { - NetEventSource.Fail(null, $"Thread source changed.|Was:({last}) Now:({source})"); - } - ThreadKindStack.Push(source); - } - } - } - - [Flags] - internal enum ThreadKinds - { - Unknown = 0x0000, - - // Mutually exclusive. - User = 0x0001, // Thread has entered via an API. - System = 0x0002, // Thread has entered via a system callback (e.g. completion port) or is our own thread. - - // Mutually exclusive. - Sync = 0x0004, // Thread should block. - Async = 0x0008, // Thread should not block. - - // Mutually exclusive, not always known for a user thread. Never changes. - Timer = 0x0010, // Thread is the timer thread. (Can't call user code.) - CompletionPort = 0x0020, // Thread is a ThreadPool completion-port thread. - Worker = 0x0040, // Thread is a ThreadPool worker thread. - Finalization = 0x0080, // Thread is the finalization thread. - Other = 0x0100, // Unknown source. - - OwnerMask = User | System, - SyncMask = Sync | Async, - SourceMask = Timer | CompletionPort | Worker | Finalization | Other, - - // Useful "macros" - SafeSources = SourceMask & ~(Timer | Finalization), // Methods that "unsafe" sources can call must be explicitly marked. - ThreadPool = CompletionPort | Worker, // Like Thread.CurrentThread.IsThreadPoolThread - } -} diff --git a/src/libraries/Common/src/System/Net/Mail/MailBnfHelper.cs b/src/libraries/Common/src/System/Net/Mail/MailBnfHelper.cs index 5f72eaf1bafa1..494eaea415eb2 100644 --- a/src/libraries/Common/src/System/Net/Mail/MailBnfHelper.cs +++ b/src/libraries/Common/src/System/Net/Mail/MailBnfHelper.cs @@ -45,8 +45,6 @@ internal static class MailBnfHelper internal const char Comma = ','; internal const char Dot = '.'; - private static readonly char[] s_colonSeparator = new char[] { ':' }; - // NOTE: See RFC 2822 for more detail. By default, every value in the array is false and only // those values which are allowed in that particular set are then set to true. The numbers // annotating each definition below are the range of ASCII values which are allowed in that definition. @@ -317,7 +315,7 @@ internal static string ReadToken(string data, ref int offset, StringBuilder? bui localBuilder.Append(' '); } - string[] offsetFields = offset.Split(s_colonSeparator); + string[] offsetFields = offset.Split(':'); localBuilder.Append(offsetFields[0]); localBuilder.Append(offsetFields[1]); return (builder != null ? null : localBuilder.ToString()); diff --git a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs index 157986f7bf649..a4d3143a83cfa 100644 --- a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs +++ b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs @@ -19,7 +19,8 @@ internal static class UnixCommandLinePing private static readonly string? s_discoveredPing4UtilityPath = GetPingUtilityPath(ipv4: true); private static readonly string? s_discoveredPing6UtilityPath = GetPingUtilityPath(ipv4: false); - private static readonly bool s_isBSD = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD")); + private static readonly bool s_isOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + private static readonly bool s_isBSD = RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); private static readonly Lazy s_isBusybox = new Lazy(() => IsBusyboxPing(s_discoveredPing4UtilityPath)); // We don't want to pick up an arbitrary or malicious ping @@ -72,14 +73,59 @@ public enum PingFragmentOptions { Default, Do, Dont }; /// Constructs command line arguments appropriate for the ping or ping6 utility. /// /// The packet size to use in the ping. Exact packet payload cannot be specified. + /// The timeout to use in the ping, in milliseconds. /// A string representation of the IP address to ping. /// The constructed command line arguments, which can be passed to ping or ping6. - public static string ConstructCommandLine(int packetSize, string address, bool ipv4, int ttl = 0, PingFragmentOptions fragmentOption = PingFragmentOptions.Default) + public static string ConstructCommandLine(int packetSize, int timeout, string address, bool ipv4, int ttl = 0, PingFragmentOptions fragmentOption = PingFragmentOptions.Default) { - - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.Append("-c 1"); // Just send a single ping ("count = 1") + //if timeout is zero then some ping implementations can stuck infinitely if endpoint is unreachable + if (timeout == 0) + timeout = 1; + + // Pass timeout argument to ping utility + // BusyBox, Linux: ping and ping6 requires -W flag which accepts timeout in SECONDS. + // FreeBSD: ping requires -W flag which accepts timeout in MILLISECONDS; + // ping6 requires -x which accepts timeout in MILLISECONDS + // OSX: ping requires -W flag which accepts timeout in MILLISECONDS; ping6 doesn't support timeout + if (s_isBSD) + { + if (ipv4) + { + sb.Append(" -W "); + } + else + { + sb.Append(" -x "); + } + } + else if (s_isOSX) + { + if (ipv4) + { + sb.Append(" -W "); + } + else + { + goto skipped_timeout; + } + } + else + { + sb.Append(" -W "); + const int millisInSecond = 1000; + timeout = Math.DivRem(timeout, millisInSecond, out int remainder); + if (remainder != 0) + { + timeout += 1; + } + } + sb.Append(timeout); + + skipped_timeout: + // The command-line flags for "Do-not-fragment" and "TTL" are not standard. // In fact, they are different even between ping and ping6 on the same machine. @@ -88,7 +134,7 @@ public static string ConstructCommandLine(int packetSize, string address, bool i if (ttl > 0) { - if (s_isBSD) + if (s_isBSD | s_isOSX) { // OSX and FreeBSD use -h to set hop limit for IPv6 and -m ttl for IPv4 if (ipv4) @@ -109,9 +155,9 @@ public static string ConstructCommandLine(int packetSize, string address, bool i sb.Append(ttl); } - if (fragmentOption != PingFragmentOptions.Default ) + if (fragmentOption != PingFragmentOptions.Default) { - if (s_isBSD) + if (s_isBSD | s_isOSX) { // The bit is off by default on OSX & FreeBSD if (fragmentOption == PingFragmentOptions.Dont) { diff --git a/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs b/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs index 21edf85650544..8ba6978f874b7 100644 --- a/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs +++ b/src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs @@ -43,19 +43,13 @@ internal static string QueryContextAuthenticationPackage(SafeDeleteContext secur private static byte[] GssWrap( SafeGssContextHandle? context, bool encrypt, - byte[] buffer, - int offset, - int count) + ReadOnlySpan buffer) { - Debug.Assert((buffer != null) && (buffer.Length > 0), "Invalid input buffer passed to Encrypt"); - Debug.Assert((offset >= 0) && (offset < buffer.Length), "Invalid input offset passed to Encrypt"); - Debug.Assert((count >= 0) && (count <= (buffer.Length - offset)), "Invalid input count passed to Encrypt"); - - Interop.NetSecurityNative.GssBuffer encryptedBuffer = default(Interop.NetSecurityNative.GssBuffer); + Interop.NetSecurityNative.GssBuffer encryptedBuffer = default; try { Interop.NetSecurityNative.Status minorStatus; - Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.WrapBuffer(out minorStatus, context, encrypt, buffer, offset, count, ref encryptedBuffer); + Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.WrapBuffer(out minorStatus, context, encrypt, buffer, ref encryptedBuffer); if (status != Interop.NetSecurityNative.Status.GSS_S_COMPLETE) { throw new Interop.NetSecurityNative.GssApiException(status, minorStatus); @@ -555,16 +549,14 @@ internal static SafeFreeCredentials AcquireCredentialsHandle(string package, boo internal static int Encrypt( SafeDeleteContext securityContext, - byte[] buffer, - int offset, - int count, + ReadOnlySpan buffer, bool isConfidential, bool isNtlm, - ref byte[]? output, + [NotNull] ref byte[]? output, uint sequenceNumber) { SafeDeleteNegoContext gssContext = (SafeDeleteNegoContext) securityContext; - byte[] tempOutput = GssWrap(gssContext.GssContext, isConfidential, buffer, offset, count); + byte[] tempOutput = GssWrap(gssContext.GssContext, isConfidential, buffer); // Create space for prefixing with the length const int prefixLength = 4; @@ -628,7 +620,7 @@ internal static int VerifySignature(SafeDeleteContext securityContext, byte[] bu internal static int MakeSignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count, [AllowNull] ref byte[] output) { SafeDeleteNegoContext gssContext = (SafeDeleteNegoContext)securityContext; - byte[] tempOutput = GssWrap(gssContext.GssContext, false, buffer, offset, count); + byte[] tempOutput = GssWrap(gssContext.GssContext, false, new ReadOnlySpan(buffer, offset, count)); // Create space for prefixing with the length const int prefixLength = 4; output = new byte[tempOutput.Length + prefixLength]; diff --git a/src/libraries/Common/src/System/Runtime/Serialization/SerializationGuard.cs b/src/libraries/Common/src/System/Runtime/Serialization/SerializationGuard.cs index 3fa5f3f49c3c2..35614ed285774 100644 --- a/src/libraries/Common/src/System/Runtime/Serialization/SerializationGuard.cs +++ b/src/libraries/Common/src/System/Runtime/Serialization/SerializationGuard.cs @@ -26,7 +26,7 @@ internal static partial class SerializationGuard if (throwMethod != null) { - throwIfDeserializationInProgressDelegate = (ThrowIfDeserializationInProgressWithSwitchDel)throwMethod.CreateDelegate(typeof(ThrowIfDeserializationInProgressWithSwitchDel)); + throwIfDeserializationInProgressDelegate = throwMethod.CreateDelegate(); } return throwIfDeserializationInProgressDelegate; diff --git a/src/libraries/Common/src/System/SR.cs b/src/libraries/Common/src/System/SR.cs index 357492065e502..69a233ed668e3 100644 --- a/src/libraries/Common/src/System/SR.cs +++ b/src/libraries/Common/src/System/SR.cs @@ -29,7 +29,12 @@ internal static string GetResourceString(string resourceKey, string? defaultStri string? resourceString = null; try { - resourceString = ResourceManager.GetString(resourceKey); + resourceString = +#if SYSTEM_PRIVATE_CORELIB + InternalGetResourceString(resourceKey); +#else + ResourceManager.GetString(resourceKey); +#endif } catch (MissingManifestResourceException) { } diff --git a/src/libraries/Common/src/System/Text/StringBuilderCache.cs b/src/libraries/Common/src/System/Text/StringBuilderCache.cs index aac2c2e8a9a07..4d96cb301e9e1 100644 --- a/src/libraries/Common/src/System/Text/StringBuilderCache.cs +++ b/src/libraries/Common/src/System/Text/StringBuilderCache.cs @@ -11,7 +11,7 @@ internal static class StringBuilderCache // The value 360 was chosen in discussion with performance experts as a compromise between using // as litle memory per thread as possible and still covering a large part of short-lived // StringBuilder creations on the startup path of VS designers. - private const int MaxBuilderSize = 360; + internal const int MaxBuilderSize = 360; private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity // WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance). diff --git a/src/libraries/Common/src/System/Threading/Tasks/TaskToApm.cs b/src/libraries/Common/src/System/Threading/Tasks/TaskToApm.cs index ecd9f27ecb8dd..7be4563cddecd 100644 --- a/src/libraries/Common/src/System/Threading/Tasks/TaskToApm.cs +++ b/src/libraries/Common/src/System/Threading/Tasks/TaskToApm.cs @@ -14,6 +14,7 @@ #nullable enable using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Threading.Tasks { @@ -43,7 +44,7 @@ public static void End(IAsyncResult asyncResult) return; } - throw new ArgumentNullException(); + ThrowArgumentException(asyncResult); } /// Processes an IAsyncResult returned by Begin. @@ -55,9 +56,17 @@ public static TResult End(IAsyncResult asyncResult) return task.GetAwaiter().GetResult(); } - throw new ArgumentNullException(); + ThrowArgumentException(asyncResult); + return default!; // unreachable } + /// Throws an argument exception for the invalid . + [DoesNotReturn] + private static void ThrowArgumentException(IAsyncResult asyncResult) => + throw (asyncResult is null ? + new ArgumentNullException(nameof(asyncResult)) : + new ArgumentException(null, nameof(asyncResult))); + /// Provides a simple IAsyncResult that wraps a Task. /// /// We could use the Task as the IAsyncResult if the Task's AsyncState is the same as the object state, diff --git a/src/mono/msbuild/AndroidTestRunner/AndroidTestRunner.cs b/src/libraries/Common/tests/AndroidTestRunner/AndroidTestRunner.cs similarity index 87% rename from src/mono/msbuild/AndroidTestRunner/AndroidTestRunner.cs rename to src/libraries/Common/tests/AndroidTestRunner/AndroidTestRunner.cs index c223eba130cc7..9f232f549ba92 100644 --- a/src/mono/msbuild/AndroidTestRunner/AndroidTestRunner.cs +++ b/src/libraries/Common/tests/AndroidTestRunner/AndroidTestRunner.cs @@ -1,3 +1,7 @@ +// 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.Linq; using System.Text; @@ -24,11 +28,18 @@ public static async Task Main(string[] args) Console.WriteLine($"Test libs were not found (*.Tests.dll was not found in {Environment.CurrentDirectory})"); return -1; } + int exitCode = 0; s_MainTestName = Path.GetFileNameWithoutExtension(s_testLibs[0]); var simpleTestRunner = new SimpleAndroidTestRunner(true); + simpleTestRunner.TestsCompleted += (e, result) => + { + if (result.FailedTests > 0) + exitCode = 1; + }; + await simpleTestRunner.RunAsync(); Console.WriteLine("----- Done -----"); - return 0; + return exitCode; } public SimpleAndroidTestRunner(bool verbose) diff --git a/src/libraries/Common/tests/AndroidTestRunner/AndroidTestRunner.csproj b/src/libraries/Common/tests/AndroidTestRunner/AndroidTestRunner.csproj new file mode 100644 index 0000000000000..6f73d8ec7cefb --- /dev/null +++ b/src/libraries/Common/tests/AndroidTestRunner/AndroidTestRunner.csproj @@ -0,0 +1,11 @@ + + + Exe + enable + $(NetCoreAppCurrent) + + + + + + diff --git a/src/mono/msbuild/AppleTestRunner/AppleTestRunner.cs b/src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.cs similarity index 95% rename from src/mono/msbuild/AppleTestRunner/AppleTestRunner.cs rename to src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.cs index 9fa35b6cc15fa..22979b7d4cf37 100644 --- a/src/mono/msbuild/AppleTestRunner/AppleTestRunner.cs +++ b/src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.cs @@ -1,3 +1,7 @@ +// 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.Linq; using System.Text; diff --git a/src/mono/msbuild/AndroidTestRunner/AndroidTestRunner.csproj b/src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.csproj similarity index 74% rename from src/mono/msbuild/AndroidTestRunner/AndroidTestRunner.csproj rename to src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.csproj index 8c6e2429f6ee2..906eea315338d 100644 --- a/src/mono/msbuild/AndroidTestRunner/AndroidTestRunner.csproj +++ b/src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.csproj @@ -1,11 +1,11 @@ Exe - bin - $(NetCoreAppCurrent) enable + $(NetCoreAppCurrent) + diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs index 6d87c677fd020..679b5406f8170 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs @@ -437,7 +437,7 @@ public static IEnumerable PostAsync_Cancel_CancellationTokenPassedToCo bool called = false; var content = new StreamContent(new DelegateStream( canReadFunc: () => true, - readAsyncFunc: (buffer, offset, count, cancellationToken) => + readAsyncFunc: async (buffer, offset, count, cancellationToken) => { int result = 1; if (called) @@ -445,11 +445,17 @@ public static IEnumerable PostAsync_Cancel_CancellationTokenPassedToCo result = 0; Assert.False(cancellationToken.IsCancellationRequested); tokenSource.Cancel(); - Assert.True(cancellationToken.IsCancellationRequested); + + // Wait for cancellation to occur. It should be very quickly after it's been requested. + var tcs = new TaskCompletionSource(); + using (cancellationToken.Register(() => tcs.SetResult(true))) + { + await tcs.Task; + } } called = true; - return Task.FromResult(result); + return result; } )); yield return new object[] { content, tokenSource }; @@ -467,7 +473,7 @@ public static IEnumerable PostAsync_Cancel_CancellationTokenPassedToCo lengthFunc: () => 1, positionGetFunc: () => 0, positionSetFunc: _ => {}, - readAsyncFunc: (buffer, offset, count, cancellationToken) => + readAsyncFunc: async (buffer, offset, count, cancellationToken) => { int result = 1; if (called) @@ -475,11 +481,17 @@ public static IEnumerable PostAsync_Cancel_CancellationTokenPassedToCo result = 0; Assert.False(cancellationToken.IsCancellationRequested); tokenSource.Cancel(); - Assert.True(cancellationToken.IsCancellationRequested); + + // Wait for cancellation to occur. It should be very quickly after it's been requested. + var tcs = new TaskCompletionSource(); + using (cancellationToken.Register(() => tcs.SetResult(true))) + { + await tcs.Task; + } } called = true; - return Task.FromResult(result); + return result; } ))); yield return new object[] { content, tokenSource }; @@ -497,7 +509,7 @@ public static IEnumerable PostAsync_Cancel_CancellationTokenPassedToCo lengthFunc: () => 1, positionGetFunc: () => 0, positionSetFunc: _ => {}, - readAsyncFunc: (buffer, offset, count, cancellationToken) => + readAsyncFunc: async (buffer, offset, count, cancellationToken) => { int result = 1; if (called) @@ -505,11 +517,17 @@ public static IEnumerable PostAsync_Cancel_CancellationTokenPassedToCo result = 0; Assert.False(cancellationToken.IsCancellationRequested); tokenSource.Cancel(); - Assert.True(cancellationToken.IsCancellationRequested); + + // Wait for cancellation to occur. It should be very quickly after it's been requested. + var tcs = new TaskCompletionSource(); + using (cancellationToken.Register(() => tcs.SetResult(true))) + { + await tcs.Task; + } } called = true; - return Task.FromResult(result); + return result; } ))); yield return new object[] { content, tokenSource }; diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs index b264aa6bc6c5d..735642702cded 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs @@ -150,9 +150,7 @@ public async Task GetAsync_AllowedSSLVersion_Succeeds(SslProtocols acceptedProto public static IEnumerable SupportedSSLVersionServers() { #pragma warning disable 0618 // SSL2/3 are deprecated - if (PlatformDetection.IsWindows || - PlatformDetection.IsOSX || - (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion < new Version(1, 0, 2) && !PlatformDetection.IsDebian)) + if (PlatformDetection.SupportsSsl3) { yield return new object[] { SslProtocols.Ssl3, Configuration.Http.SSLv3RemoteServer }; } @@ -197,7 +195,7 @@ public async Task GetAsync_SupportedSSLVersion_Succeeds(SslProtocols sslProtocol public static IEnumerable NotSupportedSSLVersionServers() { #pragma warning disable 0618 - if (PlatformDetection.IsWindows10Version1607OrGreater) + if (PlatformDetection.SupportsSsl2) { yield return new object[] { SslProtocols.Ssl2, Configuration.Http.SSLv2RemoteServer }; } diff --git a/src/libraries/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs b/src/libraries/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs index 0f45acc9f80f0..daf5caf54a60d 100644 --- a/src/libraries/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs +++ b/src/libraries/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs @@ -22,6 +22,8 @@ public VirtualNetworkStream(VirtualNetwork network, bool isServer) _isServer = isServer; } + public int DelayMilliseconds { get; set; } + public bool Disposed { get; private set; } public override bool CanRead => true; @@ -87,6 +89,11 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, await _readStreamLock.WaitAsync(cancellationToken).ConfigureAwait(false); try { + if (DelayMilliseconds > 0) + { + await Task.Delay(DelayMilliseconds, cancellationToken); + } + if (_readStream == null || (_readStream.Position >= _readStream.Length)) { _readStream = new MemoryStream(await _network.ReadFrameAsync(_isServer, cancellationToken).ConfigureAwait(false)); @@ -105,22 +112,16 @@ public override void Write(byte[] buffer, int offset, int count) _network.WriteFrame(_isServer, buffer.AsSpan(offset, count).ToArray()); } - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); - try + if (DelayMilliseconds > 0) { - Write(buffer, offset, count); - return Task.CompletedTask; - } - catch (Exception exc) - { - return Task.FromException(exc); + await Task.Delay(DelayMilliseconds, cancellationToken); } + + Write(buffer, offset, count); } public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => diff --git a/src/libraries/Common/tests/TestUtilities.Unicode/TestUtilities.Unicode.csproj b/src/libraries/Common/tests/TestUtilities.Unicode/TestUtilities.Unicode.csproj index a3eaba2cfc48d..5f241043489c3 100644 --- a/src/libraries/Common/tests/TestUtilities.Unicode/TestUtilities.Unicode.csproj +++ b/src/libraries/Common/tests/TestUtilities.Unicode/TestUtilities.Unicode.csproj @@ -47,7 +47,6 @@ - diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index d1688c9c860b0..45f0d59333667 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -27,7 +27,7 @@ public static void ThrowsContains(Action action, string expectedMessageConten Assert.Contains(expectedMessageContent, Assert.Throws(action).Message); } - public static void Throws(string netCoreParamName, string netFxParamName, Action action) + public static T Throws(string netCoreParamName, string netFxParamName, Action action) where T : ArgumentException { T exception = Assert.Throws(action); @@ -35,7 +35,7 @@ public static void Throws(string netCoreParamName, string netFxParamName, Act if (netFxParamName == null && IsNetFramework) { // Param name varies between .NET Framework versions -- skip checking it - return; + return exception; } string expectedParamName = @@ -43,6 +43,7 @@ public static void Throws(string netCoreParamName, string netFxParamName, Act netFxParamName : netCoreParamName; Assert.Equal(expectedParamName, exception.ParamName); + return exception; } public static void Throws(string netCoreParamName, string netFxParamName, Func testCode) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs index 4ecee83ba6693..38fb7d598ce0a 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs @@ -2,8 +2,8 @@ // 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.IO; using System.Runtime.InteropServices; -using System.Xml.Linq; namespace System { @@ -34,14 +34,10 @@ public static partial class PlatformDetection // OSX family public static bool IsOSX => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); public static bool IsNotOSX => !IsOSX; - public static Version OSXVersion => IsOSX ? - ToVersion(Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion) : - throw new PlatformNotSupportedException(); - private static Lazy m_osxProductVersion = new Lazy(GetOSXProductVersion); - public static bool IsMacOsHighSierraOrHigher => IsOSX && (m_osxProductVersion.Value.Major > 10 || (m_osxProductVersion.Value.Major == 10 && m_osxProductVersion.Value.Minor >= 13)); + public static bool IsMacOsHighSierraOrHigher => IsOSX && Environment.OSVersion.Version >= new Version(10, 13); public static bool IsNotMacOsHighSierraOrHigher => !IsMacOsHighSierraOrHigher; - public static bool IsMacOsMojaveOrHigher => IsOSX && (m_osxProductVersion.Value.Major > 10 || (m_osxProductVersion.Value.Major == 10 && m_osxProductVersion.Value.Minor >= 14)); - public static bool IsMacOsCatalinaOrHigher => IsOSX && (m_osxProductVersion.Value.Major > 10 || (m_osxProductVersion.Value.Major == 10 && m_osxProductVersion.Value.Minor >= 15)); + public static bool IsMacOsMojaveOrHigher => IsOSX && Environment.OSVersion.Version >= new Version(10, 14); + public static bool IsMacOsCatalinaOrHigher => IsOSX && Environment.OSVersion.Version >= new Version(10, 15); // RedHat family covers RedHat and CentOS public static bool IsRedHatFamily => IsRedHatFamilyAndVersion(); @@ -106,56 +102,6 @@ public static string LibcVersion } } - private static Version GetOSXProductVersion() - { - if (IsOSX) - { - try - { - // - // - // ProductBuildVersion - // 17A330h - // ProductCopyright - // 1983-2017 Apple Inc. - // ProductName - // Mac OS X - // ProductUserVisibleVersion - // 10.13 - // ProductVersion - // 10.13 - // - // - - XElement dict = XDocument.Load("/System/Library/CoreServices/SystemVersion.plist").Root.Element("dict"); - if (dict != null) - { - foreach (XElement key in dict.Elements("key")) - { - if ("ProductVersion".Equals(key.Value)) - { - XElement stringElement = key.NextNode as XElement; - if (stringElement != null && stringElement.Name.LocalName.Equals("string")) - { - string versionString = stringElement.Value; - if (versionString != null) - { - return Version.Parse(versionString); - } - } - } - } - } - } - catch - { - } - } - - // In case of exception, couldn't get the version or non osx - return new Version(0, 0, 0); - } - private static Version s_opensslVersion; private static Version GetOpenSslVersion() { @@ -204,11 +150,38 @@ private static Version ToVersion(string versionString) } } - private static DistroInfo GetDistroInfo() => new DistroInfo() + private static DistroInfo GetDistroInfo() { - Id = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystem, - VersionId = ToVersion(Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion) - }; + DistroInfo result = new DistroInfo(); + + if (IsFreeBSD) + { + result.Id = "FreeBSD"; + // example: + // FreeBSD 11.0-RELEASE-p1 FreeBSD 11.0-RELEASE-p1 #0 r306420: Thu Sep 29 01:43:23 UTC 2016 root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC + // What we want is major release as minor releases should be compatible. + result.VersionId = ToVersion(RuntimeInformation.OSDescription.Split()[1].Split('.')[0]); + } + else if (File.Exists("/etc/os-release")) + { + foreach (string line in File.ReadAllLines("/etc/os-release")) + { + if (line.StartsWith("ID=", StringComparison.Ordinal)) + { + result.Id = line.Substring(3).Trim('"', '\''); + } + else if (line.StartsWith("VERSION_ID=", StringComparison.Ordinal)) + { + result.VersionId = ToVersion(line.Substring(11).Trim('"', '\'')); + } + } + } + + result.Id ??= "Linux"; + result.VersionId ??= ToVersion(string.Empty); + + return result; + } private static bool IsRedHatFamilyAndVersion(int major = -1, int minor = -1, int build = -1, int revision = -1) { diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index e6b1845a1ea68..a17d3eebce28d 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -24,6 +24,8 @@ public static partial class PlatformDetection public static bool IsMonoInterpreter => GetIsRunningOnMonoInterpreter(); public static bool IsFreeBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD")); public static bool IsNetBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("NETBSD")); + public static bool IsiOS => RuntimeInformation.IsOSPlatform(OSPlatform.Create("IOS")); + public static bool IstvOS => RuntimeInformation.IsOSPlatform(OSPlatform.Create("TVOS")); public static bool IsArmProcess => RuntimeInformation.ProcessArchitecture == Architecture.Arm; public static bool IsNotArmProcess => !IsArmProcess; @@ -63,6 +65,7 @@ public static bool IsDrawingSupported public static bool IsInContainer => GetIsInContainer(); public static bool SupportsSsl3 => GetSsl3Support(); + public static bool SupportsSsl2 => IsWindows && !PlatformDetection.IsWindows10Version1607OrGreater; #if NETCOREAPP public static bool IsReflectionEmitSupported = RuntimeFeature.IsDynamicCodeSupported; @@ -108,11 +111,13 @@ public static bool IsNonZeroLowerBoundArraySupported // Windows - Schannel supports alpn from win8.1/2012 R2 and higher. // Linux - OpenSsl supports alpn from openssl 1.0.2 and higher. // OSX - SecureTransport doesn't expose alpn APIs. TODO https://github.com/dotnet/runtime/issues/27727 + public static bool IsOpenSslSupported => IsLinux || IsFreeBSD; + public static bool SupportsAlpn => (IsWindows && !IsWindows7) || - ((!IsOSX && !IsWindows) && + (IsOpenSslSupported && (OpenSslVersion.Major >= 1 && (OpenSslVersion.Minor >= 1 || OpenSslVersion.Build >= 2))); - public static bool SupportsClientAlpn => SupportsAlpn || (IsOSX && PlatformDetection.OSXVersion > new Version(10, 12)); + public static bool SupportsClientAlpn => SupportsAlpn || IsOSX || IsiOS || IstvOS; // OpenSSL 1.1.1 and above. public static bool SupportsTls13 => GetTls13Support(); @@ -141,7 +146,7 @@ public static string GetDistroVersionString() } else if (IsOSX) { - return "OSX Version=" + m_osxProductVersion.Value.ToString(); + return "OSX Version=" + Environment.OSVersion.Version.ToString(); } else { @@ -260,16 +265,18 @@ private static bool GetTls13Support() // assume no if key is missing or on error. return false; } - else if (IsOSX) + else if (IsOSX || IsiOS || IstvOS) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/1979")] return false; } - else + else if (IsOpenSslSupported) { // Covers Linux and FreeBSD return OpenSslVersion >= new Version(1,1,1); } + + return false; } private static bool GetIsRunningOnMonoInterpreter() diff --git a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj index a589043f2a565..b9207224c8709 100644 --- a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj +++ b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj @@ -63,6 +63,5 @@ - diff --git a/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs new file mode 100644 index 0000000000000..0ee51166fbf29 --- /dev/null +++ b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs @@ -0,0 +1,29 @@ +// 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.Linq; +using System.Text; +using System.IO; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +public class WasmTestRunner +{ + public static int Main(string[] args) + { + Console.Write("Args: "); + foreach (string arg in args) + { + Console.Write(arg); + } + Console.WriteLine("."); + + return 0; + } +} diff --git a/src/mono/msbuild/AppleTestRunner/AppleTestRunner.csproj b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.csproj similarity index 74% rename from src/mono/msbuild/AppleTestRunner/AppleTestRunner.csproj rename to src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.csproj index 8c6e2429f6ee2..7d68c49a196a3 100644 --- a/src/mono/msbuild/AppleTestRunner/AppleTestRunner.csproj +++ b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.csproj @@ -1,11 +1,11 @@ Exe - bin - $(NetCoreAppCurrent) enable + $(NetCoreAppCurrent) + diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index a86add4cad990..fca7201e832da 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -20,8 +20,6 @@ $(LibrariesProjectRoot)OSGroups.json $(NetCoreAppCurrent) false - - $(TargetOS) $(AdditionalBuildTargetFrameworks);$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-NetBSD;$(NetCoreAppCurrent)-FreeBSD $(RepositoryEngineeringDir)LicenseHeader.txt @@ -41,9 +39,9 @@ x64 x64 - - $(TargetOS.ToLowerInvariant()) + + $(TargetOS.ToLowerInvariant()) Debug @@ -106,7 +104,7 @@ <_runtimeOS Condition="'$(_runtimeOS)' == 'tizen.5.0.0'">linux <_runtimeOS Condition="'$(PortableBuild)' == 'true'">$(_portableOS) $(_runtimeOS)-x64 - $(_runtimeOS)-$(HostArch) + $(_runtimeOS)-$(HostArch) linux-x64 @@ -171,7 +169,7 @@ $([MSBuild]::NormalizeDirectory('$(AssemblyBinDirOutputPath)', 'ref')) - + @@ -272,9 +270,10 @@ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'testhost', '$(BuildSettings)')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'lib-runtime-packs')) - $([MSBuild]::NormalizeDirectory('$(NETCoreAppRuntimePackPath)', 'runtimes', '$(PackageRID)', 'lib', '$(NETCoreAppFramework)')) - $([MSBuild]::NormalizeDirectory('$(NETCoreAppRuntimePackPath)', 'runtimes', '$(PackageRID)', 'native')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'lib-runtime-packs', '$(BuildSettings)')) + $([MSBuild]::NormalizeDirectory('$(RuntimePackDir)', 'runtimes', '$(PackageRID)')) + $([MSBuild]::NormalizeDirectory('$(RuntimePackRidDir)', 'lib', '$(NetCoreAppCurrent)')) + $([MSBuild]::NormalizeDirectory('$(RuntimePackRidDir)', 'native')) runtimes/$(PackageRID) $(ArtifactsObjDir)version.txt @@ -326,7 +325,9 @@ true - true + + true + true diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index 7c2f62de0a78f..cad6c2ed4803a 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -2,13 +2,6 @@ $([MSBuild]::NormalizeDirectory('$(RefRootPath)', '$(TargetFramework)')) - - - $(TargetOS) - $(Configuration) - $(TargetOS) - $(Configuration) - @@ -95,11 +88,11 @@ - $(NETCoreAppRuntimePackLibPath) + $(RuntimePackLibDir) - $(NETCoreAppRuntimePackNativePath) + $(RuntimePackNativeDir) NativeBinPlaceItem @@ -136,9 +129,10 @@ - - + + + @@ -153,27 +147,23 @@ - + - <_RefSourceFileOutputPath>$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '..', 'ref', '$(AssemblyName).cs')) <_ExcludeAPIList>$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '..', 'ref', 'ReferenceSourceExcludeApi.txt')) <_ExcludeAttributesList>$(RepositoryEngineeringDir)DefaultGenApiDocIds.txt - <_LicenseHeaderTxtPath>$(RepositoryEngineeringDir)LicenseHeader.txt - - - - <_GenAPICmd>$(_GenAPICommand) - <_GenAPICmd>$(_GenAPICmd) "@(IntermediateAssembly)" - <_GenAPICmd>$(_GenAPICmd) --lib-path "$(RefPath.Trim('\/'))" - <_GenAPICmd>$(_GenAPICmd) --out "$(_RefSourceFileOutputPath)" - <_GenAPICmd>$(_GenAPICmd) --exclude-attributes-list "$(_ExcludeAttributesList)" - <_GenAPICmd Condition="Exists('$(_ExcludeAPIList)')">$(_GenAPICmd) --exclude-api-list "$(_ExcludeAPIList)" - <_GenAPICmd>$(_GenAPICmd) --header-file "$(_LicenseHeaderTxtPath)" - <_GenAPICmd Condition="'$(LangVersion)' != ''">$(_GenAPICmd) --lang-version "$(LangVersion)" + <_LicenseHeaderTxtPath>$(RepositoryEngineeringDir)LicenseHeader.txt + $([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '..', 'ref', '$(AssemblyName).cs')) + $(GenAPIAdditionalParameters) --exclude-attributes-list "$(_ExcludeAttributesList)" + $(GenAPIAdditionalParameters) --exclude-api-list "$(_ExcludeAPIList)" + $(GenAPIAdditionalParameters) --header-file "$(_LicenseHeaderTxtPath)" + $(GenAPIAdditionalParameters) --lang-version "$(LangVersion)" + $(GenAPIAdditionalParameters) --follow-type-forwards + - - + + diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs index 9e9ade68ea2bf..11bfce9b08dcd 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs @@ -399,7 +399,7 @@ private static IUnknownReleaseDelegate Create_IUnknownRelease() method.Emit(OpCodes.Ret); - return (IUnknownReleaseDelegate)dm.CreateDelegate(typeof(IUnknownReleaseDelegate)); + return dm.CreateDelegate(); } internal static readonly IntPtr s_nullInterfaceId = GetNullInterfaceId(); @@ -539,7 +539,7 @@ private static IDispatchInvokeDelegate Create_IDispatchInvoke(bool returnResult) method.EmitCalli(OpCodes.Calli, CallingConvention.Winapi, typeof(int), invokeParamTypes); method.Emit(OpCodes.Ret); - return (IDispatchInvokeDelegate)dm.CreateDelegate(typeof(IDispatchInvokeDelegate)); + return dm.CreateDelegate(); } #endregion diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs index e08bc7d9b66f2..3cc1e52fb30b4 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs @@ -262,7 +262,7 @@ private static bool IsTypeParameterEquivalentToTypeInst(this Type typeParam, Typ modifiers: null); if (apiMethod != null) { - Func apiDelegate = (Func)(apiMethod.CreateDelegate(typeof(Func))); + Func apiDelegate = apiMethod.CreateDelegate>(); try { bool result = apiDelegate(m1, m2); diff --git a/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj b/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj index 2c74bc81f267d..11dfc740701cd 100644 --- a/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj +++ b/src/libraries/Microsoft.CSharp/tests/Microsoft.CSharp.Tests.csproj @@ -34,7 +34,7 @@ - + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/AssemblyAttributes.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/AssemblyAttributes.cs new file mode 100644 index 0000000000000..82c60ec93e309 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/AssemblyAttributes.cs @@ -0,0 +1,7 @@ +// 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 Xunit; + +[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/35970", TestRuntimes.Mono)] diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj b/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj index 61a5cedc58bd8..edd848567a5c4 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/src/Microsoft.Extensions.Configuration.Json.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj index 13214ba45ced1..654d0f9f53be6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj index 348382d6fd9ff..dfb45ab9f8cec 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj @@ -22,7 +22,7 @@ Link="Common\tests\Extensions\TestingUtils\Microsoft.AspNetCore.Testing\src\xunit\RuntimeFrameworks.cs" /> - + diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs index ffc3a406b9f8f..56802e813c795 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs @@ -29,7 +29,7 @@ public ChainedConfigurationProvider(ChainedConfigurationSource source) } if (source.Configuration == null) { - throw new ArgumentNullException(nameof(source.Configuration)); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "source.Configuration"), nameof(source)); } _config = source.Configuration; diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx index 52fb2be3e50a1..1c4c38af9b51b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx @@ -120,4 +120,7 @@ A configuration source is not registered. Please register one before setting a value. + + Null is not a valid value for '{0}'. + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj index 8e8efebdf748b..50cdcabc140e5 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj @@ -3,17 +3,15 @@ $(NetCoreAppCurrent);$(NetFrameworkCurrent);net461;netstandard2.0;netstandard2.1 true - - True - $(DefineConstants);IL_EMIT - False - $(DefineConstants);SAVE_ASSEMBLIES + True + $(DefineConstants);IL_EMIT + $(DefineConstants);SAVE_ASSEMBLIES diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Dependency.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/Dependency.cs index e60989f77a5c8..6c26416a9359e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Dependency.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Dependency.cs @@ -13,11 +13,11 @@ public Dependency(string name, string version) { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException(nameof(name)); + throw new ArgumentException(null, nameof(name)); } if (string.IsNullOrEmpty(version)) { - throw new ArgumentException(nameof(version)); + throw new ArgumentException(null, nameof(version)); } Name = name; Version = version; diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Library.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/Library.cs index cef2b76d2c9c9..eb64ac5fc95da 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Library.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Library.cs @@ -43,15 +43,15 @@ public class Library { if (string.IsNullOrEmpty(type)) { - throw new ArgumentException(nameof(type)); + throw new ArgumentException(null, nameof(type)); } if (string.IsNullOrEmpty(name)) { - throw new ArgumentException(nameof(name)); + throw new ArgumentException(null, nameof(name)); } if (string.IsNullOrEmpty(version)) { - throw new ArgumentException(nameof(version)); + throw new ArgumentException(null, nameof(version)); } if (dependencies == null) { diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/ResourceAssembly.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/ResourceAssembly.cs index 998789b51001e..4e754367b7791 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/ResourceAssembly.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/ResourceAssembly.cs @@ -12,11 +12,11 @@ public ResourceAssembly(string path, string locale) { if (string.IsNullOrEmpty(path)) { - throw new ArgumentException(nameof(path)); + throw new ArgumentException(null, nameof(path)); } if (string.IsNullOrEmpty(locale)) { - throw new ArgumentException(nameof(locale)); + throw new ArgumentException(null, nameof(locale)); } Locale = locale; Path = path; @@ -27,4 +27,4 @@ public ResourceAssembly(string path, string locale) public string Path { get; set; } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeAssembly.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeAssembly.cs index c4e07fe7deb4b..edf908e9766c6 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeAssembly.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeAssembly.cs @@ -16,11 +16,11 @@ public RuntimeAssembly(string assemblyName, string path) { if (string.IsNullOrEmpty(assemblyName)) { - throw new ArgumentException(nameof(assemblyName)); + throw new ArgumentException(null, nameof(assemblyName)); } if (string.IsNullOrEmpty(path)) { - throw new ArgumentException(nameof(path)); + throw new ArgumentException(null, nameof(path)); } _assemblyName = assemblyName; Path = path; @@ -45,4 +45,4 @@ public static RuntimeAssembly Create(string path) return new RuntimeAssembly(assemblyName, path); } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFallbacks.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFallbacks.cs index 32b3635c92f66..9ce186d557b6c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFallbacks.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFallbacks.cs @@ -18,7 +18,7 @@ public RuntimeFallbacks(string runtime, IEnumerable fallbacks) { if (string.IsNullOrEmpty(runtime)) { - throw new ArgumentException(nameof(runtime)); + throw new ArgumentException(null, nameof(runtime)); } if (fallbacks == null) { @@ -28,4 +28,4 @@ public RuntimeFallbacks(string runtime, IEnumerable fallbacks) Fallbacks = fallbacks.ToArray(); } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFile.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFile.cs index 542a5b65a51aa..5777a34dfa2c4 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFile.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/RuntimeFile.cs @@ -12,7 +12,7 @@ public RuntimeFile(string path, string assemblyVersion, string fileVersion) { if (string.IsNullOrEmpty(path)) { - throw new ArgumentException(nameof(path)); + throw new ArgumentException(null, nameof(path)); } Path = path; diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/TargetInfo.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/TargetInfo.cs index 0b2f53607b863..485ff58d3eb23 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/TargetInfo.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/TargetInfo.cs @@ -14,7 +14,7 @@ public class TargetInfo { if (string.IsNullOrEmpty(framework)) { - throw new ArgumentException(nameof(framework)); + throw new ArgumentException(null, nameof(framework)); } Framework = framework; @@ -32,4 +32,4 @@ public class TargetInfo public bool IsPortable { get; } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/tests/ReferenceAssemblyResolverTests.cs b/src/libraries/Microsoft.Extensions.DependencyModel/tests/ReferenceAssemblyResolverTests.cs index 99f8fa4ed6c29..a165d17eacccd 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/tests/ReferenceAssemblyResolverTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/tests/ReferenceAssemblyResolverTests.cs @@ -6,8 +6,6 @@ using System.Collections.Generic; using System.IO; using FluentAssertions; -using Microsoft.DotNet.PlatformAbstractions; -using Microsoft.Extensions.DependencyModel; using Microsoft.Extensions.DependencyModel.Resolution; using Xunit; using F = Microsoft.Extensions.DependencyModel.Tests.TestLibraryFactory; diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj index 1996b8d4effcb..2194698876f88 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj @@ -1,7 +1,7 @@ - netstandard2.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0 $(NoWarn);CS1591 Microsoft.Extensions.Hosting true diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs index 277995d71b183..ddfb1feeb450a 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs @@ -167,7 +167,7 @@ public static IHostBuilder UseConsoleLifetime(this IHostBuilder hostBuilder, Act /// /// The to configure. /// A that can be used to cancel the console. - /// A that only completes when the token is triggeredor shutdown is triggered. + /// A that only completes when the token is triggered or shutdown is triggered. public static Task RunConsoleAsync(this IHostBuilder hostBuilder, CancellationToken cancellationToken = default) { return hostBuilder.UseConsoleLifetime().Build().RunAsync(cancellationToken); @@ -179,7 +179,7 @@ public static Task RunConsoleAsync(this IHostBuilder hostBuilder, CancellationTo /// The to configure. /// The delegate for configuring the . /// A that can be used to cancel the console. - /// A that only completes when the token is triggeredor shutdown is triggered. + /// A that only completes when the token is triggered or shutdown is triggered. public static Task RunConsoleAsync(this IHostBuilder hostBuilder, Action configureOptions, CancellationToken cancellationToken = default) { return hostBuilder.UseConsoleLifetime(configureOptions).Build().RunAsync(cancellationToken); diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj index 0333fb952b461..7dc68b6e59196 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj @@ -1,7 +1,7 @@ - netstandard2.0;netstandard2.1;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0;netstandard2.1 $(NoWarn);CS1591 true diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Logging/RedactedLogValueIntegrationTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Logging/RedactedLogValueIntegrationTest.cs index 67ec29684936e..3b3c122b52fa9 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Logging/RedactedLogValueIntegrationTest.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Logging/RedactedLogValueIntegrationTest.cs @@ -51,7 +51,7 @@ public async Task RedactHeaderValueWithHeaderList_ValueIsRedactedBeforeLogging() m.EventId == LoggingScopeHttpMessageHandler.Log.EventIds.RequestHeader && m.LoggerName == "System.Net.Http.HttpClient.test.LogicalHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Request Headers: Authorization: * Cache-Control: no-cache @@ -63,7 +63,7 @@ public async Task RedactHeaderValueWithHeaderList_ValueIsRedactedBeforeLogging() m.EventId == LoggingHttpMessageHandler.Log.EventIds.RequestHeader && m.LoggerName == "System.Net.Http.HttpClient.test.ClientHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Request Headers: Authorization: * Cache-Control: no-cache @@ -75,7 +75,7 @@ public async Task RedactHeaderValueWithHeaderList_ValueIsRedactedBeforeLogging() m.EventId == LoggingHttpMessageHandler.Log.EventIds.ResponseHeader && m.LoggerName == "System.Net.Http.HttpClient.test.ClientHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Response Headers: X-Sensitive: * Y-Non-Sensitive: innocuous value @@ -87,7 +87,7 @@ public async Task RedactHeaderValueWithHeaderList_ValueIsRedactedBeforeLogging() m.EventId == LoggingScopeHttpMessageHandler.Log.EventIds.ResponseHeader && m.LoggerName == "System.Net.Http.HttpClient.test.LogicalHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Response Headers: X-Sensitive: * Y-Non-Sensitive: innocuous value @@ -132,7 +132,7 @@ public async Task RedactHeaderValueWithPredicate_ValueIsRedactedBeforeLogging() m.EventId == LoggingScopeHttpMessageHandler.Log.EventIds.RequestHeader && m.LoggerName == "System.Net.Http.HttpClient.test.LogicalHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Request Headers: Authorization: * Cache-Control: no-cache @@ -144,7 +144,7 @@ public async Task RedactHeaderValueWithPredicate_ValueIsRedactedBeforeLogging() m.EventId == LoggingHttpMessageHandler.Log.EventIds.RequestHeader && m.LoggerName == "System.Net.Http.HttpClient.test.ClientHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Request Headers: Authorization: * Cache-Control: no-cache @@ -156,7 +156,7 @@ public async Task RedactHeaderValueWithPredicate_ValueIsRedactedBeforeLogging() m.EventId == LoggingHttpMessageHandler.Log.EventIds.ResponseHeader && m.LoggerName == "System.Net.Http.HttpClient.test.ClientHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Response Headers: X-Sensitive: * Y-Non-Sensitive: innocuous value @@ -168,7 +168,7 @@ public async Task RedactHeaderValueWithPredicate_ValueIsRedactedBeforeLogging() m.EventId == LoggingScopeHttpMessageHandler.Log.EventIds.ResponseHeader && m.LoggerName == "System.Net.Http.HttpClient.test.LogicalHandler"; })); - Assert.Equal( + Assert.StartsWith( @"Response Headers: X-Sensitive: * Y-Non-Sensitive: innocuous value diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs index c2b9f5e73d3ef..a2fb5967231b6 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs @@ -40,7 +40,7 @@ public ConsoleLoggerFormat Format } /// - /// Gets or sets value indicating the minimum level of messaged that would get written to Console.Error. + /// Gets or sets value indicating the minimum level of messages that would get written to Console.Error. /// public LogLevel LogToStandardErrorThreshold { get; set; } = LogLevel.None; diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj index 67e55d95d6322..9feb20a52838a 100644 --- a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/Microsoft.Extensions.Options.ConfigurationExtensions.csproj @@ -1,7 +1,7 @@ - netstandard2.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0 true diff --git a/src/libraries/Microsoft.Extensions.Options.DataAnnotations/src/Microsoft.Extensions.Options.DataAnnotations.csproj b/src/libraries/Microsoft.Extensions.Options.DataAnnotations/src/Microsoft.Extensions.Options.DataAnnotations.csproj index 043d82dc2348f..8dadd0c88af19 100644 --- a/src/libraries/Microsoft.Extensions.Options.DataAnnotations/src/Microsoft.Extensions.Options.DataAnnotations.csproj +++ b/src/libraries/Microsoft.Extensions.Options.DataAnnotations/src/Microsoft.Extensions.Options.DataAnnotations.csproj @@ -1,7 +1,7 @@ - netstandard2.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0 true diff --git a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj index 94e49733c1e11..fcc42385829ff 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj +++ b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj @@ -1,7 +1,7 @@ - netstandard2.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0 true diff --git a/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj b/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj index 4bcbb7f525744..c237f53d34828 100644 --- a/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj +++ b/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj @@ -1,13 +1,12 @@ - Microsoft.Win32.Registry.AccessControl true - SR.PlatformNotSupported_RegistryAccessControl netstandard2.0-Windows_NT;netstandard2.0;net461-Windows_NT;$(NetFrameworkCurrent)-Windows_NT true + SR.PlatformNotSupported_RegistryAccessControl true diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj b/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj index c291861079963..9083620b97edd 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj @@ -3,7 +3,6 @@ true $(NoWarn);CS1573 $(DefineConstants);REGISTRY_ASSEMBLY - $(NoWarn);CA1823 $(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix;$(NetFrameworkCurrent)-Windows_NT;netstandard2.0-Windows_NT;netstandard2.0-Unix;netstandard2.0;net461-Windows_NT true true @@ -13,6 +12,7 @@ true SR.PlatformNotSupported_Registry + $(NoWarn);CA1823 true - SR.PlatformNotSupported_SystemEvents + SR.PlatformNotSupported_SystemEvents cmakeargs -DCLR_ADDITIONAL_LINKER_FLAGS=<...> # if(CLR_CMAKE_TARGET_UNIX) - if(NOT CLR_CMAKE_TARGET_ARCH_WASM AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS) + if(NOT CLR_CMAKE_TARGET_BROWSER AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS) if(CLR_CMAKE_TARGET_OSX) add_definitions(-DTARGET_OSX) add_link_options(-Wl,-bind_at_load) @@ -190,7 +189,7 @@ include(configure.cmake) add_subdirectory(System.IO.Compression.Native) -if (NOT CLR_CMAKE_TARGET_ARCH_WASM AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ANDROID) +if (NOT CLR_CMAKE_TARGET_BROWSER AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ANDROID) add_subdirectory(System.IO.Ports.Native) endif() @@ -200,26 +199,22 @@ endif() add_subdirectory(System.Native) -if(CLR_CMAKE_TARGET_ARCH_WASM) +if(CLR_CMAKE_TARGET_BROWSER) # skip for now elseif(CLR_CMAKE_TARGET_IOS) add_subdirectory(System.Net.Security.Native) - #add_subdirectory(System.Globalization.Native) # TODO: reenable # System.Security.Cryptography.Native is intentionally disabled on iOS # it is only used for interacting with OpenSSL which isn't useful there elseif(CLR_CMAKE_TARGET_TVOS) #add_subdirectory(System.Net.Security.Native) # no gssapi on tvOS, see https://developer.apple.com/documentation/gss - #add_subdirectory(System.Globalization.Native) # TODO: reenable # System.Security.Cryptography.Native is intentionally disabled on tvOS # it is only used for interacting with OpenSSL which isn't useful there elseif(CLR_CMAKE_TARGET_ANDROID AND NOT CROSS_ROOTFS) - add_subdirectory(System.Globalization.Native) #add_subdirectory(System.Net.Security.Native) # TODO: reenable - if (NOT "$ENV{AndroidOpenSslHeaders}" STREQUAL "") + if (NOT "$ENV{ANDROID_OPENSSL_AAR}" STREQUAL "") add_subdirectory(System.Security.Cryptography.Native) endif() else() - add_subdirectory(System.Globalization.Native) add_subdirectory(System.Net.Security.Native) add_subdirectory(System.Security.Cryptography.Native) endif() diff --git a/src/libraries/Native/Unix/Common/pal_error_common.h b/src/libraries/Native/Unix/Common/pal_error_common.h new file mode 100644 index 0000000000000..f185811e6fb22 --- /dev/null +++ b/src/libraries/Native/Unix/Common/pal_error_common.h @@ -0,0 +1,580 @@ +// 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. + +#pragma once + +#include "pal_compiler.h" +#include "pal_types.h" +#include "pal_config.h" +#include "pal_utilities.h" +#include +#include +#include +#include + +// ENODATA is not defined in FreeBSD 10.3 but is defined in 11.0 +#if defined(__FreeBSD__) & !defined(ENODATA) +#define ENODATA ENOATTR +#endif + +/** + * Error codes returned via ConvertErrno. + * + * Only the names (without the PAL_ prefix) are specified by POSIX. + * + * The values chosen below are simply assigned arbitrarily (originally + * in alphabetical order they appear in the spec, but they can't change so + * add new values to the end!). + * + * Also, the values chosen are deliberately outside the range of + * typical UNIX errnos (small numbers), HRESULTs (negative for errors) + * and Win32 errors (0x0000 - 0xFFFF). This isn't required for + * correctness, but may help debug a caller that is interpreting a raw + * int incorrectly. + * + * Wherever the spec says "x may be the same value as y", we do use + * the same value so that callers cannot not take a dependency on + * being able to distinguish between them. + */ +typedef enum +{ + Error_SUCCESS = 0, + + Error_E2BIG = 0x10001, // Argument list too long. + Error_EACCES = 0x10002, // Permission denied. + Error_EADDRINUSE = 0x10003, // Address in use. + Error_EADDRNOTAVAIL = 0x10004, // Address not available. + Error_EAFNOSUPPORT = 0x10005, // Address family not supported. + Error_EAGAIN = 0x10006, // Resource unavailable, try again (same value as EWOULDBLOCK), + Error_EALREADY = 0x10007, // Connection already in progress. + Error_EBADF = 0x10008, // Bad file descriptor. + Error_EBADMSG = 0x10009, // Bad message. + Error_EBUSY = 0x1000A, // Device or resource busy. + Error_ECANCELED = 0x1000B, // Operation canceled. + Error_ECHILD = 0x1000C, // No child processes. + Error_ECONNABORTED = 0x1000D, // Connection aborted. + Error_ECONNREFUSED = 0x1000E, // Connection refused. + Error_ECONNRESET = 0x1000F, // Connection reset. + Error_EDEADLK = 0x10010, // Resource deadlock would occur. + Error_EDESTADDRREQ = 0x10011, // Destination address required. + Error_EDOM = 0x10012, // Mathematics argument out of domain of function. + Error_EDQUOT = 0x10013, // Reserved. + Error_EEXIST = 0x10014, // File exists. + Error_EFAULT = 0x10015, // Bad address. + Error_EFBIG = 0x10016, // File too large. + Error_EHOSTUNREACH = 0x10017, // Host is unreachable. + Error_EIDRM = 0x10018, // Identifier removed. + Error_EILSEQ = 0x10019, // Illegal byte sequence. + Error_EINPROGRESS = 0x1001A, // Operation in progress. + Error_EINTR = 0x1001B, // Interrupted function. + Error_EINVAL = 0x1001C, // Invalid argument. + Error_EIO = 0x1001D, // I/O error. + Error_EISCONN = 0x1001E, // Socket is connected. + Error_EISDIR = 0x1001F, // Is a directory. + Error_ELOOP = 0x10020, // Too many levels of symbolic links. + Error_EMFILE = 0x10021, // File descriptor value too large. + Error_EMLINK = 0x10022, // Too many links. + Error_EMSGSIZE = 0x10023, // Message too large. + Error_EMULTIHOP = 0x10024, // Reserved. + Error_ENAMETOOLONG = 0x10025, // Filename too long. + Error_ENETDOWN = 0x10026, // Network is down. + Error_ENETRESET = 0x10027, // Connection aborted by network. + Error_ENETUNREACH = 0x10028, // Network unreachable. + Error_ENFILE = 0x10029, // Too many files open in system. + Error_ENOBUFS = 0x1002A, // No buffer space available. + Error_ENODEV = 0x1002C, // No such device. + Error_ENOENT = 0x1002D, // No such file or directory. + Error_ENOEXEC = 0x1002E, // Executable file format error. + Error_ENOLCK = 0x1002F, // No locks available. + Error_ENOLINK = 0x10030, // Reserved. + Error_ENOMEM = 0x10031, // Not enough space. + Error_ENOMSG = 0x10032, // No message of the desired type. + Error_ENOPROTOOPT = 0x10033, // Protocol not available. + Error_ENOSPC = 0x10034, // No space left on device. + Error_ENOSYS = 0x10037, // Function not supported. + Error_ENOTCONN = 0x10038, // The socket is not connected. + Error_ENOTDIR = 0x10039, // Not a directory or a symbolic link to a directory. + Error_ENOTEMPTY = 0x1003A, // Directory not empty. + Error_ENOTRECOVERABLE = 0x1003B, // State not recoverable. + Error_ENOTSOCK = 0x1003C, // Not a socket. + Error_ENOTSUP = 0x1003D, // Not supported (same value as EOPNOTSUP). + Error_ENOTTY = 0x1003E, // Inappropriate I/O control operation. + Error_ENXIO = 0x1003F, // No such device or address. + Error_EOVERFLOW = 0x10040, // Value too large to be stored in data type. + Error_EOWNERDEAD = 0x10041, // Previous owner died. + Error_EPERM = 0x10042, // Operation not permitted. + Error_EPIPE = 0x10043, // Broken pipe. + Error_EPROTO = 0x10044, // Protocol error. + Error_EPROTONOSUPPORT = 0x10045, // Protocol not supported. + Error_EPROTOTYPE = 0x10046, // Protocol wrong type for socket. + Error_ERANGE = 0x10047, // Result too large. + Error_EROFS = 0x10048, // Read-only file system. + Error_ESPIPE = 0x10049, // Invalid seek. + Error_ESRCH = 0x1004A, // No such process. + Error_ESTALE = 0x1004B, // Reserved. + Error_ETIMEDOUT = 0x1004D, // Connection timed out. + Error_ETXTBSY = 0x1004E, // Text file busy. + Error_EXDEV = 0x1004F, // Cross-device link. + Error_ESOCKTNOSUPPORT = 0x1005E, // Socket type not supported. + Error_EPFNOSUPPORT = 0x10060, // Protocol family not supported. + Error_ESHUTDOWN = 0x1006C, // Socket shutdown. + Error_EHOSTDOWN = 0x10070, // Host is down. + Error_ENODATA = 0x10071, // No data available. + + // Error codes to track errors beyond kernel. + Error_EHOSTNOTFOUND = 0x20001, // Name lookup failed. + + // POSIX permits these to have the same value and we make them + // always equal so that we cannot introduce a dependency on + // distinguishing between them that would not work on all + // platforms. + Error_EOPNOTSUPP = Error_ENOTSUP, // Operation not supported on socket + Error_EWOULDBLOCK = Error_EAGAIN, // Operation would block + + // This one is not part of POSIX, but is a catch-all for the case + // where we cannot convert the raw errno value to something above. + Error_ENONSTANDARD = 0x1FFFF, +} Error; + +inline static int32_t ConvertErrorPlatformToPal(int32_t platformErrno) +{ + switch (platformErrno) + { + case 0: + return Error_SUCCESS; + case E2BIG: + return Error_E2BIG; + case EACCES: + return Error_EACCES; + case EADDRINUSE: + return Error_EADDRINUSE; + case EADDRNOTAVAIL: + return Error_EADDRNOTAVAIL; + case EAFNOSUPPORT: + return Error_EAFNOSUPPORT; + case EAGAIN: + return Error_EAGAIN; + case EALREADY: + return Error_EALREADY; + case EBADF: + return Error_EBADF; + case EBADMSG: + return Error_EBADMSG; + case EBUSY: + return Error_EBUSY; + case ECANCELED: + return Error_ECANCELED; + case ECHILD: + return Error_ECHILD; + case ECONNABORTED: + return Error_ECONNABORTED; + case ECONNREFUSED: + return Error_ECONNREFUSED; + case ECONNRESET: + return Error_ECONNRESET; + case EDEADLK: + return Error_EDEADLK; + case EDESTADDRREQ: + return Error_EDESTADDRREQ; + case EDOM: + return Error_EDOM; + case EDQUOT: + return Error_EDQUOT; + case EEXIST: + return Error_EEXIST; + case EFAULT: + return Error_EFAULT; + case EFBIG: + return Error_EFBIG; + case EHOSTUNREACH: + return Error_EHOSTUNREACH; + case EIDRM: + return Error_EIDRM; + case EILSEQ: + return Error_EILSEQ; + case EINPROGRESS: + return Error_EINPROGRESS; + case EINTR: + return Error_EINTR; + case EINVAL: + return Error_EINVAL; + case EIO: + return Error_EIO; + case EISCONN: + return Error_EISCONN; + case EISDIR: + return Error_EISDIR; + case ELOOP: + return Error_ELOOP; + case EMFILE: + return Error_EMFILE; + case EMLINK: + return Error_EMLINK; + case EMSGSIZE: + return Error_EMSGSIZE; + case EMULTIHOP: + return Error_EMULTIHOP; + case ENAMETOOLONG: + return Error_ENAMETOOLONG; + case ENETDOWN: + return Error_ENETDOWN; + case ENETRESET: + return Error_ENETRESET; + case ENETUNREACH: + return Error_ENETUNREACH; + case ENFILE: + return Error_ENFILE; + case ENOBUFS: + return Error_ENOBUFS; + case ENODEV: + return Error_ENODEV; + case ENOENT: + return Error_ENOENT; + case ENOEXEC: + return Error_ENOEXEC; + case ENOLCK: + return Error_ENOLCK; + case ENOLINK: + return Error_ENOLINK; + case ENOMEM: + return Error_ENOMEM; + case ENOMSG: + return Error_ENOMSG; + case ENOPROTOOPT: + return Error_ENOPROTOOPT; + case ENOSPC: + return Error_ENOSPC; + case ENOSYS: + return Error_ENOSYS; + case ENOTCONN: + return Error_ENOTCONN; + case ENOTDIR: + return Error_ENOTDIR; +#if ENOTEMPTY != EEXIST // AIX defines this + case ENOTEMPTY: + return Error_ENOTEMPTY; +#endif +#ifdef ENOTRECOVERABLE // not available in NetBSD + case ENOTRECOVERABLE: + return Error_ENOTRECOVERABLE; +#endif + case ENOTSOCK: + return Error_ENOTSOCK; + case ENOTSUP: + return Error_ENOTSUP; + case ENOTTY: + return Error_ENOTTY; + case ENXIO: + return Error_ENXIO; + case EOVERFLOW: + return Error_EOVERFLOW; +#ifdef EOWNERDEAD // not available in NetBSD + case EOWNERDEAD: + return Error_EOWNERDEAD; +#endif + case EPERM: + return Error_EPERM; + case EPIPE: + return Error_EPIPE; + case EPROTO: + return Error_EPROTO; + case EPROTONOSUPPORT: + return Error_EPROTONOSUPPORT; + case EPROTOTYPE: + return Error_EPROTOTYPE; + case ERANGE: + return Error_ERANGE; + case EROFS: + return Error_EROFS; + case ESPIPE: + return Error_ESPIPE; + case ESRCH: + return Error_ESRCH; + case ESTALE: + return Error_ESTALE; + case ETIMEDOUT: + return Error_ETIMEDOUT; + case ETXTBSY: + return Error_ETXTBSY; + case EXDEV: + return Error_EXDEV; +#ifdef ESOCKTNOSUPPORT + case ESOCKTNOSUPPORT: + return Error_ESOCKTNOSUPPORT; +#endif + case EPFNOSUPPORT: + return Error_EPFNOSUPPORT; + case ESHUTDOWN: + return Error_ESHUTDOWN; + case EHOSTDOWN: + return Error_EHOSTDOWN; + case ENODATA: + return Error_ENODATA; + +// #if because these will trigger duplicate case label warnings when +// they have the same value, which is permitted by POSIX and common. +#if EOPNOTSUPP != ENOTSUP + case EOPNOTSUPP: + return Error_EOPNOTSUPP; +#endif +#if EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: + return Error_EWOULDBLOCK; +#endif + } + + return Error_ENONSTANDARD; +} + +inline static int32_t ConvertErrorPalToPlatform(int32_t error) +{ + switch (error) + { + case Error_SUCCESS: + return 0; + case Error_E2BIG: + return E2BIG; + case Error_EACCES: + return EACCES; + case Error_EADDRINUSE: + return EADDRINUSE; + case Error_EADDRNOTAVAIL: + return EADDRNOTAVAIL; + case Error_EAFNOSUPPORT: + return EAFNOSUPPORT; + case Error_EAGAIN: + return EAGAIN; + case Error_EALREADY: + return EALREADY; + case Error_EBADF: + return EBADF; + case Error_EBADMSG: + return EBADMSG; + case Error_EBUSY: + return EBUSY; + case Error_ECANCELED: + return ECANCELED; + case Error_ECHILD: + return ECHILD; + case Error_ECONNABORTED: + return ECONNABORTED; + case Error_ECONNREFUSED: + return ECONNREFUSED; + case Error_ECONNRESET: + return ECONNRESET; + case Error_EDEADLK: + return EDEADLK; + case Error_EDESTADDRREQ: + return EDESTADDRREQ; + case Error_EDOM: + return EDOM; + case Error_EDQUOT: + return EDQUOT; + case Error_EEXIST: + return EEXIST; + case Error_EFAULT: + return EFAULT; + case Error_EFBIG: + return EFBIG; + case Error_EHOSTUNREACH: + return EHOSTUNREACH; + case Error_EIDRM: + return EIDRM; + case Error_EILSEQ: + return EILSEQ; + case Error_EINPROGRESS: + return EINPROGRESS; + case Error_EINTR: + return EINTR; + case Error_EINVAL: + return EINVAL; + case Error_EIO: + return EIO; + case Error_EISCONN: + return EISCONN; + case Error_EISDIR: + return EISDIR; + case Error_ELOOP: + return ELOOP; + case Error_EMFILE: + return EMFILE; + case Error_EMLINK: + return EMLINK; + case Error_EMSGSIZE: + return EMSGSIZE; + case Error_EMULTIHOP: + return EMULTIHOP; + case Error_ENAMETOOLONG: + return ENAMETOOLONG; + case Error_ENETDOWN: + return ENETDOWN; + case Error_ENETRESET: + return ENETRESET; + case Error_ENETUNREACH: + return ENETUNREACH; + case Error_ENFILE: + return ENFILE; + case Error_ENOBUFS: + return ENOBUFS; + case Error_ENODEV: + return ENODEV; + case Error_ENOENT: + return ENOENT; + case Error_ENOEXEC: + return ENOEXEC; + case Error_ENOLCK: + return ENOLCK; + case Error_ENOLINK: + return ENOLINK; + case Error_ENOMEM: + return ENOMEM; + case Error_ENOMSG: + return ENOMSG; + case Error_ENOPROTOOPT: + return ENOPROTOOPT; + case Error_ENOSPC: + return ENOSPC; + case Error_ENOSYS: + return ENOSYS; + case Error_ENOTCONN: + return ENOTCONN; + case Error_ENOTDIR: + return ENOTDIR; + case Error_ENOTEMPTY: + return ENOTEMPTY; +#ifdef ENOTRECOVERABLE // not available in NetBSD + case Error_ENOTRECOVERABLE: + return ENOTRECOVERABLE; +#endif + case Error_ENOTSOCK: + return ENOTSOCK; + case Error_ENOTSUP: + return ENOTSUP; + case Error_ENOTTY: + return ENOTTY; + case Error_ENXIO: + return ENXIO; + case Error_EOVERFLOW: + return EOVERFLOW; +#ifdef EOWNERDEAD // not available in NetBSD + case Error_EOWNERDEAD: + return EOWNERDEAD; +#endif + case Error_EPERM: + return EPERM; + case Error_EPIPE: + return EPIPE; + case Error_EPROTO: + return EPROTO; + case Error_EPROTONOSUPPORT: + return EPROTONOSUPPORT; + case Error_EPROTOTYPE: + return EPROTOTYPE; + case Error_ERANGE: + return ERANGE; + case Error_EROFS: + return EROFS; + case Error_ESPIPE: + return ESPIPE; + case Error_ESRCH: + return ESRCH; + case Error_ESTALE: + return ESTALE; + case Error_ETIMEDOUT: + return ETIMEDOUT; + case Error_ETXTBSY: + return ETXTBSY; + case Error_EXDEV: + return EXDEV; + case Error_EPFNOSUPPORT: + return EPFNOSUPPORT; +#ifdef ESOCKTNOSUPPORT + case Error_ESOCKTNOSUPPORT: + return ESOCKTNOSUPPORT; +#endif + case Error_ESHUTDOWN: + return ESHUTDOWN; + case Error_EHOSTDOWN: + return EHOSTDOWN; + case Error_ENODATA: + return ENODATA; + case Error_EHOSTNOTFOUND: + return -(Error_EHOSTNOTFOUND); + case Error_ENONSTANDARD: + break; // fall through to assert + } + + // We should not use this function to round-trip platform -> pal + // -> platform. It's here only to synthesize a platform number + // from the fixed set above. Note that the assert is outside the + // switch rather than in a default case block because not + // having a default will trigger a warning (as error) if there's + // an enum value we haven't handled. Should that trigger, make + // note that there is probably a corresponding missing case in the + // other direction above, but the compiler can't warn in that case + // because the platform values are not part of an enum. + assert_err(false, "Unknown error code", (int) error); + return -1; +} + +static int32_t ConvertErrorPalToGai(int32_t error) +{ + switch (error) + { + case -(Error_EHOSTNOTFOUND): + return EAI_NONAME; + } + // Fall-through for unknown codes. gai_strerror() will handle that. + + return error; +} + + + +inline static const char* StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize) +{ + assert(buffer != NULL); + assert(bufferSize > 0); + + if (bufferSize < 0) + return NULL; + + if (platformErrno < 0) + { + // Not a system error + SafeStringCopy(buffer, (size_t)bufferSize, gai_strerror(ConvertErrorPalToGai(platformErrno))); + return buffer; + } + +// Note that we must use strerror_r because plain strerror is not +// thread-safe. +// +// However, there are two versions of strerror_r: +// - GNU: char* strerror_r(int, char*, size_t); +// - POSIX: int strerror_r(int, char*, size_t); +// +// The former may or may not use the supplied buffer, and returns +// the error message string. The latter stores the error message +// string into the supplied buffer and returns an error code. + +#if HAVE_GNU_STRERROR_R + const char* message = strerror_r(platformErrno, buffer, (uint32_t) bufferSize); + assert(message != NULL); + return message; +#else + int error = strerror_r(platformErrno, buffer, (uint32_t) bufferSize); + if (error == ERANGE) + { + // Buffer is too small to hold the entire message, but has + // still been filled to the extent possible and null-terminated. + return NULL; + } + + // The only other valid error codes are 0 for success or EINVAL for + // an unknown error, but in the latter case a reasonable string (e.g + // "Unknown error: 0x123") is returned. + assert_err(error == 0 || error == EINVAL, "invalid error", error); + return buffer; +#endif +} diff --git a/src/libraries/Native/Unix/Common/pal_io_common.h b/src/libraries/Native/Unix/Common/pal_io_common.h new file mode 100644 index 0000000000000..15bf1423aa327 --- /dev/null +++ b/src/libraries/Native/Unix/Common/pal_io_common.h @@ -0,0 +1,189 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include + +/** + * Our intermediate pollfd struct to normalize the data types + */ +typedef struct +{ + int32_t FileDescriptor; // The file descriptor to poll + int16_t Events; // The events to poll for + int16_t TriggeredEvents; // The events that triggered the poll +} PollEvent; + +/** + * Constants passed to and from poll describing what to poll for and what + * kind of data was received from poll. + */ +typedef enum +{ + PAL_POLLIN = 0x0001, /* non-urgent readable data available */ + PAL_POLLPRI = 0x0002, /* urgent readable data available */ + PAL_POLLOUT = 0x0004, /* data can be written without blocked */ + PAL_POLLERR = 0x0008, /* an error occurred */ + PAL_POLLHUP = 0x0010, /* the file descriptor hung up */ + PAL_POLLNVAL = 0x0020, /* the requested events were invalid */ +} PollEvents; + +inline static int32_t Common_Read(intptr_t fd, void* buffer, int32_t bufferSize) +{ + assert(buffer != NULL || bufferSize == 0); + assert(bufferSize >= 0); + + if (bufferSize < 0) + { + errno = EINVAL; + return -1; + } + + ssize_t count; + while ((count = read(ToFileDescriptor(fd), buffer, (uint32_t)bufferSize)) < 0 && errno == EINTR); + + assert(count >= -1 && count <= bufferSize); + return (int32_t)count; +} + +inline static int32_t Common_Write(intptr_t fd, const void* buffer, int32_t bufferSize) +{ + assert(buffer != NULL || bufferSize == 0); + assert(bufferSize >= 0); + + if (bufferSize < 0) + { + errno = ERANGE; + return -1; + } + + ssize_t count; + while ((count = write(ToFileDescriptor(fd), buffer, (uint32_t)bufferSize)) < 0 && errno == EINTR); + + assert(count >= -1 && count <= bufferSize); + return (int32_t)count; +} + +inline static int32_t Common_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered) +{ + if (pollEvents == NULL || triggered == NULL) + { + return Error_EFAULT; + } + + if (milliseconds < -1) + { + return Error_EINVAL; + } + + struct pollfd stackBuffer[(uint32_t)(2048/sizeof(struct pollfd))]; + int useStackBuffer = eventCount <= ARRAY_SIZE(stackBuffer); + struct pollfd* pollfds = NULL; + if (useStackBuffer) + { + pollfds = &stackBuffer[0]; + } + else + { + pollfds = calloc(eventCount, sizeof(*pollfds)); + if (pollfds == NULL) + { + return Error_ENOMEM; + } + } + + for (uint32_t i = 0; i < eventCount; i++) + { + const PollEvent* event = &pollEvents[i]; + pollfds[i].fd = event->FileDescriptor; + // we need to do this for platforms like AIX where PAL_POLL* doesn't + // match up to their reality; this is PollEvent -> system polling + switch (event->Events) + { + case PAL_POLLIN: + pollfds[i].events = POLLIN; + break; + case PAL_POLLPRI: + pollfds[i].events = POLLPRI; + break; + case PAL_POLLOUT: + pollfds[i].events = POLLOUT; + break; + case PAL_POLLERR: + pollfds[i].events = POLLERR; + break; + case PAL_POLLHUP: + pollfds[i].events = POLLHUP; + break; + case PAL_POLLNVAL: + pollfds[i].events = POLLNVAL; + break; + default: + pollfds[i].events = event->Events; + break; + } + pollfds[i].revents = 0; + } + + int rv; + while ((rv = poll(pollfds, (nfds_t)eventCount, milliseconds)) < 0 && errno == EINTR); + + if (rv < 0) + { + if (!useStackBuffer) + { + free(pollfds); + } + + *triggered = 0; + return ConvertErrorPlatformToPal(errno); + } + + for (uint32_t i = 0; i < eventCount; i++) + { + const struct pollfd* pfd = &pollfds[i]; + assert(pfd->fd == pollEvents[i].FileDescriptor); + assert(pfd->events == pollEvents[i].Events); + + // same as the other switch, just system -> PollEvent + switch (pfd->revents) + { + case POLLIN: + pollEvents[i].TriggeredEvents = PAL_POLLIN; + break; + case POLLPRI: + pollEvents[i].TriggeredEvents = PAL_POLLPRI; + break; + case POLLOUT: + pollEvents[i].TriggeredEvents = PAL_POLLOUT; + break; + case POLLERR: + pollEvents[i].TriggeredEvents = PAL_POLLERR; + break; + case POLLHUP: + pollEvents[i].TriggeredEvents = PAL_POLLHUP; + break; + case POLLNVAL: + pollEvents[i].TriggeredEvents = PAL_POLLNVAL; + break; + default: + pollEvents[i].TriggeredEvents = (int16_t)pfd->revents; + break; + } + } + + *triggered = (uint32_t)rv; + + if (!useStackBuffer) + { + free(pollfds); + } + + return Error_SUCCESS; +} diff --git a/src/libraries/Native/Unix/Common/pal_networking_common.h b/src/libraries/Native/Unix/Common/pal_networking_common.h new file mode 100644 index 0000000000000..353862cd7ce0d --- /dev/null +++ b/src/libraries/Native/Unix/Common/pal_networking_common.h @@ -0,0 +1,47 @@ +// 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. + +#pragma once + +#include +#include + +/* + * Socket shutdown modes. + * + * NOTE: these values are taken from System.Net.SocketShutdown. + */ +typedef enum +{ + SocketShutdown_SHUT_READ = 0, // SHUT_RD + SocketShutdown_SHUT_WRITE = 1, // SHUT_WR + SocketShutdown_SHUT_BOTH = 2, // SHUT_RDWR +} SockerShutdown; + +inline static int32_t Common_Shutdown(intptr_t socket, int32_t socketShutdown) +{ + int fd = ToFileDescriptor(socket); + + int how; + switch (socketShutdown) + { + case SocketShutdown_SHUT_READ: + how = SHUT_RD; + break; + + case SocketShutdown_SHUT_WRITE: + how = SHUT_WR; + break; + + case SocketShutdown_SHUT_BOTH: + how = SHUT_RDWR; + break; + + default: + return Error_EINVAL; + } + + int err = shutdown(fd, how); + return err == 0 ? Error_SUCCESS : ConvertErrorPlatformToPal(errno); +} diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c index 1a594c461c0ed..7fa6dd6fd8ac1 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c @@ -3,6 +3,9 @@ // See the LICENSE file in the project root for more information. // +#include +#include "pal_icushim_internal.h" + #if defined(TARGET_UNIX) #include #elif defined(TARGET_WINDOWS) @@ -10,12 +13,10 @@ #include #include #endif -#include #include #include #include -#include "pal_icushim_internal.h" #include "pal_icushim.h" // Define pointers to all the used ICU functions @@ -431,10 +432,23 @@ void GlobalizationNative_InitICUFunctions(void* icuuc, void* icuin, const char* char symbolVersion[MaxICUVersionStringWithSuffixLength + 1]=""; char symbolSuffix[SYMBOL_CUSTOM_SUFFIX_SIZE]=""; + if (strlen(version) > (size_t)MaxICUVersionStringLength) + { + fprintf(stderr, "The resolved version \"%s\" from System.Globalization.AppLocalIcu switch has to be < %zu chars long.\n", version, (size_t)MaxICUVersionStringLength); + abort(); + } + sscanf(version, "%d.%d.%d", &major, &minor, &build); if (suffix != NULL) { + size_t suffixAllowedSize = SYMBOL_CUSTOM_SUFFIX_SIZE - 2; // SYMBOL_CUSTOM_SUFFIX_SIZE considers `_` and `\0`. + if (strlen(suffix) > suffixAllowedSize) + { + fprintf(stderr, "The resolved suffix \"%s\" from System.Globalization.AppLocalIcu switch has to be < %zu chars long.\n", suffix, suffixAllowedSize); + abort(); + } + assert(strlen(suffix) + 1 <= SYMBOL_CUSTOM_SUFFIX_SIZE); #if defined(TARGET_WINDOWS) diff --git a/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt index 3315941e1aceb..602d6a3989715 100644 --- a/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt @@ -1,10 +1,12 @@ project(System.IO.Compression.Native C) -if (CLR_CMAKE_TARGET_ARCH_WASM) +if (CLR_CMAKE_TARGET_BROWSER) add_definitions(-s USE_ZLIB) elseif (CLR_CMAKE_TARGET_ANDROID) # need special case here since we want to link against libz.so but find_package() would resolve libz.a set(ZLIB_LIBRARIES z) +elseif (CLR_CMAKE_TARGET_SUNOS) + set(ZLIB_LIBRARIES z m) else () find_package(ZLIB REQUIRED) endif () diff --git a/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.c b/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.c index cca1c53aa63e0..4a4babd185448 100644 --- a/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.c +++ b/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.c @@ -10,6 +10,14 @@ #include #include #include +#include +#include +#include + +// ENODATA is not defined in FreeBSD 10.3 but is defined in 11.0 +#if defined(__FreeBSD__) & !defined(ENODATA) +#define ENODATA ENOATTR +#endif /* Open device file in non-blocking mode and without controlling terminal */ intptr_t SystemIoPortsNative_SerialPortOpen(const char * name) @@ -44,3 +52,38 @@ int SystemIoPortsNative_SerialPortClose(intptr_t handle) ioctl(fd, TIOCNXCL); return close(fd); } + +int32_t SystemIoPortsNative_Read(intptr_t fd, void* buffer, int32_t bufferSize) +{ + return Common_Read(fd, buffer, bufferSize); +} + +int32_t SystemIoPortsNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize) +{ + return Common_Write(fd, buffer, bufferSize); +} + +int32_t SystemIoPortsNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered) +{ + return Common_Poll(pollEvents, eventCount, milliseconds, triggered); +} + +int32_t SystemIoPortsNative_Shutdown(intptr_t socket, int32_t socketShutdown) +{ + return Common_Shutdown(socket, socketShutdown); +} + +int32_t SystemIoPortsNative_ConvertErrorPlatformToPal(int32_t platformErrno) +{ + return ConvertErrorPlatformToPal(platformErrno); +} + +int32_t SystemIoPortsNative_ConvertErrorPalToPlatform(int32_t error) +{ + return ConvertErrorPalToPlatform(error); +} + +const char* SystemIoPortsNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize) +{ + return StrErrorR(platformErrno, buffer, bufferSize); +} diff --git a/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.h b/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.h index 3d35b8186ed89..371ceba0e8f70 100644 --- a/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.h +++ b/src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.h @@ -2,8 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#include "pal_types.h" -#include "pal_compiler.h" +#include PALEXPORT intptr_t SystemIoPortsNative_SerialPortOpen(const char * name); PALEXPORT int SystemIoPortsNative_SerialPortClose(intptr_t fd); +PALEXPORT int32_t SystemIoPortsNative_Read(intptr_t fd, void* buffer, int32_t bufferSize); +PALEXPORT int32_t SystemIoPortsNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize); +PALEXPORT int32_t SystemIoPortsNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered); +PALEXPORT int32_t SystemIoPortsNative_Shutdown(intptr_t socket, int32_t socketShutdown); +PALEXPORT int32_t SystemIoPortsNative_ConvertErrorPlatformToPal(int32_t platformErrno); +PALEXPORT int32_t SystemIoPortsNative_ConvertErrorPalToPlatform(int32_t error); +PALEXPORT const char* SystemIoPortsNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize); diff --git a/src/libraries/Native/Unix/System.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.Native/CMakeLists.txt index e3bf2532b3ae5..e72161d0ee77e 100644 --- a/src/libraries/Native/Unix/System.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Native/CMakeLists.txt @@ -30,7 +30,7 @@ else () set(NATIVE_SOURCES ${NATIVE_SOURCES} pal_console.c) endif () -if (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ARCH_WASM) +if (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_BROWSER) set(NATIVE_SOURCES ${NATIVE_SOURCES} pal_networkchange.c) if (!HAVE_LINUX_RTNETLINK_H) @@ -52,14 +52,14 @@ if (GEN_SHARED_LIB) ) if (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID) target_link_libraries(System.Native rt) - endif () - - if (CLR_CMAKE_TARGET_FREEBSD) + elseif (CLR_CMAKE_TARGET_FREEBSD) target_link_libraries(System.Native pthread) if (HAVE_INOTIFY) find_library(INOTIFY_LIBRARY inotify HINTS /usr/local/lib) target_link_libraries(System.Native ${INOTIFY_LIBRARY}) endif () + elseif (CLR_CMAKE_TARGET_SUNOS) + target_link_libraries(System.Native socket) endif () install_with_stripped_symbols (System.Native PROGRAMS .) endif () diff --git a/src/libraries/Native/Unix/System.Native/pal_errno.c b/src/libraries/Native/Unix/System.Native/pal_errno.c index d3bfde6d2f97e..b0da1ec1f548e 100644 --- a/src/libraries/Native/Unix/System.Native/pal_errno.c +++ b/src/libraries/Native/Unix/System.Native/pal_errno.c @@ -2,459 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#include "pal_config.h" #include "pal_errno.h" -#include "pal_utilities.h" - -#include -#include - -// ENODATA is not defined in FreeBSD 10.3 but is defined in 11.0 -#if defined(__FreeBSD__) & !defined(ENODATA) -#define ENODATA ENOATTR -#endif - -#include -#include int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno) { - switch (platformErrno) - { - case 0: - return Error_SUCCESS; - case E2BIG: - return Error_E2BIG; - case EACCES: - return Error_EACCES; - case EADDRINUSE: - return Error_EADDRINUSE; - case EADDRNOTAVAIL: - return Error_EADDRNOTAVAIL; - case EAFNOSUPPORT: - return Error_EAFNOSUPPORT; - case EAGAIN: - return Error_EAGAIN; - case EALREADY: - return Error_EALREADY; - case EBADF: - return Error_EBADF; - case EBADMSG: - return Error_EBADMSG; - case EBUSY: - return Error_EBUSY; - case ECANCELED: - return Error_ECANCELED; - case ECHILD: - return Error_ECHILD; - case ECONNABORTED: - return Error_ECONNABORTED; - case ECONNREFUSED: - return Error_ECONNREFUSED; - case ECONNRESET: - return Error_ECONNRESET; - case EDEADLK: - return Error_EDEADLK; - case EDESTADDRREQ: - return Error_EDESTADDRREQ; - case EDOM: - return Error_EDOM; - case EDQUOT: - return Error_EDQUOT; - case EEXIST: - return Error_EEXIST; - case EFAULT: - return Error_EFAULT; - case EFBIG: - return Error_EFBIG; - case EHOSTUNREACH: - return Error_EHOSTUNREACH; - case EIDRM: - return Error_EIDRM; - case EILSEQ: - return Error_EILSEQ; - case EINPROGRESS: - return Error_EINPROGRESS; - case EINTR: - return Error_EINTR; - case EINVAL: - return Error_EINVAL; - case EIO: - return Error_EIO; - case EISCONN: - return Error_EISCONN; - case EISDIR: - return Error_EISDIR; - case ELOOP: - return Error_ELOOP; - case EMFILE: - return Error_EMFILE; - case EMLINK: - return Error_EMLINK; - case EMSGSIZE: - return Error_EMSGSIZE; - case EMULTIHOP: - return Error_EMULTIHOP; - case ENAMETOOLONG: - return Error_ENAMETOOLONG; - case ENETDOWN: - return Error_ENETDOWN; - case ENETRESET: - return Error_ENETRESET; - case ENETUNREACH: - return Error_ENETUNREACH; - case ENFILE: - return Error_ENFILE; - case ENOBUFS: - return Error_ENOBUFS; - case ENODEV: - return Error_ENODEV; - case ENOENT: - return Error_ENOENT; - case ENOEXEC: - return Error_ENOEXEC; - case ENOLCK: - return Error_ENOLCK; - case ENOLINK: - return Error_ENOLINK; - case ENOMEM: - return Error_ENOMEM; - case ENOMSG: - return Error_ENOMSG; - case ENOPROTOOPT: - return Error_ENOPROTOOPT; - case ENOSPC: - return Error_ENOSPC; - case ENOSYS: - return Error_ENOSYS; - case ENOTCONN: - return Error_ENOTCONN; - case ENOTDIR: - return Error_ENOTDIR; -#if ENOTEMPTY != EEXIST // AIX defines this - case ENOTEMPTY: - return Error_ENOTEMPTY; -#endif -#ifdef ENOTRECOVERABLE // not available in NetBSD - case ENOTRECOVERABLE: - return Error_ENOTRECOVERABLE; -#endif - case ENOTSOCK: - return Error_ENOTSOCK; - case ENOTSUP: - return Error_ENOTSUP; - case ENOTTY: - return Error_ENOTTY; - case ENXIO: - return Error_ENXIO; - case EOVERFLOW: - return Error_EOVERFLOW; -#ifdef EOWNERDEAD // not available in NetBSD - case EOWNERDEAD: - return Error_EOWNERDEAD; -#endif - case EPERM: - return Error_EPERM; - case EPIPE: - return Error_EPIPE; - case EPROTO: - return Error_EPROTO; - case EPROTONOSUPPORT: - return Error_EPROTONOSUPPORT; - case EPROTOTYPE: - return Error_EPROTOTYPE; - case ERANGE: - return Error_ERANGE; - case EROFS: - return Error_EROFS; - case ESPIPE: - return Error_ESPIPE; - case ESRCH: - return Error_ESRCH; - case ESTALE: - return Error_ESTALE; - case ETIMEDOUT: - return Error_ETIMEDOUT; - case ETXTBSY: - return Error_ETXTBSY; - case EXDEV: - return Error_EXDEV; -#ifdef ESOCKTNOSUPPORT - case ESOCKTNOSUPPORT: - return Error_ESOCKTNOSUPPORT; -#endif - case EPFNOSUPPORT: - return Error_EPFNOSUPPORT; - case ESHUTDOWN: - return Error_ESHUTDOWN; - case EHOSTDOWN: - return Error_EHOSTDOWN; - case ENODATA: - return Error_ENODATA; - -// #if because these will trigger duplicate case label warnings when -// they have the same value, which is permitted by POSIX and common. -#if EOPNOTSUPP != ENOTSUP - case EOPNOTSUPP: - return Error_EOPNOTSUPP; -#endif -#if EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: - return Error_EWOULDBLOCK; -#endif - } - - return Error_ENONSTANDARD; + return ConvertErrorPlatformToPal(platformErrno); } int32_t SystemNative_ConvertErrorPalToPlatform(int32_t error) { - switch (error) - { - case Error_SUCCESS: - return 0; - case Error_E2BIG: - return E2BIG; - case Error_EACCES: - return EACCES; - case Error_EADDRINUSE: - return EADDRINUSE; - case Error_EADDRNOTAVAIL: - return EADDRNOTAVAIL; - case Error_EAFNOSUPPORT: - return EAFNOSUPPORT; - case Error_EAGAIN: - return EAGAIN; - case Error_EALREADY: - return EALREADY; - case Error_EBADF: - return EBADF; - case Error_EBADMSG: - return EBADMSG; - case Error_EBUSY: - return EBUSY; - case Error_ECANCELED: - return ECANCELED; - case Error_ECHILD: - return ECHILD; - case Error_ECONNABORTED: - return ECONNABORTED; - case Error_ECONNREFUSED: - return ECONNREFUSED; - case Error_ECONNRESET: - return ECONNRESET; - case Error_EDEADLK: - return EDEADLK; - case Error_EDESTADDRREQ: - return EDESTADDRREQ; - case Error_EDOM: - return EDOM; - case Error_EDQUOT: - return EDQUOT; - case Error_EEXIST: - return EEXIST; - case Error_EFAULT: - return EFAULT; - case Error_EFBIG: - return EFBIG; - case Error_EHOSTUNREACH: - return EHOSTUNREACH; - case Error_EIDRM: - return EIDRM; - case Error_EILSEQ: - return EILSEQ; - case Error_EINPROGRESS: - return EINPROGRESS; - case Error_EINTR: - return EINTR; - case Error_EINVAL: - return EINVAL; - case Error_EIO: - return EIO; - case Error_EISCONN: - return EISCONN; - case Error_EISDIR: - return EISDIR; - case Error_ELOOP: - return ELOOP; - case Error_EMFILE: - return EMFILE; - case Error_EMLINK: - return EMLINK; - case Error_EMSGSIZE: - return EMSGSIZE; - case Error_EMULTIHOP: - return EMULTIHOP; - case Error_ENAMETOOLONG: - return ENAMETOOLONG; - case Error_ENETDOWN: - return ENETDOWN; - case Error_ENETRESET: - return ENETRESET; - case Error_ENETUNREACH: - return ENETUNREACH; - case Error_ENFILE: - return ENFILE; - case Error_ENOBUFS: - return ENOBUFS; - case Error_ENODEV: - return ENODEV; - case Error_ENOENT: - return ENOENT; - case Error_ENOEXEC: - return ENOEXEC; - case Error_ENOLCK: - return ENOLCK; - case Error_ENOLINK: - return ENOLINK; - case Error_ENOMEM: - return ENOMEM; - case Error_ENOMSG: - return ENOMSG; - case Error_ENOPROTOOPT: - return ENOPROTOOPT; - case Error_ENOSPC: - return ENOSPC; - case Error_ENOSYS: - return ENOSYS; - case Error_ENOTCONN: - return ENOTCONN; - case Error_ENOTDIR: - return ENOTDIR; - case Error_ENOTEMPTY: - return ENOTEMPTY; -#ifdef ENOTRECOVERABLE // not available in NetBSD - case Error_ENOTRECOVERABLE: - return ENOTRECOVERABLE; -#endif - case Error_ENOTSOCK: - return ENOTSOCK; - case Error_ENOTSUP: - return ENOTSUP; - case Error_ENOTTY: - return ENOTTY; - case Error_ENXIO: - return ENXIO; - case Error_EOVERFLOW: - return EOVERFLOW; -#ifdef EOWNERDEAD // not available in NetBSD - case Error_EOWNERDEAD: - return EOWNERDEAD; -#endif - case Error_EPERM: - return EPERM; - case Error_EPIPE: - return EPIPE; - case Error_EPROTO: - return EPROTO; - case Error_EPROTONOSUPPORT: - return EPROTONOSUPPORT; - case Error_EPROTOTYPE: - return EPROTOTYPE; - case Error_ERANGE: - return ERANGE; - case Error_EROFS: - return EROFS; - case Error_ESPIPE: - return ESPIPE; - case Error_ESRCH: - return ESRCH; - case Error_ESTALE: - return ESTALE; - case Error_ETIMEDOUT: - return ETIMEDOUT; - case Error_ETXTBSY: - return ETXTBSY; - case Error_EXDEV: - return EXDEV; - case Error_EPFNOSUPPORT: - return EPFNOSUPPORT; -#ifdef ESOCKTNOSUPPORT - case Error_ESOCKTNOSUPPORT: - return ESOCKTNOSUPPORT; -#endif - case Error_ESHUTDOWN: - return ESHUTDOWN; - case Error_EHOSTDOWN: - return EHOSTDOWN; - case Error_ENODATA: - return ENODATA; - case Error_EHOSTNOTFOUND: - return -(Error_EHOSTNOTFOUND); - case Error_ENONSTANDARD: - break; // fall through to assert - } - - // We should not use this function to round-trip platform -> pal - // -> platform. It's here only to synthesize a platform number - // from the fixed set above. Note that the assert is outside the - // switch rather than in a default case block because not - // having a default will trigger a warning (as error) if there's - // an enum value we haven't handled. Should that trigger, make - // note that there is probably a corresponding missing case in the - // other direction above, but the compiler can't warn in that case - // because the platform values are not part of an enum. - assert_err(false, "Unknown error code", (int) error); - return -1; + return ConvertErrorPalToPlatform(error); } -static int32_t SystemNative_ConvertErrorPalToGai(int32_t error) -{ - switch (error) - { - case -(Error_EHOSTNOTFOUND): - return EAI_NONAME; - } - // Fall-through for unknown codes. gai_strerror() will handle that. - - return error; -} - - - const char* SystemNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize) { - assert(buffer != NULL); - assert(bufferSize > 0); - - if (bufferSize < 0) - return NULL; - - if (platformErrno < 0) - { - // Not a system error - SafeStringCopy(buffer, (size_t)bufferSize, gai_strerror(SystemNative_ConvertErrorPalToGai(platformErrno))); - return buffer; - } - -// Note that we must use strerror_r because plain strerror is not -// thread-safe. -// -// However, there are two versions of strerror_r: -// - GNU: char* strerror_r(int, char*, size_t); -// - POSIX: int strerror_r(int, char*, size_t); -// -// The former may or may not use the supplied buffer, and returns -// the error message string. The latter stores the error message -// string into the supplied buffer and returns an error code. - -#if HAVE_GNU_STRERROR_R - const char* message = strerror_r(platformErrno, buffer, (uint32_t) bufferSize); - assert(message != NULL); - return message; -#else - int error = strerror_r(platformErrno, buffer, (uint32_t) bufferSize); - if (error == ERANGE) - { - // Buffer is too small to hold the entire message, but has - // still been filled to the extent possible and null-terminated. - return NULL; - } - - // The only other valid error codes are 0 for success or EINVAL for - // an unknown error, but in the latter case a reasonable string (e.g - // "Unknown error: 0x123") is returned. - assert_err(error == 0 || error == EINVAL, "invalid error", error); - return buffer; -#endif + return StrErrorR(platformErrno, buffer, bufferSize); } diff --git a/src/libraries/Native/Unix/System.Native/pal_errno.h b/src/libraries/Native/Unix/System.Native/pal_errno.h index c4ba9ccd6e508..f73fe707c59fb 100644 --- a/src/libraries/Native/Unix/System.Native/pal_errno.h +++ b/src/libraries/Native/Unix/System.Native/pal_errno.h @@ -4,127 +4,7 @@ #pragma once -#include "pal_compiler.h" -#include "pal_types.h" - -/** - * Error codes returned via ConvertErrno. - * - * Only the names (without the PAL_ prefix) are specified by POSIX. - * - * The values chosen below are simply assigned arbitrarily (originally - * in alphabetical order they appear in the spec, but they can't change so - * add new values to the end!). - * - * Also, the values chosen are deliberately outside the range of - * typical UNIX errnos (small numbers), HRESULTs (negative for errors) - * and Win32 errors (0x0000 - 0xFFFF). This isn't required for - * correctness, but may help debug a caller that is interpreting a raw - * int incorrectly. - * - * Wherever the spec says "x may be the same value as y", we do use - * the same value so that callers cannot not take a dependency on - * being able to distinguish between them. - */ -typedef enum -{ - Error_SUCCESS = 0, - - Error_E2BIG = 0x10001, // Argument list too long. - Error_EACCES = 0x10002, // Permission denied. - Error_EADDRINUSE = 0x10003, // Address in use. - Error_EADDRNOTAVAIL = 0x10004, // Address not available. - Error_EAFNOSUPPORT = 0x10005, // Address family not supported. - Error_EAGAIN = 0x10006, // Resource unavailable, try again (same value as EWOULDBLOCK), - Error_EALREADY = 0x10007, // Connection already in progress. - Error_EBADF = 0x10008, // Bad file descriptor. - Error_EBADMSG = 0x10009, // Bad message. - Error_EBUSY = 0x1000A, // Device or resource busy. - Error_ECANCELED = 0x1000B, // Operation canceled. - Error_ECHILD = 0x1000C, // No child processes. - Error_ECONNABORTED = 0x1000D, // Connection aborted. - Error_ECONNREFUSED = 0x1000E, // Connection refused. - Error_ECONNRESET = 0x1000F, // Connection reset. - Error_EDEADLK = 0x10010, // Resource deadlock would occur. - Error_EDESTADDRREQ = 0x10011, // Destination address required. - Error_EDOM = 0x10012, // Mathematics argument out of domain of function. - Error_EDQUOT = 0x10013, // Reserved. - Error_EEXIST = 0x10014, // File exists. - Error_EFAULT = 0x10015, // Bad address. - Error_EFBIG = 0x10016, // File too large. - Error_EHOSTUNREACH = 0x10017, // Host is unreachable. - Error_EIDRM = 0x10018, // Identifier removed. - Error_EILSEQ = 0x10019, // Illegal byte sequence. - Error_EINPROGRESS = 0x1001A, // Operation in progress. - Error_EINTR = 0x1001B, // Interrupted function. - Error_EINVAL = 0x1001C, // Invalid argument. - Error_EIO = 0x1001D, // I/O error. - Error_EISCONN = 0x1001E, // Socket is connected. - Error_EISDIR = 0x1001F, // Is a directory. - Error_ELOOP = 0x10020, // Too many levels of symbolic links. - Error_EMFILE = 0x10021, // File descriptor value too large. - Error_EMLINK = 0x10022, // Too many links. - Error_EMSGSIZE = 0x10023, // Message too large. - Error_EMULTIHOP = 0x10024, // Reserved. - Error_ENAMETOOLONG = 0x10025, // Filename too long. - Error_ENETDOWN = 0x10026, // Network is down. - Error_ENETRESET = 0x10027, // Connection aborted by network. - Error_ENETUNREACH = 0x10028, // Network unreachable. - Error_ENFILE = 0x10029, // Too many files open in system. - Error_ENOBUFS = 0x1002A, // No buffer space available. - Error_ENODEV = 0x1002C, // No such device. - Error_ENOENT = 0x1002D, // No such file or directory. - Error_ENOEXEC = 0x1002E, // Executable file format error. - Error_ENOLCK = 0x1002F, // No locks available. - Error_ENOLINK = 0x10030, // Reserved. - Error_ENOMEM = 0x10031, // Not enough space. - Error_ENOMSG = 0x10032, // No message of the desired type. - Error_ENOPROTOOPT = 0x10033, // Protocol not available. - Error_ENOSPC = 0x10034, // No space left on device. - Error_ENOSYS = 0x10037, // Function not supported. - Error_ENOTCONN = 0x10038, // The socket is not connected. - Error_ENOTDIR = 0x10039, // Not a directory or a symbolic link to a directory. - Error_ENOTEMPTY = 0x1003A, // Directory not empty. - Error_ENOTRECOVERABLE = 0x1003B, // State not recoverable. - Error_ENOTSOCK = 0x1003C, // Not a socket. - Error_ENOTSUP = 0x1003D, // Not supported (same value as EOPNOTSUP). - Error_ENOTTY = 0x1003E, // Inappropriate I/O control operation. - Error_ENXIO = 0x1003F, // No such device or address. - Error_EOVERFLOW = 0x10040, // Value too large to be stored in data type. - Error_EOWNERDEAD = 0x10041, // Previous owner died. - Error_EPERM = 0x10042, // Operation not permitted. - Error_EPIPE = 0x10043, // Broken pipe. - Error_EPROTO = 0x10044, // Protocol error. - Error_EPROTONOSUPPORT = 0x10045, // Protocol not supported. - Error_EPROTOTYPE = 0x10046, // Protocol wrong type for socket. - Error_ERANGE = 0x10047, // Result too large. - Error_EROFS = 0x10048, // Read-only file system. - Error_ESPIPE = 0x10049, // Invalid seek. - Error_ESRCH = 0x1004A, // No such process. - Error_ESTALE = 0x1004B, // Reserved. - Error_ETIMEDOUT = 0x1004D, // Connection timed out. - Error_ETXTBSY = 0x1004E, // Text file busy. - Error_EXDEV = 0x1004F, // Cross-device link. - Error_ESOCKTNOSUPPORT = 0x1005E, // Socket type not supported. - Error_EPFNOSUPPORT = 0x10060, // Protocol family not supported. - Error_ESHUTDOWN = 0x1006C, // Socket shutdown. - Error_EHOSTDOWN = 0x10070, // Host is down. - Error_ENODATA = 0x10071, // No data available. - - // Error codes to track errors beyond kernel. - Error_EHOSTNOTFOUND = 0x20001, // Name lookup failed. - - // POSIX permits these to have the same value and we make them - // always equal so that we cannot introduce a dependency on - // distinguishing between them that would not work on all - // platforms. - Error_EOPNOTSUPP = Error_ENOTSUP, // Operation not supported on socket - Error_EWOULDBLOCK = Error_EAGAIN, // Operation would block - - // This one is not part of POSIX, but is a catch-all for the case - // where we cannot convert the raw errno value to something above. - Error_ENONSTANDARD = 0x1FFFF, -} Error; +#include /** * Converts the given raw numeric value obtained via errno -> diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 4c5af27593cb2..ccae4e87c9756 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -921,120 +920,7 @@ int32_t SystemNative_FTruncate(intptr_t fd, int64_t length) int32_t SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered) { - if (pollEvents == NULL || triggered == NULL) - { - return Error_EFAULT; - } - - if (milliseconds < -1) - { - return Error_EINVAL; - } - - struct pollfd stackBuffer[(uint32_t)(2048/sizeof(struct pollfd))]; - int useStackBuffer = eventCount <= ARRAY_SIZE(stackBuffer); - struct pollfd* pollfds = NULL; - if (useStackBuffer) - { - pollfds = &stackBuffer[0]; - } - else - { - pollfds = calloc(eventCount, sizeof(*pollfds)); - if (pollfds == NULL) - { - return Error_ENOMEM; - } - } - - for (uint32_t i = 0; i < eventCount; i++) - { - const PollEvent* event = &pollEvents[i]; - pollfds[i].fd = event->FileDescriptor; - // we need to do this for platforms like AIX where PAL_POLL* doesn't - // match up to their reality; this is PollEvent -> system polling - switch (event->Events) - { - case PAL_POLLIN: - pollfds[i].events = POLLIN; - break; - case PAL_POLLPRI: - pollfds[i].events = POLLPRI; - break; - case PAL_POLLOUT: - pollfds[i].events = POLLOUT; - break; - case PAL_POLLERR: - pollfds[i].events = POLLERR; - break; - case PAL_POLLHUP: - pollfds[i].events = POLLHUP; - break; - case PAL_POLLNVAL: - pollfds[i].events = POLLNVAL; - break; - default: - pollfds[i].events = event->Events; - break; - } - pollfds[i].revents = 0; - } - - int rv; - while ((rv = poll(pollfds, (nfds_t)eventCount, milliseconds)) < 0 && errno == EINTR); - - if (rv < 0) - { - if (!useStackBuffer) - { - free(pollfds); - } - - *triggered = 0; - return SystemNative_ConvertErrorPlatformToPal(errno); - } - - for (uint32_t i = 0; i < eventCount; i++) - { - const struct pollfd* pfd = &pollfds[i]; - assert(pfd->fd == pollEvents[i].FileDescriptor); - assert(pfd->events == pollEvents[i].Events); - - // same as the other switch, just system -> PollEvent - switch (pfd->revents) - { - case POLLIN: - pollEvents[i].TriggeredEvents = PAL_POLLIN; - break; - case POLLPRI: - pollEvents[i].TriggeredEvents = PAL_POLLPRI; - break; - case POLLOUT: - pollEvents[i].TriggeredEvents = PAL_POLLOUT; - break; - case POLLERR: - pollEvents[i].TriggeredEvents = PAL_POLLERR; - break; - case POLLHUP: - pollEvents[i].TriggeredEvents = PAL_POLLHUP; - break; - case POLLNVAL: - pollEvents[i].TriggeredEvents = PAL_POLLNVAL; - break; - default: - pollEvents[i].TriggeredEvents = (int16_t)pfd->revents; - break; - } - } - - *triggered = (uint32_t)rv; - - if (!useStackBuffer) - { - free(pollfds); - } - - return Error_SUCCESS; + return Common_Poll(pollEvents, eventCount, milliseconds, triggered); } int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, int32_t advice) @@ -1085,20 +971,7 @@ char* SystemNative_GetLine(FILE* stream) int32_t SystemNative_Read(intptr_t fd, void* buffer, int32_t bufferSize) { - assert(buffer != NULL || bufferSize == 0); - assert(bufferSize >= 0); - - if (bufferSize < 0) - { - errno = EINVAL; - return -1; - } - - ssize_t count; - while ((count = read(ToFileDescriptor(fd), buffer, (uint32_t)bufferSize)) < 0 && errno == EINTR); - - assert(count >= -1 && count <= bufferSize); - return (int32_t)count; + return Common_Read(fd, buffer, bufferSize); } int32_t SystemNative_ReadLink(const char* path, char* buffer, int32_t bufferSize) @@ -1139,20 +1012,7 @@ void SystemNative_Sync(void) int32_t SystemNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize) { - assert(buffer != NULL || bufferSize == 0); - assert(bufferSize >= 0); - - if (bufferSize < 0) - { - errno = ERANGE; - return -1; - } - - ssize_t count; - while ((count = write(ToFileDescriptor(fd), buffer, (uint32_t)bufferSize)) < 0 && errno == EINTR); - - assert(count >= -1 && count <= bufferSize); - return (int32_t)count; + return Common_Write(fd, buffer, bufferSize); } // Read all data from inFd and write it to outFd @@ -1420,7 +1280,7 @@ int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid) // ucred causes Emscripten to fail even though it's defined, // but getting peer credentials won't work for WebAssembly anyway -#if defined(SO_PEERCRED) && !defined(_WASM_) +#if defined(SO_PEERCRED) && !defined(TARGET_WASM) struct ucred creds; socklen_t len = sizeof(creds); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) == 0) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.h b/src/libraries/Native/Unix/System.Native/pal_io.h index 9f68aa3d62f9e..3c7384b50f16a 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.h +++ b/src/libraries/Native/Unix/System.Native/pal_io.h @@ -11,6 +11,7 @@ #include #include #include +#include /** * File status returned by Stat or FStat. @@ -259,20 +260,6 @@ typedef enum PAL_SC_PAGESIZE = 2, // Size of a page in bytes } SysConfName; -/** - * Constants passed to and from poll describing what to poll for and what - * kind of data was received from poll. - */ -typedef enum -{ - PAL_POLLIN = 0x0001, /* non-urgent readable data available */ - PAL_POLLPRI = 0x0002, /* urgent readable data available */ - PAL_POLLOUT = 0x0004, /* data can be written without blocked */ - PAL_POLLERR = 0x0008, /* an error occurred */ - PAL_POLLHUP = 0x0010, /* the file descriptor hung up */ - PAL_POLLNVAL = 0x0020, /* the requested events were invalid */ -} PollEvents; - /** * Constants passed to posix_advise to give hints to the kernel about the type of I/O * operations that will occur. @@ -297,16 +284,6 @@ typedef struct int32_t InodeType; // The inode type as described in the NodeType enum } DirectoryEntry; -/** - * Our intermediate pollfd struct to normalize the data types - */ -typedef struct -{ - int32_t FileDescriptor; // The file descriptor to poll - int16_t Events; // The events to poll for - int16_t TriggeredEvents; // The events that triggered the poll -} PollEvent; - /** * Constants passed in the mask argument of INotifyAddWatch which identify inotify events. */ diff --git a/src/libraries/Native/Unix/System.Native/pal_networking.c b/src/libraries/Native/Unix/System.Native/pal_networking.c index 47d4273f6dc50..9aabac040abe7 100644 --- a/src/libraries/Native/Unix/System.Native/pal_networking.c +++ b/src/libraries/Native/Unix/System.Native/pal_networking.c @@ -7,6 +7,7 @@ #include "pal_io.h" #include "pal_safecrt.h" #include "pal_utilities.h" +#include #include #include @@ -1347,6 +1348,34 @@ static int32_t ConvertSocketFlagsPlatformToPal(int platformFlags) ((platformFlags & MSG_CTRUNC) == 0 ? 0 : SocketFlags_MSG_CTRUNC); } +int32_t SystemNative_Receive(intptr_t socket, void* buffer, int32_t bufferLen, int32_t flags, int32_t* received) +{ + if (buffer == NULL || bufferLen < 0 || received == NULL) + { + return Error_EFAULT; + } + + int fd = ToFileDescriptor(socket); + + int socketFlags; + if (!ConvertSocketFlagsPalToPlatform(flags, &socketFlags)) + { + return Error_ENOTSUP; + } + + ssize_t res; + while ((res = recv(fd, buffer, (size_t)bufferLen, socketFlags)) < 0 && errno == EINTR); + + if (res != -1) + { + *received = (int32_t)res; + return Error_SUCCESS; + } + + *received = 0; + return SystemNative_ConvertErrorPlatformToPal(errno); +} + int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* received) { if (messageHeader == NULL || received == NULL || messageHeader->SocketAddressLen < 0 || @@ -1390,6 +1419,38 @@ int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeade return SystemNative_ConvertErrorPlatformToPal(errno); } +int32_t SystemNative_Send(intptr_t socket, void* buffer, int32_t bufferLen, int32_t flags, int32_t* sent) +{ + if (buffer == NULL || bufferLen < 0 || sent == NULL) + { + return Error_EFAULT; + } + + int fd = ToFileDescriptor(socket); + + int socketFlags; + if (!ConvertSocketFlagsPalToPlatform(flags, &socketFlags)) + { + return Error_ENOTSUP; + } + + ssize_t res; +#if defined(__APPLE__) && __APPLE__ + // possible OSX kernel bug: https://github.com/dotnet/runtime/issues/27221 + while ((res = send(fd, buffer, (size_t)bufferLen, socketFlags)) < 0 && (errno == EINTR || errno == EPROTOTYPE)); +#else + while ((res = send(fd, buffer, (size_t)bufferLen, socketFlags)) < 0 && errno == EINTR); +#endif + if (res != -1) + { + *sent = (int32_t)res; + return Error_SUCCESS; + } + + *sent = 0; + return SystemNative_ConvertErrorPlatformToPal(errno); +} + int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* sent) { if (messageHeader == NULL || sent == NULL || messageHeader->SocketAddressLen < 0 || @@ -1411,7 +1472,7 @@ int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, ssize_t res; #if defined(__APPLE__) && __APPLE__ - // possible OSX kernel bug: #31927 + // possible OSX kernel bug: https://github.com/dotnet/runtime/issues/27221 while ((res = sendmsg(fd, &header, socketFlags)) < 0 && (errno == EINTR || errno == EPROTOTYPE)); #else while ((res = sendmsg(fd, &header, socketFlags)) < 0 && errno == EINTR); @@ -1566,29 +1627,7 @@ int32_t SystemNative_Listen(intptr_t socket, int32_t backlog) int32_t SystemNative_Shutdown(intptr_t socket, int32_t socketShutdown) { - int fd = ToFileDescriptor(socket); - - int how; - switch (socketShutdown) - { - case SocketShutdown_SHUT_READ: - how = SHUT_RD; - break; - - case SocketShutdown_SHUT_WRITE: - how = SHUT_WR; - break; - - case SocketShutdown_SHUT_BOTH: - how = SHUT_RDWR; - break; - - default: - return Error_EINVAL; - } - - int err = shutdown(fd, how); - return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno); + return Common_Shutdown(socket, socketShutdown); } int32_t SystemNative_GetSocketErrorOption(intptr_t socket, int32_t* error) @@ -1613,14 +1652,14 @@ int32_t SystemNative_GetSocketErrorOption(intptr_t socket, int32_t* error) return Error_SUCCESS; } -static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketOptionLevel, int* optLevel, int* optName) +static bool TryGetPlatformSocketOption(int32_t socketOptionLevel, int32_t socketOptionName, int* optLevel, int* optName) { - switch (socketOptionName) + switch (socketOptionLevel) { case SocketOptionLevel_SOL_SOCKET: *optLevel = SOL_SOCKET; - switch (socketOptionLevel) + switch (socketOptionName) { case SocketOptionName_SO_DEBUG: *optName = SO_DEBUG; @@ -1701,7 +1740,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO case SocketOptionLevel_SOL_IP: *optLevel = IPPROTO_IP; - switch (socketOptionLevel) + switch (socketOptionName) { case SocketOptionName_SO_IP_OPTIONS: *optName = IP_OPTIONS; @@ -1780,7 +1819,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO case SocketOptionLevel_SOL_IPV6: *optLevel = IPPROTO_IPV6; - switch (socketOptionLevel) + switch (socketOptionName) { case SocketOptionName_SO_IPV6_HOPLIMIT: *optName = IPV6_HOPLIMIT; @@ -1814,7 +1853,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO case SocketOptionLevel_SOL_TCP: *optLevel = IPPROTO_TCP; - switch (socketOptionLevel) + switch (socketOptionName) { case SocketOptionName_SO_TCP_NODELAY: *optName = TCP_NODELAY; @@ -1846,7 +1885,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO case SocketOptionLevel_SOL_UDP: *optLevel = IPPROTO_UDP; - switch (socketOptionLevel) + switch (socketOptionName) { // case SocketOptionName_SO_UDP_NOCHECKSUM: diff --git a/src/libraries/Native/Unix/System.Native/pal_networking.h b/src/libraries/Native/Unix/System.Native/pal_networking.h index 8d228c9f1bac4..04f26eb6650d1 100644 --- a/src/libraries/Native/Unix/System.Native/pal_networking.h +++ b/src/libraries/Native/Unix/System.Native/pal_networking.h @@ -7,6 +7,7 @@ #include "pal_compiler.h" #include "pal_types.h" #include "pal_errno.h" +#include /** * These error values are different on every platform so make a @@ -111,18 +112,6 @@ typedef enum MulticastOption_MULTICAST_IF = 2 // IP_MULTICAST_IF } MulticastOption; -/* - * Socket shutdown modes. - * - * NOTE: these values are taken from System.Net.SocketShutdown. - */ -typedef enum -{ - SocketShutdown_SHUT_READ = 0, // SHUT_RD - SocketShutdown_SHUT_WRITE = 1, // SHUT_WR - SocketShutdown_SHUT_BOTH = 2, // SHUT_RDWR -} SockerShutdown; - /* * Socket option levels. * @@ -371,8 +360,12 @@ PALEXPORT int32_t SystemNative_SetReceiveTimeout(intptr_t socket, int32_t millis PALEXPORT int32_t SystemNative_SetSendTimeout(intptr_t socket, int32_t millisecondsTimeout); +PALEXPORT int32_t SystemNative_Receive(intptr_t socket, void* buffer, int32_t bufferLen, int32_t flags, int32_t* received); + PALEXPORT int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* received); +PALEXPORT int32_t SystemNative_Send(intptr_t socket, void* buffer, int32_t bufferLen, int32_t flags, int32_t* sent); + PALEXPORT int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* sent); PALEXPORT int32_t SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* socketAddressLen, intptr_t* acceptedSocket); diff --git a/src/libraries/Native/Unix/System.Native/pal_process.c b/src/libraries/Native/Unix/System.Native/pal_process.c index 2a5028558446a..4b640ceef6fcf 100644 --- a/src/libraries/Native/Unix/System.Native/pal_process.c +++ b/src/libraries/Native/Unix/System.Native/pal_process.c @@ -21,9 +21,8 @@ #if HAVE_CRT_EXTERNS_H #include #endif -#if HAVE_PIPE2 #include -#endif +#include #include #if HAVE_SCHED_SETAFFINITY || HAVE_SCHED_GETAFFINITY @@ -48,7 +47,7 @@ c_static_assert(PAL_PRIO_PROCESS == (int)PRIO_PROCESS); c_static_assert(PAL_PRIO_PGRP == (int)PRIO_PGRP); c_static_assert(PAL_PRIO_USER == (int)PRIO_USER); -#if !HAVE_PIPE2 +#ifndef SOCK_CLOEXEC static pthread_mutex_t ProcessCreateLock = PTHREAD_MUTEX_INITIALIZER; #endif @@ -134,7 +133,7 @@ static int compare_groups(const void * a, const void * b) static int SetGroups(uint32_t* userGroups, int32_t userGroupsLength, uint32_t* processGroups) { -#if defined(__linux__) || defined(_WASM_) +#if defined(__linux__) || defined(TARGET_WASM) size_t platformGroupsLength = Int32ToSizeT(userGroupsLength); #else // BSD int platformGroupsLength = userGroupsLength; @@ -183,6 +182,31 @@ static int SetGroups(uint32_t* userGroups, int32_t userGroupsLength, uint32_t* p return rv; } +static int32_t SocketPair(int32_t sv[2]) +{ + int32_t result; + + int type = SOCK_STREAM; +#ifdef SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif + + while ((result = socketpair(AF_UNIX, type, 0, sv)) < 0 && errno == EINTR); + +#ifndef SOCK_CLOEXEC + if (result == 0) + { + while ((result = fcntl(sv[READ_END_OF_PIPE], F_SETFD, FD_CLOEXEC)) < 0 && errno == EINTR); + if (result == 0) + { + while ((result = fcntl(sv[WRITE_END_OF_PIPE], F_SETFD, FD_CLOEXEC)) < 0 && errno == EINTR); + } + } +#endif + + return result; +} + int32_t SystemNative_ForkAndExecProcess(const char* filename, char* const argv[], char* const envp[], @@ -201,7 +225,7 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, int32_t* stderrFd) { #if HAVE_FORK -#if !HAVE_PIPE2 +#ifndef SOCK_CLOEXEC bool haveProcessCreateLock = false; #endif bool success = true; @@ -257,11 +281,11 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, goto done; } -#if !HAVE_PIPE2 - // We do not have pipe2(); take the lock to emulate it race free. - // If another process were to be launched between the pipe creation and the fcntl call to set CLOEXEC on it, that - // file descriptor will be inherited into the other child process, eventually causing a deadlock either in the loop - // below that waits for that pipe to be closed or in StreamReader.ReadToEnd() in the calling code. +#ifndef SOCK_CLOEXEC + // We do not have SOCK_CLOEXEC; take the lock to emulate it race free. + // If another process were to be launched between the socket creation and the fcntl call to set CLOEXEC on it, that + // file descriptor would be inherited into the other child process, eventually causing a deadlock either in the loop + // below that waits for that socket to be closed or in StreamReader.ReadToEnd() in the calling code. if (pthread_mutex_lock(&ProcessCreateLock) != 0) { // This check is pretty much just checking for trashed memory. @@ -273,9 +297,9 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, // Open pipes for any requests to redirect stdin/stdout/stderr and set the // close-on-exec flag to the pipe file descriptors. - if ((redirectStdin && SystemNative_Pipe(stdinFds, PAL_O_CLOEXEC) != 0) || - (redirectStdout && SystemNative_Pipe(stdoutFds, PAL_O_CLOEXEC) != 0) || - (redirectStderr && SystemNative_Pipe(stderrFds, PAL_O_CLOEXEC) != 0)) + if ((redirectStdin && SocketPair(stdinFds) != 0) || + (redirectStdout && SocketPair(stdoutFds) != 0) || + (redirectStderr && SocketPair(stderrFds) != 0)) { success = false; goto done; @@ -426,7 +450,7 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, *stderrFd = stderrFds[READ_END_OF_PIPE]; done:; -#if !HAVE_PIPE2 +#ifndef SOCK_CLOEXEC if (haveProcessCreateLock) { pthread_mutex_unlock(&ProcessCreateLock); diff --git a/src/libraries/Native/Unix/System.Native/pal_sysctl.c b/src/libraries/Native/Unix/System.Native/pal_sysctl.c index 0adf8ac57d33a..0d3b7f1e9a16f 100644 --- a/src/libraries/Native/Unix/System.Native/pal_sysctl.c +++ b/src/libraries/Native/Unix/System.Native/pal_sysctl.c @@ -24,7 +24,7 @@ int32_t SystemNative_Sysctl(int* name, unsigned int namelen, void* value, size_t void* newp = NULL; size_t newlen = 0; -#if defined(__linux__) || defined(_WASM_) +#if defined(__linux__) || defined(TARGET_WASM) return sysctl(name, (int)(namelen), value, len, newp, newlen); #else return sysctl(name, namelen, value, len, newp, newlen); diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index 0fbd518fa8bc0..03eef6231a930 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -417,7 +417,6 @@ uint32_t NetSecurityNative_Wrap(uint32_t* minorStatus, GssCtxId* contextHandle, int32_t isEncrypt, uint8_t* inputBytes, - int32_t offset, int32_t count, PAL_GssBuffer* outBuffer) { @@ -425,14 +424,13 @@ uint32_t NetSecurityNative_Wrap(uint32_t* minorStatus, assert(contextHandle != NULL); assert(isEncrypt == 1 || isEncrypt == 0); assert(inputBytes != NULL); - assert(offset >= 0); assert(count >= 0); assert(outBuffer != NULL); // count refers to the length of the input message. That is, number of bytes of inputBytes - // starting at offset that need to be wrapped. + // that need to be wrapped. int confState; - GssBuffer inputMessageBuffer = {.length = (size_t)count, .value = inputBytes + offset}; + GssBuffer inputMessageBuffer = {.length = (size_t)count, .value = inputBytes}; GssBuffer gssBuffer; uint32_t majorStatus = gss_wrap(minorStatus, contextHandle, isEncrypt, GSS_C_QOP_DEFAULT, &inputMessageBuffer, &confState, &gssBuffer); diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h index 11e232d01501d..489b66b09290a 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h @@ -159,7 +159,6 @@ PALEXPORT uint32_t NetSecurityNative_Wrap(uint32_t* minorStatus, GssCtxId* contextHandle, int32_t isEncrypt, uint8_t* inputBytes, - int32_t offset, int32_t count, PAL_GssBuffer* outBuffer); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt index 743c501f12486..42f845d494d25 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt @@ -15,9 +15,20 @@ endif(CMAKE_STATIC_LIB_LINK) if(CLR_CMAKE_TARGET_ANDROID AND NOT CROSS_ROOTFS) # TEMP: consume OpenSSL dependencies from external sources via env. variables set(OPENSSL_FOUND 1) - set(OPENSSL_INCLUDE_DIR $ENV{AndroidOpenSslHeaders}) - set(OPENSSL_CRYPTO_LIBRARY $ENV{AndroidOpenSslCryptoLib}) - set(OPENSSL_SSL_LIBRARY $ENV{AndroidOpenSslLib}) + set(OPENSSL_INCLUDE_DIR $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/ssl/include) + if(CLR_CMAKE_TARGET_ARCH_ARM64) + set(OPENSSL_CRYPTO_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/crypto/libs/android.arm64-v8a/libcrypto.so) + set(OPENSSL_SSL_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/ssl/libs/android.arm64-v8a/libssl.so) + elseif(CLR_CMAKE_TARGET_ARCH_ARM) + set(OPENSSL_CRYPTO_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/crypto/libs/android.armeabi-v7a/libcrypto.so) + set(OPENSSL_SSL_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/ssl/libs/android.armeabi-v7a/libssl.so) + elseif(CLR_CMAKE_TARGET_ARCH_I386) + set(OPENSSL_CRYPTO_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/crypto/libs/android.x86/libcrypto.so) + set(OPENSSL_SSL_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/ssl/libs/android.x86/libssl.so) + else() + set(OPENSSL_CRYPTO_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/crypto/libs/android.x86_64/libcrypto.so) + set(OPENSSL_SSL_LIBRARY $ENV{ANDROID_OPENSSL_AAR}/prefab/modules/ssl/libs/android.x86_64/libssl.so) + endif() else() find_package(OpenSSL) endif() diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c index 1a9ea04839756..21820f8f443a1 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#include "pal_err.h" #include "pal_types.h" #include "pal_utilities.h" #include "pal_safecrt.h" @@ -1263,6 +1264,23 @@ static int32_t EnsureOpenSsl10Initialized() #define OPENSSL_INIT_NO_ATEXIT 0x00080000L #endif +pthread_mutex_t g_err_mutex = PTHREAD_MUTEX_INITIALIZER; +int volatile g_err_unloaded = 0; + +static void HandleShutdown() +{ + // Generally, a mutex to set a boolean is overkill, but this lock + // ensures that there are no callers already inside the string table + // when the unload (possibly) executes. + int result = pthread_mutex_lock(&g_err_mutex); + assert(!result && "Acquiring the error string table mutex failed."); + + g_err_unloaded = 1; + + result = pthread_mutex_unlock(&g_err_mutex); + assert(!result && "Releasing the error string table mutex failed."); +} + static int32_t EnsureOpenSsl11Initialized() { // In OpenSSL 1.0 we call OPENSSL_add_all_algorithms_conf() and ERR_load_crypto_strings(), @@ -1279,6 +1297,10 @@ static int32_t EnsureOpenSsl11Initialized() OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); + // As a fallback for when the NO_ATEXIT isn't respected, register a later + // atexit handler, so we will indicate that we're in the shutdown state + // and stop asking problematic questions from other threads. + atexit(HandleShutdown); return 0; } diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.c index 252e7be59ce29..e38aaf71f7aec 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.c @@ -34,10 +34,48 @@ uint64_t CryptoNative_ErrPeekLastError() const char* CryptoNative_ErrReasonErrorString(uint64_t error) { - return ERR_reason_error_string((unsigned long)error); + const char* errStr = NULL; + +#ifdef NEED_OPENSSL_1_1 + int result = pthread_mutex_lock(&g_err_mutex); + assert(!result && "Acquiring the error string table mutex failed."); + + if (!g_err_unloaded) + { +#endif + errStr = ERR_reason_error_string((unsigned long)error); +#ifdef NEED_OPENSSL_1_1 + } + + result = pthread_mutex_unlock(&g_err_mutex); + assert(!result && "Releasing the error string table mutex failed."); +#endif + + return errStr; } void CryptoNative_ErrErrorStringN(uint64_t e, char* buf, int32_t len) { - ERR_error_string_n((unsigned long)e, buf, Int32ToSizeT(len)); +#ifdef NEED_OPENSSL_1_1 + int result = pthread_mutex_lock(&g_err_mutex); + assert(!result && "Acquiring the error string table mutex failed."); + + if (!g_err_unloaded) + { +#endif + ERR_error_string_n((unsigned long)e, buf, Int32ToSizeT(len)); +#ifdef NEED_OPENSSL_1_1 + } + else + { + // If there's no string table, just make it be the empty string. + if (buf != NULL && len > 0) + { + buf[0] = 0; + } + } + + result = pthread_mutex_unlock(&g_err_mutex); + assert(!result && "Releasing the error string table mutex failed."); +#endif } diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.h index 3610c263d0af1..1c7470251e411 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_err.h @@ -6,6 +6,13 @@ #include #include "opensslshim.h" +#include + +#ifdef NEED_OPENSSL_1_1 +extern pthread_mutex_t g_err_mutex; +extern int volatile g_err_unloaded; +#endif + /* Shims the ERR_clear_error method. */ diff --git a/src/libraries/Native/Unix/configure.cmake b/src/libraries/Native/Unix/configure.cmake index 96f8f7857c3dc..4dc8b93c36de8 100644 --- a/src/libraries/Native/Unix/configure.cmake +++ b/src/libraries/Native/Unix/configure.cmake @@ -9,8 +9,8 @@ include(CheckTypeSize) if (CLR_CMAKE_TARGET_ANDROID) set(PAL_UNIX_NAME \"ANDROID\") -elseif (CLR_CMAKE_TARGET_ARCH_WASM) - set(PAL_UNIX_NAME \"WEBASSEMBLY\") +elseif (CLR_CMAKE_TARGET_BROWSER) + set(PAL_UNIX_NAME \"BROWSER\") elseif (CLR_CMAKE_TARGET_LINUX) set(PAL_UNIX_NAME \"LINUX\") elseif (CLR_CMAKE_TARGET_OSX) @@ -879,7 +879,7 @@ set (CMAKE_REQUIRED_LIBRARIES ${PREVIOUS_CMAKE_REQUIRED_LIBRARIES}) set (HAVE_INOTIFY 0) if (HAVE_INOTIFY_INIT AND HAVE_INOTIFY_ADD_WATCH AND HAVE_INOTIFY_RM_WATCH) set (HAVE_INOTIFY 1) -elseif (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ARCH_WASM) +elseif (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_BROWSER) message(FATAL_ERROR "Cannot find inotify functions on a Linux platform.") endif() diff --git a/src/libraries/Native/Windows/probe-win.ps1 b/src/libraries/Native/Windows/probe-win.ps1 index 353db37bfc63b..8641741c6c79e 100644 --- a/src/libraries/Native/Windows/probe-win.ps1 +++ b/src/libraries/Native/Windows/probe-win.ps1 @@ -34,7 +34,7 @@ function GetCMakeInfo($regKey) function LocateCMake { - $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from http://www.cmake.org/download/ and ensure it is on your path." + $errorMsg = "CMake is a pre-requisite to build this repository but it was not found on the path. Please install CMake from https://cmake.org/download/ and ensure it is on your path." $inPathPath = (get-command cmake.exe -ErrorAction SilentlyContinue) if ($inPathPath -ne $null) { # Resolve the first version of CMake if multiple commands are found diff --git a/src/libraries/Native/build-native.sh b/src/libraries/Native/build-native.sh index 84061ea1b2cef..fb8b183403eb5 100755 --- a/src/libraries/Native/build-native.sh +++ b/src/libraries/Native/build-native.sh @@ -109,6 +109,10 @@ elif [[ "$__TargetOS" == iOS ]]; then # set default iOS simulator deployment target (8.0 is the minimum supported by Xcode 11) # keep in sync with src/mono/Directory.Build.props __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs" + elif [[ "$__BuildArch" == x86 ]]; then + # set default iOS simulator deployment target (8.0 is the minimum supported by Xcode 11) + # keep in sync with src/mono/Directory.Build.props + __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"i386\" $__CMakeArgs" elif [[ "$__BuildArch" == arm64 ]]; then # set default iOS device deployment target (7.0 is the minimum supported by Xcode 11) # keep in sync with src/mono/Directory.Build.props diff --git a/src/libraries/Native/native-binplace.proj b/src/libraries/Native/native-binplace.proj index a17aab30baef9..2cd59c4856f44 100644 --- a/src/libraries/Native/native-binplace.proj +++ b/src/libraries/Native/native-binplace.proj @@ -20,6 +20,12 @@ + + wasm\runtimes\debug\ + + + wasm\runtimes\release\ + diff --git a/src/libraries/System.CodeDom/src/System.CodeDom.csproj b/src/libraries/System.CodeDom/src/System.CodeDom.csproj index a527bc6d02b9c..7217ca52bc65d 100644 --- a/src/libraries/System.CodeDom/src/System.CodeDom.csproj +++ b/src/libraries/System.CodeDom/src/System.CodeDom.csproj @@ -9,7 +9,7 @@ true - + diff --git a/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs b/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs index 022d5ce0456e5..c19a7197d8fce 100644 --- a/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs +++ b/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs @@ -113,7 +113,7 @@ public partial class ConcurrentDictionary : System.Collections.Gen void System.Collections.Generic.IDictionary.Add(TKey key, TValue value) { } bool System.Collections.Generic.IDictionary.Remove(TKey key) { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - void System.Collections.IDictionary.Add(object key, object value) { } + void System.Collections.IDictionary.Add(object key, object? value) { } bool System.Collections.IDictionary.Contains(object key) { throw null; } System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; } void System.Collections.IDictionary.Remove(object key) { } diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs index 71d94c8dc72d0..1939dd9d68b29 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs @@ -755,7 +755,13 @@ private bool TryTakeWithNoTimeValidation([MaybeNullWhen(false)] out T item, int } } } + +#pragma warning disable CS8762 + // https://github.com/dotnet/runtime/issues/36132 + // Compiler can't automatically deduce that nullability constraints + // for 'item' are satisfied at this exit point. return waitForSemaphoreWasSuccessful; +#pragma warning restore CS8762 } diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs index c37a08aa82f87..3088224b47186 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs @@ -170,7 +170,7 @@ private WorkStealingQueue CreateWorkStealingQueueForCurrentThread() /// To receive the item retrieved from the bag /// Whether to remove or peek. /// True if succeeded, false otherwise. - private bool TrySteal(out T result, bool take) + private bool TrySteal([MaybeNullWhen(false)] out T result, bool take) { if (CDSCollectionETWBCLProvider.Log.IsEnabled()) { @@ -219,7 +219,12 @@ private bool TrySteal(out T result, bool take) (TryStealFromTo(localQueue._nextQueue, null, out result, take) || TryStealFromTo(_workStealingQueues, localQueue, out result, take)); if (gotItem) { +#pragma warning disable CS8762 + // https://github.com/dotnet/runtime/issues/36132 + // Compiler can't automatically deduce that nullability constraints + // for 'result' are satisfied at this exit point. return true; +#pragma warning restore CS8762 } if (Interlocked.Read(ref _emptyToNonEmptyListTransitionCount) == initialEmptyToNonEmptyCounts) @@ -248,7 +253,7 @@ private bool TryStealFromTo(WorkStealingQueue? startInclusive, WorkStealingQueue } } - result = default(T)!; + result = default(T); return false; } @@ -870,7 +875,7 @@ internal bool TryLocalPop([MaybeNullWhen(false)] out T result) int tail = _tailIndex; if (_headIndex - tail >= 0) { - result = default(T)!; + result = default(T); return false; } @@ -914,7 +919,7 @@ internal bool TryLocalPop([MaybeNullWhen(false)] out T result) { // We encountered a race condition and the element was stolen, restore the tail. _tailIndex = tail + 1; - result = default(T)!; + result = default(T); return false; } } @@ -958,7 +963,7 @@ internal bool TryLocalPeek([MaybeNullWhen(false)] out T result) } } - result = default(T)!; + result = default(T); return false; } @@ -1015,7 +1020,7 @@ internal bool TrySteal([MaybeNullWhen(false)] out T result, bool take) } // The queue was empty. - result = default(T)!; + result = default(T); return false; } diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs index e8a10a5d788eb..7667e21505e7c 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -44,7 +44,7 @@ private sealed class Tables { internal readonly Node[] _buckets; // A singly-linked list for each bucket. internal readonly object[] _locks; // A set of locks, each guarding a section of the table. - internal volatile int[] _countPerLock; // The number of elements guarded by each lock. + internal readonly int[] _countPerLock; // The number of elements guarded by each lock. internal Tables(Node[] buckets, object[] locks, int[] countPerLock) { diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs index 6d5ca3a6af701..0d9ea6434ea7a 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs @@ -692,7 +692,7 @@ private static void CopyRemovedItems(Node head, T[] collection, int startIndex, /// For , this operation will attempt to pope the object at /// the top of the . /// - bool IProducerConsumerCollection.TryTake(out T item) + bool IProducerConsumerCollection.TryTake([MaybeNullWhen(false)] out T item) { return TryPop(out item); } diff --git a/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionTests.cs b/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionTests.cs index 6f8a107ccb8c6..9a21bc6ef01e7 100644 --- a/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionTests.cs +++ b/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionTests.cs @@ -966,6 +966,22 @@ public static void Test21_CopyToExceptions() }); } + [Fact] + public static void Test_WithNullEntries() + { + BlockingCollection collection = new BlockingCollection() + { + "hello", + null, + "goodbye" + }; + + Assert.Equal("hello", collection.Take()); + Assert.Null(collection.Take()); + Assert.Equal("goodbye", collection.Take()); + Assert.False(collection.TryTake(out _)); + } + [Fact] public static void Test_LargeSize() { diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index 060f87f330fc5..25cdd45c80070 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -702,7 +702,7 @@ public sealed partial class Builder : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } void System.Collections.IList.Clear() { } bool System.Collections.IList.Contains(object? value) { throw null; } int System.Collections.IList.IndexOf(object? value) { throw null; } @@ -819,7 +819,7 @@ public sealed partial class ImmutableSortedDictionary : System.Col bool System.Collections.Generic.IDictionary.Remove(TKey key) { throw null; } System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - void System.Collections.IDictionary.Add(object key, object value) { } + void System.Collections.IDictionary.Add(object key, object? value) { } void System.Collections.IDictionary.Clear() { } bool System.Collections.IDictionary.Contains(object key) { throw null; } System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; } diff --git a/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj b/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj index d456db9f3e9a4..a942bf3a506cd 100644 --- a/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj +++ b/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj @@ -1,11 +1,13 @@ - System.Collections.Immutable - netstandard1.0;portable-net45+win8+wp8+wpa81 $(NetCoreAppCurrent);netstandard1.0;netstandard1.3;netstandard2.0 true enable + + + netstandard1.0;portable-net45+win8+wp8+wpa81 + diff --git a/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj b/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj index 7eed443c2c2f4..f5130bcc181d6 100644 --- a/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj +++ b/src/libraries/System.Collections.Immutable/tests/System.Collections.Immutable.Tests.csproj @@ -4,7 +4,7 @@ $(NetCoreAppCurrent);$(NetFrameworkCurrent) - @@ -75,7 +75,7 @@ - + diff --git a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs index fd2e1cbdd8de5..d99c32ebed762 100644 --- a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs +++ b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs @@ -189,7 +189,7 @@ public partial class OrderedDictionary : System.Collections.ICollection, System. public void Remove(object key) { } public void RemoveAt(int index) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } } public partial class StringCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { diff --git a/src/libraries/System.Collections/ref/System.Collections.cs b/src/libraries/System.Collections/ref/System.Collections.cs index 918809a121156..92958369371d2 100644 --- a/src/libraries/System.Collections/ref/System.Collections.cs +++ b/src/libraries/System.Collections/ref/System.Collections.cs @@ -56,7 +56,7 @@ public abstract partial class Comparer : System.Collections.Generic.IComparer public static System.Collections.Generic.Comparer Default { get { throw null; } } public abstract int Compare([System.Diagnostics.CodeAnalysis.AllowNullAttribute] T x, [System.Diagnostics.CodeAnalysis.AllowNullAttribute] T y); public static System.Collections.Generic.Comparer Create(System.Comparison comparison) { throw null; } - int System.Collections.IComparer.Compare(object x, object y) { throw null; } + int System.Collections.IComparer.Compare(object? x, object? y) { throw null; } } public partial class Dictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable where TKey : notnull { @@ -102,7 +102,7 @@ public partial class Dictionary : System.Collections.Generic.IColl bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair keyValuePair) { throw null; } System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - void System.Collections.IDictionary.Add(object key, object value) { } + void System.Collections.IDictionary.Add(object key, object? value) { } bool System.Collections.IDictionary.Contains(object key) { throw null; } System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; } void System.Collections.IDictionary.Remove(object key) { } @@ -187,7 +187,7 @@ public abstract partial class EqualityComparer : System.Collections.Generic.I public static System.Collections.Generic.EqualityComparer Default { get { throw null; } } public abstract bool Equals([System.Diagnostics.CodeAnalysis.AllowNullAttribute] T x, [System.Diagnostics.CodeAnalysis.AllowNullAttribute] T y); public abstract int GetHashCode([System.Diagnostics.CodeAnalysis.DisallowNullAttribute] T obj); - bool System.Collections.IEqualityComparer.Equals(object x, object y) { throw null; } + bool System.Collections.IEqualityComparer.Equals(object? x, object? y) { throw null; } int System.Collections.IEqualityComparer.GetHashCode(object obj) { throw null; } } public partial class HashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable @@ -295,7 +295,7 @@ public partial struct Enumerator : System.Collections.Generic.IEnumerator, Sy public void Dispose() { } public bool MoveNext() { throw null; } void System.Collections.IEnumerator.Reset() { } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } } @@ -361,11 +361,11 @@ public partial class List : System.Collections.Generic.ICollection, System System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.IList.Add(object item) { throw null; } - bool System.Collections.IList.Contains(object item) { throw null; } - int System.Collections.IList.IndexOf(object item) { throw null; } - void System.Collections.IList.Insert(int index, object item) { } - void System.Collections.IList.Remove(object item) { } + int System.Collections.IList.Add(object? item) { throw null; } + bool System.Collections.IList.Contains(object? item) { throw null; } + int System.Collections.IList.IndexOf(object? item) { throw null; } + void System.Collections.IList.Insert(int index, object? item) { } + void System.Collections.IList.Remove(object? item) { } public T[] ToArray() { throw null; } public void TrimExcess() { } public bool TrueForAll(System.Predicate match) { throw null; } @@ -457,7 +457,7 @@ public partial class SortedDictionary : System.Collections.Generic bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair keyValuePair) { throw null; } System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - void System.Collections.IDictionary.Add(object key, object value) { } + void System.Collections.IDictionary.Add(object key, object? value) { } bool System.Collections.IDictionary.Contains(object key) { throw null; } System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; } void System.Collections.IDictionary.Remove(object key) { } @@ -572,7 +572,7 @@ public partial class SortedList : System.Collections.Generic.IColl bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair keyValuePair) { throw null; } System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) { } - void System.Collections.IDictionary.Add(object key, object value) { } + void System.Collections.IDictionary.Add(object key, object? value) { } bool System.Collections.IDictionary.Contains(object key) { throw null; } System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; } void System.Collections.IDictionary.Remove(object key) { } @@ -624,7 +624,7 @@ public partial class SortedSet : System.Collections.Generic.ICollection, S System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public bool TryGetValue(T equalValue, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out T actualValue) { throw null; } public void UnionWith(System.Collections.Generic.IEnumerable other) { } @@ -637,7 +637,7 @@ public partial struct Enumerator : System.Collections.Generic.IEnumerator, Sy public void Dispose() { } public bool MoveNext() { throw null; } void System.Collections.IEnumerator.Reset() { } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } } diff --git a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj index 06fbf9985c8d9..d093096479037 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj +++ b/src/libraries/System.ComponentModel.Composition/src/System.ComponentModel.Composition.csproj @@ -1,8 +1,6 @@ - System.ComponentModel.Composition - - + $(NoWarn);CS1573 $(NetCoreAppCurrent);netstandard2.0;netcoreapp2.0;_$(NetFrameworkCurrent) @@ -11,13 +9,13 @@ - SR.PlatformNotSupported_ComponentModel_Composition + SR.PlatformNotSupported_ComponentModel_Composition $(NoWarn);nullable - + @@ -188,7 +186,7 @@ - + diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx index 84fd677ad6763..7de9810d591ed 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -76,16 +77,16 @@ The value '{0}' is not a valid value for the enum '{1}'. - Invalid event handler for the {0} event. + Invalid event handler for the {0} event. - Invalid type for the {0} event. + Invalid type for the {0} event. Invalid type for the {0} property - Accessor methods for the {0} event are missing. + Accessor methods for the {0} event are missing. Accessor methods for the {0} property are missing. @@ -170,7 +171,7 @@ The {0} culture cannot be converted to a CultureInfo object on this computer. - + The service instance must derive from or implement {0}. @@ -178,7 +179,7 @@ The service {0} already exists in the service container. - Value of '{1}' is not valid for '{0}'. + Value of '{0}' cannot be empty. Null is not a valid value for {0}. @@ -242,11 +243,11 @@ The checkout was canceled by the user. - - + + (none) - + Relationships between {0}.{1} and {2}.{3} are not supported. - + \ No newline at end of file diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs index f80f2c00babdd..3227d9c8170df 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs @@ -14,7 +14,6 @@ namespace System.ComponentModel.Design public abstract class DesignerOptionService : IDesignerOptionService { private DesignerOptionCollection _options; - private static readonly char[] s_slash = { '\\' }; /// /// Returns the options collection for this service. There is @@ -48,7 +47,7 @@ protected DesignerOptionCollection CreateOptionCollection(DesignerOptionCollecti if (name.Length == 0) { - throw new ArgumentException(SR.Format(SR.InvalidArgumentValue, name.Length.ToString(), "0"), "name.Length"); + throw new ArgumentException(SR.Format(SR.InvalidArgumentValue, "name.Length"), nameof(name)); } return new DesignerOptionCollection(this, parent, name, value); @@ -70,7 +69,7 @@ private PropertyDescriptor GetOptionProperty(string pageName, string valueName) throw new ArgumentNullException(nameof(valueName)); } - string[] optionNames = pageName.Split(s_slash); + string[] optionNames = pageName.Split('\\'); DesignerOptionCollection options = Options; foreach (string optionName in optionNames) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs index c5bceb6e9d450..81889b0ca6327 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs @@ -44,7 +44,7 @@ public abstract class MemberRelationshipService // and not the other as the main constructor performs argument validation. if (source.Owner == null) { - throw new ArgumentNullException(nameof(MemberRelationship.Owner)); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "source.Owner"), nameof(source)); } Debug.Assert(source.Member != null); @@ -57,7 +57,7 @@ public abstract class MemberRelationshipService // and not the other as the main constructor performs argument validation. if (source.Owner == null) { - throw new ArgumentNullException(nameof(MemberRelationship.Owner)); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "source.Owner"), nameof(source)); } Debug.Assert(source.Member != null); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs index b7db262f29830..2ae15a3c54741 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs @@ -16,8 +16,6 @@ namespace System.ComponentModel /// public class EnumConverter : TypeConverter { - private static readonly char[] s_separators = { ',' }; - /// /// Initializes a new instance of the class for the given /// type. @@ -83,7 +81,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c { bool isUnderlyingTypeUInt64 = Enum.GetUnderlyingType(EnumType) == typeof(ulong); long convertedValue = 0; - string[] values = strValue.Split(s_separators); + string[] values = strValue.Split(','); foreach (string v in values) { convertedValue |= GetEnumValue(isUnderlyingTypeUInt64, (Enum)Enum.Parse(EnumType, v, true), culture); diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/DesignerOptionServiceTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/DesignerOptionServiceTests.cs index 37aaf19073788..78778d048a330 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/DesignerOptionServiceTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/DesignerOptionServiceTests.cs @@ -53,7 +53,7 @@ public void CreateOptionCollection_NullName_ThrowsArgumentNullException() public void CreateOptionCollection_EmptyName_ThrowsArgumentException() { var service = new TestDesignerOptionService(); - AssertExtensions.Throws("name.Length", () => service.DoCreateOptionCollection(service.Options, string.Empty, "value")); + AssertExtensions.Throws("name", () => service.DoCreateOptionCollection(service.Options, string.Empty, "value")); } [Fact] diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs index 9f85a1eeff671..5bc0242ca9ed5 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Design/Serialization/MemberRelationshipServiceTests.cs @@ -56,8 +56,8 @@ public void Indexer_NullSourceOwner_ThrowsArgumentNullException() Assert.Throws("sourceOwner", () => service[null, member]); Assert.Throws("sourceOwner", () => service[null, member] = new MemberRelationship()); - Assert.Throws("Owner", () => service[new MemberRelationship()]); - Assert.Throws("Owner", () => service[new MemberRelationship()] = new MemberRelationship()); + Assert.Throws("source", () => service[new MemberRelationship()]); + Assert.Throws("source", () => service[new MemberRelationship()] = new MemberRelationship()); } [Fact] diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/EnumConverterTest.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/EnumConverterTest.cs index 9e071a1d58799..1ba44811524dc 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/EnumConverterTest.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/EnumConverterTest.cs @@ -109,7 +109,7 @@ public static void ConvertTo_WithContext_Flags() public static void ConvertTo_WithContext_Negative() { AssertExtensions.Throws(null, () => EnumConverterTests.s_someEnumConverter.ConvertTo(TypeConverterTests.s_context, null, 3, typeof(string))); - AssertExtensions.Throws(null, "enumType", () => new EnumConverter(typeof(Enum)).ConvertTo(TypeConverterTests.s_context, null, SomeFlagsEnum.Option1, typeof(string))); + AssertExtensions.Throws("enumType", () => new EnumConverter(typeof(Enum)).ConvertTo(TypeConverterTests.s_context, null, SomeFlagsEnum.Option1, typeof(string))); } [Fact] diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/Mono/KeyValueConfigurationElementTest.cs b/src/libraries/System.Configuration.ConfigurationManager/tests/Mono/KeyValueConfigurationElementTest.cs index 703e3180c974e..7055f2f73c363 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/Mono/KeyValueConfigurationElementTest.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/Mono/KeyValueConfigurationElementTest.cs @@ -57,7 +57,6 @@ public ConfigurationPropertyCollection GetProperties() } [Fact] - // [NUnit.Framework.Category("NotWorking")] public void Properties() { Poker p = new Poker("name", "value"); diff --git a/src/libraries/System.Console/src/System.Console.csproj b/src/libraries/System.Console/src/System.Console.csproj index 43368249004c8..23b21f1ee3168 100644 --- a/src/libraries/System.Console/src/System.Console.csproj +++ b/src/libraries/System.Console/src/System.Console.csproj @@ -194,6 +194,8 @@ Link="Common\Interop\Unix\Interop.OpenFlags.cs" /> + )CreateSqlReaderMethodInfo.CreateDelegate(typeof(Func)); + return CreateSqlReaderMethodInfo.CreateDelegate>(); } private static MethodInfo CreateSqlReaderMethodInfo diff --git a/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs b/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs index b2d21c2315b7c..ef5ed183c08fe 100644 --- a/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs +++ b/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs @@ -16,7 +16,6 @@ internal sealed class XDRSchema : XMLSchema internal string _schemaUri; internal XmlElement _schemaRoot; internal DataSet _ds; - private static readonly char[] s_colonArray = new char[] { ':' }; internal XDRSchema(DataSet ds, bool fInline) { @@ -294,7 +293,7 @@ private static NameType FindNameType(string name) private Type ParseDataType(string dt, string dtValues) { string strType = dt; - string[] parts = dt.Split(s_colonArray); // ":" + string[] parts = dt.Split(':'); if (parts.Length > 2) { diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index ada2f69d139ae..553fdae9adbd9 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -1,15 +1,14 @@ - System.Data.Odbc true - netcoreapp2.0-FreeBSD;netcoreapp2.0-Linux;netcoreapp2.0-OSX;netcoreapp2.0-Windows_NT;net461-Windows_NT;netstandard2.0;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-Windows_NT;$(NetFrameworkCurrent)-Windows_NT + $(NetCoreAppCurrent)-Windows_NT;netcoreapp2.0-FreeBSD;netcoreapp2.0-Linux;netcoreapp2.0-OSX;netcoreapp2.0-Windows_NT;net461-Windows_NT;netstandard2.0;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetFrameworkCurrent)-Windows_NT true true true - SR.Odbc_PlatformNotSupported + SR.Odbc_PlatformNotSupported - System.Diagnostics.Debug.Tests System.Diagnostics.Tests true None $(NetCoreAppCurrent) true - + @@ -15,17 +14,15 @@ - - + + + + + + - - - - - - \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj index db385a8be9a16..1766bbf562536 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj @@ -2,12 +2,13 @@ netstandard2.0;netstandard1.1;netstandard1.3;net45;$(NetFrameworkCurrent) true - true false enable - - $(DefineConstants);ALLOW_PARTIALLY_TRUSTED_CALLERS + + + true + $(DefineConstants);ALLOW_PARTIALLY_TRUSTED_CALLERS diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index df8de8a03def2..e3bb30d9cea2b 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -1,25 +1,25 @@ - - netstandard1.1;portable-net45+win8+wpa81 true false $(NoWarn);SA1205 enable - $(DefineConstants);NO_EVENTSOURCE_COMPLEX_TYPE_SUPPORT - $(DefineConstants);EVENTSOURCE_ACTIVITY_SUPPORT - $(DefineConstants);EVENTSOURCE_ENUMERATE_SUPPORT $(NetCoreAppCurrent);netstandard1.1;netstandard1.3;net45;net46;netstandard2.0;$(NetFrameworkCurrent) true true - true + + netstandard1.1;portable-net45+win8+wpa81 + $(DefineConstants);NO_EVENTSOURCE_COMPLEX_TYPE_SUPPORT + $(DefineConstants);EVENTSOURCE_ACTIVITY_SUPPORT + $(DefineConstants);EVENTSOURCE_ENUMERATE_SUPPORT $(DefineConstants);ALLOW_PARTIALLY_TRUSTED_CALLERS;ENABLE_HTTP_HANDLER + true diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/System.Diagnostics.DiagnosticSource.Tests.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/System.Diagnostics.DiagnosticSource.Tests.csproj index c466ff6d0a6ed..ed8d7de3079d1 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/System.Diagnostics.DiagnosticSource.Tests.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/System.Diagnostics.DiagnosticSource.Tests.csproj @@ -3,7 +3,7 @@ true $(NetCoreAppCurrent);$(NetFrameworkCurrent)-Windows_NT - + @@ -11,7 +11,7 @@ - + true - netcoreapp2.0-Windows_NT;net461;netstandard2.0;$(NetCoreAppCurrent)-Windows_NT;$(NetFrameworkCurrent) + $(NetCoreAppCurrent)-Windows_NT;netcoreapp2.0-Windows_NT;net461;netstandard2.0;$(NetFrameworkCurrent) true true true - SR.PlatformNotSupported_EventLog + SR.PlatformNotSupported_EventLog diff --git a/src/libraries/System.Diagnostics.EventLog/tests/EventLogTests/EventLogSourceCreationTests.cs b/src/libraries/System.Diagnostics.EventLog/tests/EventLogTests/EventLogSourceCreationTests.cs index 29bfba9dcbe8b..eaaa6160bb0d5 100644 --- a/src/libraries/System.Diagnostics.EventLog/tests/EventLogTests/EventLogSourceCreationTests.cs +++ b/src/libraries/System.Diagnostics.EventLog/tests/EventLogTests/EventLogSourceCreationTests.cs @@ -3,13 +3,11 @@ // See the LICENSE file in the project root for more information. using Xunit; -using Microsoft.DotNet.XUnitExtensions; namespace System.Diagnostics.Tests { public class EventLogSourceCreationTests { - [Trait(XunitConstants.Category, "EventLog")] // Unreliable Win32 API call [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))] public void CheckSourceExistenceAndDeletion() { @@ -23,13 +21,13 @@ public void CheckSourceExistenceAndDeletion() finally { EventLog.DeleteEventSource(source); - Helpers.Retry(() => EventLog.Delete(log)); // unlike other tests, throw if delete fails + if (EventLog.Exists(log)) + Helpers.Retry(() => EventLog.Delete(log)); } Assert.False(EventLog.SourceExists(source)); } - [Trait(XunitConstants.Category, "EventLog")] // Unreliable Win32 API call [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] public void LogNameWithSame8FirstChars_NetCore() @@ -50,13 +48,15 @@ public void LogNameWithSame8FirstChars_NetCore() finally { EventLog.DeleteEventSource(firstSource); - Helpers.Retry(() => EventLog.Delete(firstLog)); + if (EventLog.Exists(firstLog)) + Helpers.Retry(() => EventLog.Delete(firstLog)); + EventLog.DeleteEventSource(secondSource); - Helpers.Retry(() => EventLog.Delete(secondLog)); + if (EventLog.Exists(secondLog)) + Helpers.Retry(() => EventLog.Delete(secondLog)); } } - [Trait(XunitConstants.Category, "EventLog")] // Unreliable Win32 API call [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))] [SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework)] public void LogNameWithSame8FirstChars_NetFramework() @@ -75,7 +75,8 @@ public void LogNameWithSame8FirstChars_NetFramework() finally { EventLog.DeleteEventSource(firstSource); - Helpers.Retry(() => EventLog.Delete(firstLog)); + if (EventLog.Exists(firstLog)) + Helpers.Retry(() => EventLog.Delete(firstLog)); } } @@ -145,7 +146,6 @@ public void SourceDataNull() Assert.Throws(() => EventLog.CreateEventSource(null)); } - [Trait(XunitConstants.Category, "EventLog")] // Unreliable Win32 API call [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))] public void SourceAlreadyExistsWhenCreatingSource() { @@ -160,7 +160,8 @@ public void SourceAlreadyExistsWhenCreatingSource() finally { EventLog.DeleteEventSource(source); - Helpers.RetrySilently(() => EventLog.Delete(log)); + if (EventLog.Exists(log)) + Helpers.RetrySilently(() => EventLog.Delete(log)); } } diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs b/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs index 661b0092b2537..842ba39e86b79 100644 --- a/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs +++ b/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs @@ -11,8 +11,6 @@ namespace System.Diagnostics { public sealed partial class FileVersionInfo { - private static readonly char[] s_versionSeparators = new char[] { '.' }; - private FileVersionInfo(string fileName) { _fileName = fileName; @@ -204,7 +202,7 @@ private static void ParseVersion(string? versionString, out int major, out int m if (versionString != null) { - string[] parts = versionString.Split(s_versionSeparators); + string[] parts = versionString.Split('.'); if (parts.Length <= 4 && parts.Length > 0) { major = ParseUInt16UntilNonDigit(parts[0], out bool endedEarly); diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounter.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounter.cs index f1637f4998c36..37e4b41d98a4f 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounter.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounter.cs @@ -470,9 +470,9 @@ private void InitializeImpl() string currentCategoryName = _categoryName; string currentMachineName = _machineName; - if (currentCategoryName == string.Empty) + if (currentCategoryName.Length == 0) throw new InvalidOperationException(SR.CategoryNameMissing); - if (_counterName == string.Empty) + if (_counterName.Length == 0) throw new InvalidOperationException(SR.CounterNameMissing); if (ReadOnly) diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs index 93ad673af15cb..7facea0fcdd6c 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs @@ -455,7 +455,7 @@ private static void CreateIniFile(string categoryName, string categoryHelp, Coun iniWriter.Write(languageId); iniWriter.Write(HelpSufix); iniWriter.Write("="); - if (categoryHelp == null || categoryHelp == string.Empty) + if (string.IsNullOrEmpty(categoryHelp)) iniWriter.WriteLine(SR.HelpNotAvailable); else iniWriter.WriteLine(categoryHelp); diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceData/CounterSet.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceData/CounterSet.cs index 13ac7471b6968..3a62324c07461 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceData/CounterSet.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceData/CounterSet.cs @@ -195,7 +195,7 @@ public CounterSetInstance CreateCounterSetInstance(string instanceName) { if (_provider == null) { - throw new ArgumentException(SR.Format(SR.Perflib_Argument_ProviderNotFound, _providerGuid), "ProviderGuid"); + throw new InvalidOperationException(SR.Format(SR.Perflib_InvalidOperation_NoActiveProvider, _providerGuid)); } if (_provider._hProvider.IsInvalid) { @@ -256,7 +256,7 @@ public CounterSetInstance CreateCounterSetInstance(string instanceName) { throw Status switch { - (uint)Interop.Errors.ERROR_ALREADY_EXISTS => new ArgumentException(SR.Format(SR.Perflib_Argument_CounterSetAlreadyRegister, _counterSet), "CounterSetGuid"), + (uint)Interop.Errors.ERROR_ALREADY_EXISTS => new InvalidOperationException(SR.Format(SR.Perflib_Argument_CounterSetAlreadyRegister, _counterSet)), _ => new Win32Exception((int)Status), }; diff --git a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj index 6e3ff47ece651..33d388e4441a4 100644 --- a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj +++ b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj @@ -1,7 +1,6 @@ AnyCPU - System.Diagnostics.Process $(DefineConstants);FEATURE_REGISTRY true $(NoWarn);CS1573 @@ -341,6 +340,7 @@ + diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs index 129963c07793c..29ec30ccdd885 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.IO; +using System.Net.Sockets; using System.Security; using System.Text; using System.Threading; @@ -761,16 +762,15 @@ internal static TimeSpan TicksToTimeSpan(double ticks) return TimeSpan.FromSeconds(ticks / (double)ticksPerSecond); } - /// Opens a stream around the specified file descriptor and with the specified access. - /// The file descriptor. + /// Opens a stream around the specified socket file descriptor and with the specified access. + /// The socket file descriptor. /// The access mode. /// The opened stream. - private static FileStream OpenStream(int fd, FileAccess access) + private static Stream OpenStream(int fd, FileAccess access) { Debug.Assert(fd >= 0); - return new FileStream( - new SafeFileHandle((IntPtr)fd, ownsHandle: true), - access, StreamBufferSize, isAsync: false); + var socket = new Socket(new SafeSocketHandle((IntPtr)fd, ownsHandle: true)); + return new NetworkStream(socket, access, ownsSocket: true); } /// Parses a command-line argument string into a list of arguments. diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs index 998ec9fa03f5c..af85258d6a9ea 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs @@ -536,7 +536,7 @@ private unsafe bool StartWithCreateProcess(ProcessStartInfo startInfo) environmentBlock = GetEnvironmentVariablesBlock(startInfo._environmentVariables!); } string workingDirectory = startInfo.WorkingDirectory; - if (workingDirectory == string.Empty) + if (workingDirectory.Length == 0) workingDirectory = Directory.GetCurrentDirectory(); bool retVal; diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs index 8fac2af7d9b85..0fb4160d7eacb 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs @@ -314,6 +314,42 @@ async private Task WaitPipeSignal(PipeStream pipe, int millisecond) } } + [PlatformSpecific(~TestPlatforms.Windows)] // currently on Windows these operations async-over-sync on Windows + [Fact] + public async Task ReadAsync_OutputStreams_Cancel_RespondsQuickly() + { + Process p = CreateProcessLong(); + try + { + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.RedirectStandardError = true; + Assert.True(p.Start()); + + using (var cts = new CancellationTokenSource()) + { + ValueTask vt = p.StandardOutput.ReadAsync(new char[1].AsMemory(), cts.Token); + await Task.Delay(1); + Assert.False(vt.IsCompleted); + cts.Cancel(); + await Assert.ThrowsAnyAsync(async () => await vt); + } + + using (var cts = new CancellationTokenSource()) + { + ValueTask vt = p.StandardError.ReadAsync(new char[1].AsMemory(), cts.Token); + await Task.Delay(1); + Assert.False(vt.IsCompleted); + cts.Cancel(); + await Assert.ThrowsAnyAsync(async () => await vt); + } + } + finally + { + p.Kill(); + p.Dispose(); + } + } + [Fact] public void TestSyncStreams() { diff --git a/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs b/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs index 900f6dbbb26d7..0a614bbe9e4d5 100644 --- a/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs +++ b/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs @@ -313,7 +313,9 @@ public void ToString_NullFrame_ThrowsNullReferenceException() [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] private static StackTrace Generic() => new StackTrace(); + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] private static StackTrace InvokeIgnoredMethod() => Ignored.Method(); + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] private static StackTrace InvokeIgnoredMethodWithException() => Ignored.MethodWithException(); [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] @@ -335,6 +337,8 @@ private static Exception InvokeException() private class ClassWithConstructor { public StackTrace StackTrace { get; } + + [MethodImpl(MethodImplOptions.NoInlining)] public ClassWithConstructor() => StackTrace = new StackTrace(); } diff --git a/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj b/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj index 22f8deac3fe10..0290d8432c8ff 100644 --- a/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj +++ b/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj @@ -4,15 +4,13 @@ true + + + - - - - - \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/System.Diagnostics.TextWriterTraceListener.Tests.csproj b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/System.Diagnostics.TextWriterTraceListener.Tests.csproj index ee76c5dd787b7..4a5c22ae09ef1 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/System.Diagnostics.TextWriterTraceListener.Tests.csproj +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/System.Diagnostics.TextWriterTraceListener.Tests.csproj @@ -4,15 +4,13 @@ $(NetCoreAppCurrent) - + - - - - + + \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs index 3252a3187f594..da867700460dd 100644 --- a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs @@ -263,10 +263,10 @@ public partial class TraceListenerCollection : System.Collections.ICollection, S public void Remove(string name) { } public void RemoveAt(int index) { } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } bool System.Collections.IList.Contains(object? value) { throw null; } int System.Collections.IList.IndexOf(object? value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } + void System.Collections.IList.Insert(int index, object? value) { } void System.Collections.IList.Remove(object? value) { } } [System.FlagsAttribute] diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj index 04dea616d3dba..41b0189dc0a7c 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj @@ -1,6 +1,5 @@ - System.DirectoryServices.AccountManagement true $(DefineConstants);FLAVOR_WHIDBEY;PAPI_AD;PAPI_REGSAM;USE_CTX_CACHE $(NoWarn);8073;CA1810 @@ -10,9 +9,9 @@ - SR.DirectoryServicesAccountManagement_PlatformNotSupported + SR.DirectoryServicesAccountManagement_PlatformNotSupported - + @@ -100,7 +99,7 @@ - + diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs index 040de0d0c932c..8c2bcb0871291 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs @@ -124,7 +124,7 @@ public string SamAccountName set { if (null == value || 0 == value.Length) - throw new ArgumentNullException(PropertyNames.PrincipalSamAccountName); + throw new ArgumentNullException(nameof(value)); if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalSamAccountName)) throw new InvalidOperationException(SR.InvalidPropertyForStore); @@ -244,7 +244,7 @@ public string Name set { if (null == value || 0 == value.Length) - throw new ArgumentNullException(PropertyNames.PrincipalName); + throw new ArgumentNullException(nameof(value)); if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalName)) throw new InvalidOperationException(SR.InvalidPropertyForStore); diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs index 62b8e52e5239d..68d1811c0a0eb 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs @@ -23,7 +23,7 @@ public PrincipalSearcher() public PrincipalSearcher(Principal queryFilter) { if (null == queryFilter) - throw new ArgumentException(nameof(queryFilter)); + throw new ArgumentException(null, nameof(queryFilter)); _ctx = queryFilter.Context; this.QueryFilter = queryFilter; // use property to enforce "no persisted principals" check diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs index e17eaf3f60aac..9d83710d15168 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs @@ -35,7 +35,7 @@ public void Ctor_NullSamAccountName_ThrowsArgumentException() public void Ctor_EmptySamAccountName_ThrowsArgumentNullException() { var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws("Principal.SamAccountName", null, () => new ComputerPrincipal(context, string.Empty, "password", enabled: true)); + AssertExtensions.Throws("value", null, () => new ComputerPrincipal(context, string.Empty, "password", enabled: true)); } [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index a1fa96ae4019b..03d310243f3b3 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -1,17 +1,16 @@ - System.DirectoryServices.Protocols true $(NoWarn);0649;CA1810 true - $(NetCoreAppCurrent)-Windows_NT;netstandard2.0;netcoreapp2.0-Windows_NT;_$(NetFrameworkCurrent) + $(NetCoreAppCurrent)-Windows_NT;netcoreapp2.0-Windows_NT;$(NetCoreAppCurrent)-OSX;netcoreapp2.0-OSX;$(NetCoreAppCurrent)-Linux;netcoreapp2.0-Linux;netstandard2.0;_$(NetFrameworkCurrent) true - SR.DirectoryServicesProtocols_PlatformNotSupported + SR.DirectoryServicesProtocols_PlatformNotSupported - + @@ -36,14 +35,57 @@ - - + + + Common\Interop\Interop.Ldap.cs + + + + + + + + + + + Common\Interop\Windows\Interop.Libraries.cs + + + Common\Interop\Windows\Wldap32\Interop.Ldap.cs + + + Common\Interop\Windows\Wldap32\Interop.Ber.cs + + + + + + + + + + + Common\Interop\Linux\OpenLdap\Interop.Ldap.cs + + + Common\Interop\Linux\OpenLdap\Interop.Ber.cs + + + + + Common\Interop\Linux\Interop.Libraries.cs + + + + + Common\Interop\OSX\Interop.Libraries.cs + - + @@ -63,4 +105,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Linux.cs new file mode 100644 index 0000000000000..f58a94df52234 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Linux.cs @@ -0,0 +1,35 @@ +// 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. + +namespace System.DirectoryServices.Protocols +{ + internal static class BerPal + { + internal static void FreeBervalArray(IntPtr ptrResult) => Interop.ber_bvecfree(ptrResult); + + internal static void FreeBerval(IntPtr flattenptr) => Interop.ber_bvfree(flattenptr); + + internal static void FreeBerElement(IntPtr berelement, int option) => Interop.ber_free(berelement, option); + + internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.ber_flatten(berElement, ref flattenptr); + + internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.ber_printf_berarray(berElement, format, value); + + internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.ber_printf_bytearray(berElement, format, value, length); + + internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.ber_printf_emptyarg(berElement, format); + + internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.ber_printf_int(berElement, format, value); + + internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.ber_scanf(berElement, format); + + internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength); + + internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.ber_scanf_int(berElement, format, ref result); + + internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.ber_scanf_ptr(berElement, format, ref value); + + internal static bool IsBerDecodeError(int errorCode) => errorCode == -1; + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Windows.cs new file mode 100644 index 0000000000000..bec5b5a65d5ac --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Windows.cs @@ -0,0 +1,37 @@ +// 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.Runtime.InteropServices; + +namespace System.DirectoryServices.Protocols +{ + internal static class BerPal + { + internal static void FreeBervalArray(IntPtr ptrResult) => Interop.ber_bvecfree(ptrResult); + + internal static void FreeBerval(IntPtr flattenptr) => Interop.ber_bvfree(flattenptr); + + internal static void FreeBerElement(IntPtr berelement, int option) => Interop.ber_free(berelement, option); + + internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.ber_flatten(berElement, ref flattenptr); + + internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.ber_printf_berarray(berElement, format, value); + + internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.ber_printf_bytearray(berElement, format, value, length); + + internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.ber_printf_emptyarg(berElement, format); + + internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.ber_printf_int(berElement, format, value); + + internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.ber_scanf(berElement, format); + + internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength); + + internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.ber_scanf_int(berElement, format, ref result); + + internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.ber_scanf_ptr(berElement, format, ref value); + + internal static bool IsBerDecodeError(int errorCode) => errorCode != 0; + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs new file mode 100644 index 0000000000000..9089e8902726c --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs @@ -0,0 +1,169 @@ +// 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.Runtime.InteropServices; + +namespace System.DirectoryServices.Protocols +{ + internal static class LdapPal + { + internal static void CancelDirectoryAsyncOperation(ConnectionHandle ldapHandle, int messagId) => Interop.ldap_abandon(ldapHandle, messagId); + + internal static int AddDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_add(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber); + + internal static int CompareDirectoryEntries(ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_compare(ldapHandle, dn, attributeName, binaryValue, servercontrol, clientcontrol, ref messageNumber); + + internal static void FreeDirectoryControl(IntPtr control) => Interop.ldap_control_free(control); + + internal static void FreeDirectoryControls(IntPtr value) => Interop.ldap_controls_free(value); + + internal static int CreateDirectorySortControl(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control) => Interop.ldap_create_sort_control(handle, keys, critical, ref control); + + internal static int DeleteDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => Interop.ldap_delete_ext(ldapHandle, dn, servercontrol, clientcontrol, ref messageNumber); + + internal static int ExtendedDirectoryOperation(ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_extended_operation(ldapHandle, oid, data, servercontrol, clientcontrol, ref messageNumber); + + internal static IntPtr GetFirstAttributeFromEntry(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr address) => Interop.ldap_first_attribute(ldapHandle, result, ref address); + + internal static IntPtr GetFirstEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_entry(ldapHandle, result); + + internal static IntPtr GetFirstReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_reference(ldapHandle, result); + + internal static IntPtr GetDistinguishedName(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_get_dn(ldapHandle, result); + + internal static int GetLastErrorFromConnection(ConnectionHandle ldapHandle) + { + int result = 0; + Interop.ldap_get_option_int(ldapHandle, LdapOption.LDAP_OPT_ERROR_NUMBER, ref result); + return result; + } + + internal static int GetIntOption(ConnectionHandle ldapHandle, LdapOption option, ref int outValue) => Interop.ldap_get_option_int(ldapHandle, option, ref outValue); + + internal static int GetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr outValue) => Interop.ldap_get_option_ptr(ldapHandle, option, ref outValue); + + internal static int GetSecurityHandleOption(ConnectionHandle ldapHandle, LdapOption option, ref SecurityHandle outValue) => Interop.ldap_get_option_sechandle(ldapHandle, option, ref outValue); + + // This option is not supported on Linux, so it would most likely throw. + internal static int GetSecInfoOption(ConnectionHandle ldapHandle, LdapOption option, SecurityPackageContextConnectionInformation outValue) => Interop.ldap_get_option_secInfo(ldapHandle, option, outValue); + + internal static IntPtr GetValuesFromAttribute(ConnectionHandle ldapHandle, IntPtr result, string name) => Interop.ldap_get_values_len(ldapHandle, result, name); + + internal static void FreeMemory(IntPtr outValue) => Interop.ldap_memfree(outValue); + + internal static int ModifyDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_modify(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber); + + internal static IntPtr GetNextAttributeFromResult(ConnectionHandle ldapHandle, IntPtr result, IntPtr address) => Interop.ldap_next_attribute(ldapHandle, result, address); + + internal static IntPtr GetNextEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_entry(ldapHandle, result); + + internal static IntPtr GetNextReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_reference(ldapHandle, result); + + internal static int ParseExtendedResult(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt) => Interop.ldap_parse_extended_result(ldapHandle, result, ref oid, ref data, freeIt); + + internal static int ParseReference(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr referrals) => Interop.ldap_parse_reference(ldapHandle, result, ref referrals, IntPtr.Zero, 0); + + internal static int ParseResult(ConnectionHandle ldapHandle, IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt) => + Interop.ldap_parse_result(ldapHandle, result, ref serverError, ref dn, ref message, ref referral, ref control, freeIt); + + internal static int ParseResultReferral(ConnectionHandle ldapHandle, IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt) + => Interop.ldap_parse_result_referral(ldapHandle, result, serverError, dn, message, ref referral, control, freeIt); + + internal static int RenameDirectoryEntry(ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_rename(ldapHandle, dn, newRdn, newParentDn, deleteOldRdn, servercontrol, clientcontrol, ref messageNumber); + + internal static int GetResultFromAsyncOperation(ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Message) => Interop.ldap_result(ldapHandle, messageId, all, timeout, ref Message); + + internal static int ResultToErrorCode(ConnectionHandle ldapHandle, IntPtr result, int freeIt) => Interop.ldap_result2error(ldapHandle, result, freeIt); + + internal static int SearchDirectory(ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber) => + Interop.ldap_search(ldapHandle, dn, scope, filter, attributes, attributeOnly, servercontrol, clientcontrol, timelimit, sizelimit, ref messageNumber); + + // This option is not supported in Linux, so it would most likely throw. + internal static int SetClientCertOption(ConnectionHandle ldapHandle, LdapOption option, QUERYCLIENTCERT outValue) => Interop.ldap_set_option_clientcert(ldapHandle, option, outValue); + + internal static int SetIntOption(ConnectionHandle ld, LdapOption option, ref int inValue) => Interop.ldap_set_option_int(ld, option, ref inValue); + + internal static int SetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr inValue) => Interop.ldap_set_option_ptr(ldapHandle, option, ref inValue); + + internal static int SetReferralOption(ConnectionHandle ldapHandle, LdapOption option, ref LdapReferralCallback outValue) => Interop.ldap_set_option_referral(ldapHandle, option, ref outValue); + + // This option is not supported in Linux, so it would most likely throw. + internal static int SetServerCertOption(ConnectionHandle ldapHandle, LdapOption option, VERIFYSERVERCERT outValue) => Interop.ldap_set_option_servercert(ldapHandle, option, outValue); + + internal static int BindToDirectory(ConnectionHandle ld, string who, string passwd) => Interop.ldap_simple_bind(ld, who, passwd); + + internal static int StartTls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls) => Interop.ldap_start_tls(ldapHandle, ref ServerReturnValue, ref Message, ServerControls, ClientControls); + + // openldap doesn't have a ldap_stop_tls function. Returning true as no-op for Linux. + internal static byte StopTls(ConnectionHandle ldapHandle) => 1; + + internal static void FreeValue(IntPtr referral) => Interop.ldap_value_free(referral); + + internal static void FreeAttributes(IntPtr berelement) => Interop.ldap_value_free_len(berelement); + + internal static string PtrToString(IntPtr requestName) => Marshal.PtrToStringAnsi(requestName); + + internal static IntPtr StringToPtr(string s) => Marshal.StringToHGlobalAnsi(s); + + /// + /// Function that will be sent to the Sasl interactive bind procedure which will resolve all Sasl challenges + /// that get passed in by using the defaults that we get passed in. + /// + /// The connection handle to the LDAP server. + /// Flags that control the interaction used to retrieve any necessary Sasl authentication parameters + /// Pointer to the defaults structure that was sent to sasl_interactive_bind + /// Pointer to the challenge we need to resolve + /// + internal static int SaslInteractionProcedure(IntPtr ldapHandle, uint flags, IntPtr defaultsPtr, IntPtr interactPtr) + { + if (ldapHandle == IntPtr.Zero) + { + return -9; // Parameter Error + } + // Convert pointers into managed structures. + IntPtr currentInteractPtr = interactPtr; + SaslInteractiveChallenge interactChallenge = Marshal.PtrToStructure(currentInteractPtr); + SaslDefaultCredentials defaults = Marshal.PtrToStructure(defaultsPtr); + + // loop through all of the challenges that were sent through the interactChallenge. + while (interactChallenge.saslChallengeType != (int)SaslChallengeType.SASL_CB_LIST_END) + { + // use defaults to fix the challenge type + switch (interactChallenge.saslChallengeType) + { + case (int)SaslChallengeType.SASL_CB_GETREALM: + interactChallenge.defresult = defaults.realm; + break; + case (int)SaslChallengeType.SASL_CB_AUTHNAME: + interactChallenge.defresult = defaults.authcid; + break; + case (int)SaslChallengeType.SASL_CB_PASS: + interactChallenge.defresult = defaults.passwd; + break; + case (int)SaslChallengeType.SASL_CB_USER: + interactChallenge.defresult = defaults.authzid; + break; + } + + if (!string.IsNullOrEmpty(interactChallenge.defresult)) + { + interactChallenge.result = Marshal.StringToHGlobalAnsi(interactChallenge.defresult); + interactChallenge.len = interactChallenge != null ? (uint)interactChallenge.defresult.Length : 0; + } + + // Move to next interact challenge + Marshal.StructureToPtr(interactChallenge, currentInteractPtr, false); + currentInteractPtr = IntPtr.Add(currentInteractPtr, Marshal.SizeOf()); + interactChallenge = Marshal.PtrToStructure(currentInteractPtr); + } + + return 0; + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Windows.cs new file mode 100644 index 0000000000000..8a70be9f14e5e --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Windows.cs @@ -0,0 +1,105 @@ +// 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.Runtime.InteropServices; + +namespace System.DirectoryServices.Protocols +{ + internal static class LdapPal + { + internal static void CancelDirectoryAsyncOperation(ConnectionHandle ldapHandle, int messagId) => Interop.ldap_abandon(ldapHandle, messagId); + + internal static int AddDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_add(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber); + + internal static int CompareDirectoryEntries(ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_compare(ldapHandle, dn, attributeName, strValue, binaryValue, servercontrol, clientcontrol, ref messageNumber); + + internal static void FreeDirectoryControl(IntPtr control) => Interop.ldap_control_free(control); + + internal static void FreeDirectoryControls(IntPtr value) => Interop.ldap_controls_free(value); + + internal static int CreateDirectorySortControl(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control) => Interop.ldap_create_sort_control(handle, keys, critical, ref control); + + internal static int DeleteDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => Interop.ldap_delete_ext(ldapHandle, dn, servercontrol, clientcontrol, ref messageNumber); + + internal static int ExtendedDirectoryOperation(ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_extended_operation(ldapHandle, oid, data, servercontrol, clientcontrol, ref messageNumber); + + internal static IntPtr GetFirstAttributeFromEntry(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr address) => Interop.ldap_first_attribute(ldapHandle, result, ref address); + + internal static IntPtr GetFirstEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_entry(ldapHandle, result); + + internal static IntPtr GetFirstReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_reference(ldapHandle, result); + + internal static IntPtr GetDistinguishedName(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_get_dn(ldapHandle, result); + + internal static int GetLastErrorFromConnection(ConnectionHandle ldapHandle) => Interop.LdapGetLastError(); + + internal static int GetIntOption(ConnectionHandle ldapHandle, LdapOption option, ref int outValue) => Interop.ldap_get_option_int(ldapHandle, option, ref outValue); + + internal static int GetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr outValue) => Interop.ldap_get_option_ptr(ldapHandle, option, ref outValue); + + internal static int GetSecurityHandleOption(ConnectionHandle ldapHandle, LdapOption option, ref SecurityHandle outValue) => Interop.ldap_get_option_sechandle(ldapHandle, option, ref outValue); + + internal static int GetSecInfoOption(ConnectionHandle ldapHandle, LdapOption option, SecurityPackageContextConnectionInformation outValue) => Interop.ldap_get_option_secInfo(ldapHandle, option, outValue); + + internal static IntPtr GetValuesFromAttribute(ConnectionHandle ldapHandle, IntPtr result, string name) => Interop.ldap_get_values_len(ldapHandle, result, name); + + internal static void FreeMemory(IntPtr outValue) => Interop.ldap_memfree(outValue); + + internal static int ModifyDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_modify(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber); + + internal static IntPtr GetNextAttributeFromResult(ConnectionHandle ldapHandle, IntPtr result, IntPtr address) => Interop.ldap_next_attribute(ldapHandle, result, address); + + internal static IntPtr GetNextEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_entry(ldapHandle, result); + + internal static IntPtr GetNextReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_reference(ldapHandle, result); + + internal static int ParseExtendedResult(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt) => Interop.ldap_parse_extended_result(ldapHandle, result, ref oid, ref data, freeIt); + + internal static int ParseReference(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr referrals) => Interop.ldap_parse_reference(ldapHandle, result, ref referrals); + + internal static int ParseResult(ConnectionHandle ldapHandle, IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt) => + Interop.ldap_parse_result(ldapHandle, result, ref serverError, ref dn, ref message, ref referral, ref control, freeIt); + + internal static int ParseResultReferral(ConnectionHandle ldapHandle, IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt) + => Interop.ldap_parse_result_referral(ldapHandle, result, serverError, dn, message, ref referral, control, freeIt); + + internal static int RenameDirectoryEntry(ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => + Interop.ldap_rename(ldapHandle, dn, newRdn, newParentDn, deleteOldRdn, servercontrol, clientcontrol, ref messageNumber); + + internal static int GetResultFromAsyncOperation(ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Message) => Interop.ldap_result(ldapHandle, messageId, all, timeout, ref Message); + + internal static int ResultToErrorCode(ConnectionHandle ldapHandle, IntPtr result, int freeIt) => Interop.ldap_result2error(ldapHandle, result, freeIt); + + internal static int SearchDirectory(ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber) => + Interop.ldap_search(ldapHandle, dn, scope, filter, attributes, attributeOnly, servercontrol, clientcontrol, timelimit, sizelimit, ref messageNumber); + + internal static int SetClientCertOption(ConnectionHandle ldapHandle, LdapOption option, QUERYCLIENTCERT outValue) => Interop.ldap_set_option_clientcert(ldapHandle, option, outValue); + + internal static int SetIntOption(ConnectionHandle ld, LdapOption option, ref int inValue) => Interop.ldap_set_option_int(ld, option, ref inValue); + + internal static int SetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr inValue) => Interop.ldap_set_option_ptr(ldapHandle, option, ref inValue); + + internal static int SetReferralOption(ConnectionHandle ldapHandle, LdapOption option, ref LdapReferralCallback outValue) => Interop.ldap_set_option_referral(ldapHandle, option, ref outValue); + + internal static int SetServerCertOption(ConnectionHandle ldapHandle, LdapOption option, VERIFYSERVERCERT outValue) => Interop.ldap_set_option_servercert(ldapHandle, option, outValue); + + internal static int BindToDirectory(ConnectionHandle ld, string who, string passwd) => Interop.ldap_simple_bind_s(ld, who, passwd); + + internal static int StartTls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls) => Interop.ldap_start_tls(ldapHandle, ref ServerReturnValue, ref Message, ServerControls, ClientControls); + + internal static byte StopTls(ConnectionHandle ldapHandle) => Interop.ldap_stop_tls(ldapHandle); + + internal static void FreeValue(IntPtr referral) => Interop.ldap_value_free(referral); + + internal static void FreeAttributes(IntPtr berelement) => Interop.ldap_value_free_len(berelement); + + internal static string PtrToString(IntPtr requestName) => Marshal.PtrToStringUni(requestName); + + internal static IntPtr StringToPtr(string s) => Marshal.StringToHGlobalUni(s); + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs new file mode 100644 index 0000000000000..8478b4b150430 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs @@ -0,0 +1,79 @@ +// 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 Microsoft.Win32.SafeHandles; + +namespace System.DirectoryServices.Protocols +{ + internal sealed class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid + { + internal bool _needDispose = false; + + internal ConnectionHandle() + :base(true) + { + Interop.ldap_initialize(out handle, null); + _needDispose = true; + } + + internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true) + { + _needDispose = disposeHandle; + if (value == IntPtr.Zero) + { + throw new LdapException(SR.LDAP_CONNECT_ERROR); + } + else + { + SetHandle(value); + } + } + + protected override bool ReleaseHandle() + { + if (_needDispose) + { + IntPtr nullPointer = IntPtr.Zero; + Interop.ldap_unbind_ext_s(handle, ref nullPointer, ref nullPointer); + } + + handle = IntPtr.Zero; + return true; + } + } + + internal sealed class SafeBerHandle : SafeHandleZeroOrMinusOneIsInvalid + { + internal SafeBerHandle() : base(true) + { + SetHandle(Interop.ber_alloc(1)); + if (handle == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + } + + internal SafeBerHandle(berval value) : base(true) + { + // In Linux if bv_val is null ber_init will segFault instead of returning IntPtr.Zero. + // In Linux if bv_len is 0 ber_init returns a valid pointer which will then fail when trying to use it, + // so we fail early by throwing exception if this is the case. + if (value.bv_val == IntPtr.Zero || value.bv_len == 0) + { + throw new BerConversionException(); + } + SetHandle(Interop.ber_init(value)); + if (handle == IntPtr.Zero) + { + throw new BerConversionException(); + } + } + + protected override bool ReleaseHandle() + { + Interop.ber_free(handle, 1); + return true; + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Windows.cs similarity index 70% rename from src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs rename to src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Windows.cs index 50a49660e34ac..26d3b4992b1bb 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Windows.cs @@ -3,25 +3,23 @@ // See the LICENSE file in the project root for more information. using Microsoft.Win32.SafeHandles; -using System.Runtime.InteropServices; -using System.Security; namespace System.DirectoryServices.Protocols { - internal sealed class BerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid + internal sealed class SafeBerHandle : SafeHandleZeroOrMinusOneIsInvalid { - internal BerSafeHandle() : base(true) + internal SafeBerHandle() : base(true) { - SetHandle(Wldap32.ber_alloc(1)); + SetHandle(Interop.ber_alloc(1)); if (handle == IntPtr.Zero) { throw new OutOfMemoryException(); } } - internal BerSafeHandle(berval value) : base(true) + internal SafeBerHandle(berval value) : base(true) { - SetHandle(Wldap32.ber_init(value)); + SetHandle(Interop.ber_init(value)); if (handle == IntPtr.Zero) { throw new BerConversionException(); @@ -30,21 +28,7 @@ internal BerSafeHandle(berval value) : base(true) protected override bool ReleaseHandle() { - Wldap32.ber_free(handle, 1); - return true; - } - } - - internal sealed class HGlobalMemHandle : SafeHandleZeroOrMinusOneIsInvalid - { - internal HGlobalMemHandle(IntPtr value) : base(true) - { - SetHandle(value); - } - - protected override bool ReleaseHandle() - { - Marshal.FreeHGlobal(handle); + Interop.ber_free(handle, 1); return true; } } @@ -55,11 +39,11 @@ internal sealed class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid internal ConnectionHandle() : base(true) { - SetHandle(Wldap32.ldap_init(null, 389)); + SetHandle(Interop.ldap_init(null, 389)); if (handle == IntPtr.Zero) { - int error = Wldap32.LdapGetLastError(); + int error = Interop.LdapGetLastError(); if (Utility.IsLdapError((LdapError)error)) { string errorMessage = LdapErrorMappings.MapResultCode(error); @@ -77,7 +61,7 @@ internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true) _needDispose = disposeHandle; if (value == IntPtr.Zero) { - int error = Wldap32.LdapGetLastError(); + int error = Interop.LdapGetLastError(); if (Utility.IsLdapError((LdapError)error)) { string errorMessage = LdapErrorMappings.MapResultCode(error); @@ -99,7 +83,7 @@ protected override bool ReleaseHandle() { if (_needDispose) { - Wldap32.ldap_unbind(handle); + Interop.ldap_unbind(handle); } handle = IntPtr.Zero; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs new file mode 100644 index 0000000000000..0904f64bb092c --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs @@ -0,0 +1,28 @@ +// 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.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +namespace System.DirectoryServices.Protocols +{ + internal sealed class HGlobalMemHandle : SafeHandleZeroOrMinusOneIsInvalid + { + internal static IntPtr _dummyPointer = new IntPtr(1); + + internal HGlobalMemHandle(IntPtr value) : base(true) + { + SetHandle(value); + } + + protected override bool ReleaseHandle() + { + if (handle != _dummyPointer) + { + Marshal.FreeHGlobal(handle); + } + return true; + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Linux.cs new file mode 100644 index 0000000000000..2d1b8508cecb1 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Linux.cs @@ -0,0 +1,28 @@ +// 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.Collections; + +namespace System.DirectoryServices.Protocols +{ + public static partial class BerConverter + { + private static unsafe int DecodeBitStringHelper(ArrayList resultList, SafeBerHandle berElement) + { + // Windows doesn't really decode BitStrings correctly, and wldap32 will internally treat it as 'O' Octet string. + // In order to match behavior, in Linux we will interpret 'B' as 'O' when passing the call to libldap. + + int error = 0; + // return berval + byte[] byteArray = DecodingByteArrayHelper(berElement, 'O', ref error); + if (!BerPal.IsBerDecodeError(error)) + { + // add result to the list + resultList.Add(byteArray); + } + + return error; + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Windows.cs new file mode 100644 index 0000000000000..88e4f250bc30d --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Windows.cs @@ -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.Collections; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.DirectoryServices.Protocols +{ + public static partial class BerConverter + { + private static unsafe int DecodeBitStringHelper(ArrayList resultList, SafeBerHandle berElement) + { + int error; + // return a bitstring and its length + IntPtr ptrResult = IntPtr.Zero; + int length = 0; + error = BerPal.ScanNextBitString(berElement, "B", ref ptrResult, ref length); + + if (!BerPal.IsBerDecodeError(error)) + { + byte[] byteArray = null; + if (ptrResult != IntPtr.Zero) + { + byteArray = new byte[length]; + Marshal.Copy(ptrResult, byteArray, 0, length); + } + resultList.Add(byteArray); + } + else + { + Debug.WriteLine("ber_scanf for format character 'B' failed"); + } + + // no need to free memory as wldap32 returns the original pointer instead of a duplicating memory pointer that + // needs to be freed + return error; + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs index 65599433b1a7f..dde428136c77e 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs @@ -2,15 +2,14 @@ // 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.Collections; using System.Diagnostics; -using System.Globalization; using System.Runtime.InteropServices; -using System.Collections; using System.Text; namespace System.DirectoryServices.Protocols { - public static class BerConverter + public static partial class BerConverter { public static byte[] Encode(string format, params object[] value) { @@ -27,7 +26,7 @@ public static byte[] Encode(string format, params object[] value) Debug.WriteLine("Begin encoding\n"); // allocate the berelement - BerSafeHandle berElement = new BerSafeHandle(); + SafeBerHandle berElement = new SafeBerHandle(); int valueCount = 0; int error = 0; @@ -37,7 +36,7 @@ public static byte[] Encode(string format, params object[] value) if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n') { // no argument needed - error = Wldap32.ber_printf_emptyarg(berElement, new string(fmt, 1)); + error = BerPal.PrintEmptyArgument(berElement, new string(fmt, 1)); } else if (fmt == 't' || fmt == 'i' || fmt == 'e') { @@ -56,7 +55,7 @@ public static byte[] Encode(string format, params object[] value) } // one int argument - error = Wldap32.ber_printf_int(berElement, new string(fmt, 1), (int)value[valueCount]); + error = BerPal.PrintInt(berElement, new string(fmt, 1), (int)value[valueCount]); // increase the value count valueCount++; @@ -78,7 +77,7 @@ public static byte[] Encode(string format, params object[] value) } // one int argument - error = Wldap32.ber_printf_int(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0); + error = BerPal.PrintInt(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0); // increase the value count valueCount++; @@ -220,7 +219,7 @@ public static byte[] Encode(string format, params object[] value) { // can't use SafeBerval here as CLR creates a SafeBerval which points to a different memory location, but when doing memory // deallocation, wldap has special check. So have to use IntPtr directly here. - error = Wldap32.ber_flatten(berElement, ref flattenptr); + error = BerPal.FlattenBerElement(berElement, ref flattenptr); if (error == -1) { @@ -247,7 +246,7 @@ public static byte[] Encode(string format, params object[] value) finally { if (flattenptr != IntPtr.Zero) - Wldap32.ber_bvfree(flattenptr); + BerPal.FreeBerval(flattenptr); } return encodingResult; @@ -273,7 +272,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS UTF8Encoding utf8Encoder = new UTF8Encoding(false, true); berval berValue = new berval(); ArrayList resultList = new ArrayList(); - BerSafeHandle berElement = null; + SafeBerHandle berElement = null; object[] decodeResult = null; decodeSucceeded = false; @@ -292,7 +291,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS try { - berElement = new BerSafeHandle(berValue); + berElement = new SafeBerHandle(berValue); } finally { @@ -307,17 +306,17 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS char fmt = format[formatCount]; if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n' || fmt == 'x') { - error = Wldap32.ber_scanf(berElement, new string(fmt, 1)); + error = BerPal.ScanNext(berElement, new string(fmt, 1)); - if (error != 0) + if (BerPal.IsBerDecodeError(error)) Debug.WriteLine("ber_scanf for {, }, [, ], n or x failed"); } else if (fmt == 'i' || fmt == 'e' || fmt == 'b') { int result = 0; - error = Wldap32.ber_scanf_int(berElement, new string(fmt, 1), ref result); + error = BerPal.ScanNextInt(berElement, new string(fmt, 1), ref result); - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { if (fmt == 'b') { @@ -341,7 +340,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS { // return a string byte[] byteArray = DecodingByteArrayHelper(berElement, 'O', ref error); - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { string s = null; if (byteArray != null) @@ -354,7 +353,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS { // return berval byte[] byteArray = DecodingByteArrayHelper(berElement, fmt, ref error); - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { // add result to the list resultList.Add(byteArray); @@ -362,26 +361,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS } else if (fmt == 'B') { - // return a bitstring and its length - IntPtr ptrResult = IntPtr.Zero; - int length = 0; - error = Wldap32.ber_scanf_bitstring(berElement, "B", ref ptrResult, ref length); - - if (error == 0) - { - byte[] byteArray = null; - if (ptrResult != IntPtr.Zero) - { - byteArray = new byte[length]; - Marshal.Copy(ptrResult, byteArray, 0, length); - } - resultList.Add(byteArray); - } - else - Debug.WriteLine("ber_scanf for format character 'B' failed"); - - // no need to free memory as wldap32 returns the original pointer instead of a duplicating memory pointer that - // needs to be freed + error = DecodeBitStringHelper(resultList, berElement); } else if (fmt == 'v') { @@ -390,7 +370,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS string[] stringArray = null; byteArrayresult = DecodingMultiByteArrayHelper(berElement, 'V', ref error); - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { if (byteArrayresult != null) { @@ -416,7 +396,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS byte[][] result = null; result = DecodingMultiByteArrayHelper(berElement, fmt, ref error); - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { resultList.Add(result); } @@ -427,7 +407,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS throw new ArgumentException(SR.BerConverterUndefineChar); } - if (error != 0) + if (BerPal.IsBerDecodeError(error)) { // decode failed, just return return decodeResult; @@ -444,7 +424,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS return decodeResult; } - private static int EncodingByteArrayHelper(BerSafeHandle berElement, byte[] tempValue, char fmt) + private static int EncodingByteArrayHelper(SafeBerHandle berElement, byte[] tempValue, char fmt) { int error = 0; @@ -454,18 +434,18 @@ private static int EncodingByteArrayHelper(BerSafeHandle berElement, byte[] temp IntPtr tmp = Marshal.AllocHGlobal(tempValue.Length); Marshal.Copy(tempValue, 0, tmp, tempValue.Length); HGlobalMemHandle memHandle = new HGlobalMemHandle(tmp); - - error = Wldap32.ber_printf_bytearray(berElement, new string(fmt, 1), memHandle, tempValue.Length); + error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, tempValue.Length); } else { - error = Wldap32.ber_printf_bytearray(berElement, new string(fmt, 1), new HGlobalMemHandle(IntPtr.Zero), 0); + HGlobalMemHandle memHandle = new HGlobalMemHandle(HGlobalMemHandle._dummyPointer); + error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, 0); } return error; } - private static byte[] DecodingByteArrayHelper(BerSafeHandle berElement, char fmt, ref int error) + private static byte[] DecodingByteArrayHelper(SafeBerHandle berElement, char fmt, ref int error) { error = 0; IntPtr result = IntPtr.Zero; @@ -474,11 +454,11 @@ private static byte[] DecodingByteArrayHelper(BerSafeHandle berElement, char fmt // can't use SafeBerval here as CLR creates a SafeBerval which points to a different memory location, but when doing memory // deallocation, wldap has special check. So have to use IntPtr directly here. - error = Wldap32.ber_scanf_ptr(berElement, new string(fmt, 1), ref result); + error = BerPal.ScanNextPtr(berElement, new string(fmt, 1), ref result); try { - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { if (result != IntPtr.Zero) { @@ -494,17 +474,17 @@ private static byte[] DecodingByteArrayHelper(BerSafeHandle berElement, char fmt finally { if (result != IntPtr.Zero) - Wldap32.ber_bvfree(result); + BerPal.FreeBerval(result); } return byteArray; } - private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[][] tempValue, char fmt) + private static int EncodingMultiByteArrayHelper(SafeBerHandle berElement, byte[][] tempValue, char fmt) { IntPtr berValArray = IntPtr.Zero; IntPtr tempPtr = IntPtr.Zero; - SafeBerval[] managedBerVal = null; + berval[] managedBervalArray = null; int error = 0; try @@ -513,31 +493,26 @@ private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[] { int i = 0; berValArray = Utility.AllocHGlobalIntPtrArray(tempValue.Length + 1); - int structSize = Marshal.SizeOf(typeof(SafeBerval)); - managedBerVal = new SafeBerval[tempValue.Length]; + int structSize = Marshal.SizeOf(typeof(berval)); + managedBervalArray = new berval[tempValue.Length]; for (i = 0; i < tempValue.Length; i++) { byte[] byteArray = tempValue[i]; // construct the managed berval - managedBerVal[i] = new SafeBerval(); + managedBervalArray[i] = new berval(); - if (byteArray == null) - { - managedBerVal[i].bv_len = 0; - managedBerVal[i].bv_val = IntPtr.Zero; - } - else + if (byteArray != null) { - managedBerVal[i].bv_len = byteArray.Length; - managedBerVal[i].bv_val = Marshal.AllocHGlobal(byteArray.Length); - Marshal.Copy(byteArray, 0, managedBerVal[i].bv_val, byteArray.Length); + managedBervalArray[i].bv_len = byteArray.Length; + managedBervalArray[i].bv_val = Marshal.AllocHGlobal(byteArray.Length); + Marshal.Copy(byteArray, 0, managedBervalArray[i].bv_val, byteArray.Length); } // allocate memory for the unmanaged structure IntPtr valPtr = Marshal.AllocHGlobal(structSize); - Marshal.StructureToPtr(managedBerVal[i], valPtr, false); + Marshal.StructureToPtr(managedBervalArray[i], valPtr, false); tempPtr = (IntPtr)((long)berValArray + IntPtr.Size * i); Marshal.WriteIntPtr(tempPtr, valPtr); @@ -547,9 +522,7 @@ private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[] Marshal.WriteIntPtr(tempPtr, IntPtr.Zero); } - error = Wldap32.ber_printf_berarray(berElement, new string(fmt, 1), berValArray); - - GC.KeepAlive(managedBerVal); + error = BerPal.PrintBerArray(berElement, new string(fmt, 1), berValArray); } finally { @@ -563,12 +536,22 @@ private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[] } Marshal.FreeHGlobal(berValArray); } + if (managedBervalArray != null) + { + foreach (berval managedBerval in managedBervalArray) + { + if (managedBerval.bv_val != IntPtr.Zero) + { + Marshal.FreeHGlobal(managedBerval.bv_val); + } + } + } } return error; } - private static byte[][] DecodingMultiByteArrayHelper(BerSafeHandle berElement, char fmt, ref int error) + private static byte[][] DecodingMultiByteArrayHelper(SafeBerHandle berElement, char fmt, ref int error) { error = 0; // several berval @@ -580,9 +563,9 @@ private static byte[][] DecodingMultiByteArrayHelper(BerSafeHandle berElement, c try { - error = Wldap32.ber_scanf_ptr(berElement, new string(fmt, 1), ref ptrResult); + error = BerPal.ScanNextPtr(berElement, new string(fmt, 1), ref ptrResult); - if (error == 0) + if (!BerPal.IsBerDecodeError(error)) { if (ptrResult != IntPtr.Zero) { @@ -615,7 +598,7 @@ private static byte[][] DecodingMultiByteArrayHelper(BerSafeHandle berElement, c { if (ptrResult != IntPtr.Zero) { - Wldap32.ber_bvecfree(ptrResult); + BerPal.FreeBervalArray(ptrResult); } } diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs index 8a9efa373315d..ca22f76d9d0be 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs @@ -729,7 +729,7 @@ public override byte[] GetValue() Marshal.WriteIntPtr(tempPtr, IntPtr.Zero); bool critical = IsCritical; - int error = Wldap32.ldap_create_sort_control(UtilityHandle.GetHandle(), memHandle, critical ? (byte)1 : (byte)0, ref control); + int error = LdapPal.CreateDirectorySortControl(UtilityHandle.GetHandle(), memHandle, critical ? (byte)1 : (byte)0, ref control); if (error != 0) { @@ -759,7 +759,7 @@ public override byte[] GetValue() { if (control != IntPtr.Zero) { - Wldap32.ldap_control_free(control); + LdapPal.FreeDirectoryControl(control); } if (memHandle != IntPtr.Zero) diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs new file mode 100644 index 0000000000000..6383c1c0446a5 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs @@ -0,0 +1,78 @@ +// 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.Diagnostics; +using System.Net; +using System.Runtime.InteropServices; + +namespace System.DirectoryServices.Protocols +{ + public partial class LdapConnection + { + // Linux doesn't support setting FQDN so we mark the flag as if it is already set so we don't make a call to set it again. + private bool _setFQDNDone = true; + + private void InternalInitConnectionHandle(string hostname) => _ldapHandle = new ConnectionHandle(Interop.ldap_init(hostname, ((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber), _needDispose); + + private int InternalConnectToServer() + { + Debug.Assert(!_ldapHandle.IsInvalid); + // In Linux you don't have to call Connect after calling init. You directly call bind. + return 0; + } + + private int InternalBind(NetworkCredential tempCredential, SEC_WINNT_AUTH_IDENTITY_EX cred, BindMethod method) + { + int error; + if (tempCredential == null && (AuthType == AuthType.External || AuthType == AuthType.Kerberos)) + { + error = BindSasl(); + } + else + { + error = Interop.ldap_simple_bind(_ldapHandle, cred.user, cred.password); + } + + return error; + } + + private int BindSasl() + { + SaslDefaultCredentials defaults = GetSaslDefaults(); + IntPtr ptrToDefaults = Marshal.AllocHGlobal(Marshal.SizeOf(defaults)); + Marshal.StructureToPtr(defaults, ptrToDefaults, false); + try + { + return Interop.ldap_sasl_interactive_bind(_ldapHandle, null, Interop.KerberosDefaultMechanism, IntPtr.Zero, IntPtr.Zero, Interop.LDAP_SASL_QUIET, LdapPal.SaslInteractionProcedure, ptrToDefaults); + } + finally + { + GC.KeepAlive(defaults); //Making sure we keep it in scope as we will still use ptrToDefaults + Marshal.FreeHGlobal(ptrToDefaults); + } + } + + private SaslDefaultCredentials GetSaslDefaults() + { + var defaults = new SaslDefaultCredentials { mech = Interop.KerberosDefaultMechanism }; + IntPtr outValue = IntPtr.Zero; + int error = Interop.ldap_get_option_ptr(_ldapHandle, LdapOption.LDAP_OPT_X_SASL_REALM, ref outValue); + if (error == 0 && outValue != IntPtr.Zero) + { + defaults.realm = Marshal.PtrToStringAnsi(outValue); + } + error = Interop.ldap_get_option_ptr(_ldapHandle, LdapOption.LDAP_OPT_X_SASL_AUTHCID, ref outValue); + if (error == 0 && outValue != IntPtr.Zero) + { + defaults.authcid = Marshal.PtrToStringAnsi(outValue); + } + error = Interop.ldap_get_option_ptr(_ldapHandle, LdapOption.LDAP_OPT_X_SASL_AUTHZID, ref outValue); + if (error == 0 && outValue != IntPtr.Zero) + { + defaults.authzid = Marshal.PtrToStringAnsi(outValue); + } + return defaults; + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Windows.cs new file mode 100644 index 0000000000000..6ae5eb96143f6 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Windows.cs @@ -0,0 +1,43 @@ +// 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.Diagnostics; +using System.Net; + +namespace System.DirectoryServices.Protocols +{ + public partial class LdapConnection + { + private bool _setFQDNDone = false; + + private void InternalInitConnectionHandle(string hostname) + { + LdapDirectoryIdentifier directoryIdentifier = _directoryIdentifier as LdapDirectoryIdentifier; + + // User wants to setup a connectionless session with server. + if (directoryIdentifier.Connectionless) + { + _ldapHandle = new ConnectionHandle(Interop.cldap_open(hostname, directoryIdentifier.PortNumber), _needDispose); + } + else + { + _ldapHandle = new ConnectionHandle(Interop.ldap_init(hostname, directoryIdentifier.PortNumber), _needDispose); + } + } + + private int InternalConnectToServer() + { + // Connect explicitly to the server. + var timeout = new LDAP_TIMEVAL() + { + tv_sec = (int)(_connectionTimeOut.Ticks / TimeSpan.TicksPerSecond) + }; + Debug.Assert(!_ldapHandle.IsInvalid); + return Interop.ldap_connect(_ldapHandle, timeout); + } + + private int InternalBind(NetworkCredential tempCredential, SEC_WINNT_AUTH_IDENTITY_EX cred, BindMethod method) + => tempCredential == null && AuthType == AuthType.External ? Interop.ldap_bind_s(_ldapHandle, null, null, method) : Interop.ldap_bind_s(_ldapHandle, null, cred, method); + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs index eef1bd29f8210..c66383e6d8a97 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs @@ -12,6 +12,7 @@ using System.Xml; using System.Threading; using System.Security.Cryptography.X509Certificates; +using System.Diagnostics.CodeAnalysis; namespace System.DirectoryServices.Protocols { @@ -20,7 +21,7 @@ namespace System.DirectoryServices.Protocols [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate bool QUERYCLIENTCERT(IntPtr Connection, IntPtr trusted_CAs, ref IntPtr certificateHandle); - public class LdapConnection : DirectoryConnection, IDisposable + public partial class LdapConnection : DirectoryConnection, IDisposable { internal enum LdapResult { @@ -48,7 +49,6 @@ internal enum LdapResult private static readonly LdapPartialResultsProcessor s_partialResultsProcessor = null; private static readonly ManualResetEvent s_waitHandle = null; private static readonly PartialResultsRetriever s_retriever = null; - private bool _setFQDNDone = false; internal bool _needDispose = true; private bool _connected = false; internal QUERYCLIENTCERT _clientCertificateRoutine = null; @@ -216,15 +216,7 @@ internal void Init() } } - // User wants to setup a connectionless session with server. - if (((LdapDirectoryIdentifier)_directoryIdentifier).Connectionless == true) - { - _ldapHandle = new ConnectionHandle(Wldap32.cldap_open(hostname, ((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber), _needDispose); - } - else - { - _ldapHandle = new ConnectionHandle(Wldap32.ldap_init(hostname, ((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber), _needDispose); - } + InternalInitConnectionHandle(hostname); // Create a WeakReference object with the target of ldapHandle and put it into our handle table. lock (s_objectLock) @@ -303,7 +295,7 @@ public DirectoryResponse SendRequest(DirectoryRequest request, TimeSpan requestT if (error == 0) { // Success code but message is -1, unexpected. - error = Wldap32.LdapGetLastError(); + error = LdapPal.GetLastErrorFromConnection(_ldapHandle); } throw ConstructException(error, operation); @@ -406,7 +398,7 @@ public IAsyncResult BeginSendRequest(DirectoryRequest request, TimeSpan requestT if (error == 0) { // Success code but message is -1, unexpected. - error = Wldap32.LdapGetLastError(); + error = LdapPal.GetLastErrorFromConnection(_ldapHandle); } throw ConstructException(error, operation); @@ -476,7 +468,7 @@ public void Abort(IAsyncResult asyncResult) } // Cancel the request. - Wldap32.ldap_abandon(_ldapHandle, messageId); + LdapPal.CancelDirectoryAsyncOperation(_ldapHandle, messageId); LdapRequestState resultObject = result._resultObject; if (resultObject != null) @@ -634,17 +626,18 @@ private int SendRequestHelper(DirectoryRequest request, ref int messageID) if (request is DeleteRequest) { // It is an delete operation. - error = Wldap32.ldap_delete_ext(_ldapHandle, ((DeleteRequest)request).DistinguishedName, serverControlArray, clientControlArray, ref messageID); + error = LdapPal.DeleteDirectoryEntry(_ldapHandle, ((DeleteRequest)request).DistinguishedName, serverControlArray, clientControlArray, ref messageID); } else if (request is ModifyDNRequest) { // It is a modify dn operation - error = Wldap32.ldap_rename(_ldapHandle, - ((ModifyDNRequest)request).DistinguishedName, - ((ModifyDNRequest)request).NewName, - ((ModifyDNRequest)request).NewParentDistinguishedName, - ((ModifyDNRequest)request).DeleteOldRdn ? 1 : 0, - serverControlArray, clientControlArray, ref messageID); + error = LdapPal.RenameDirectoryEntry( + _ldapHandle, + ((ModifyDNRequest)request).DistinguishedName, + ((ModifyDNRequest)request).NewName, + ((ModifyDNRequest)request).NewParentDistinguishedName, + ((ModifyDNRequest)request).DeleteOldRdn ? 1 : 0, + serverControlArray, clientControlArray, ref messageID); } else if (request is CompareRequest compareRequest) { @@ -680,12 +673,13 @@ private int SendRequestHelper(DirectoryRequest request, ref int messageID) } // It is a compare request. - error = Wldap32.ldap_compare(_ldapHandle, - ((CompareRequest)request).DistinguishedName, - assertion.Name, - stringValue, - berValuePtr, - serverControlArray, clientControlArray, ref messageID); + error = LdapPal.CompareDirectoryEntries( + _ldapHandle, + ((CompareRequest)request).DistinguishedName, + assertion.Name, + stringValue, + berValuePtr, + serverControlArray, clientControlArray, ref messageID); } else if (request is AddRequest || request is ModifyRequest) { @@ -715,17 +709,19 @@ private int SendRequestHelper(DirectoryRequest request, ref int messageID) if (request is AddRequest) { - error = Wldap32.ldap_add(_ldapHandle, - ((AddRequest)request).DistinguishedName, - modArray, - serverControlArray, clientControlArray, ref messageID); + error = LdapPal.AddDirectoryEntry( + _ldapHandle, + ((AddRequest)request).DistinguishedName, + modArray, + serverControlArray, clientControlArray, ref messageID); } else { - error = Wldap32.ldap_modify(_ldapHandle, - ((ModifyRequest)request).DistinguishedName, - modArray, - serverControlArray, clientControlArray, ref messageID); + error = LdapPal.ModifyDirectoryEntry( + _ldapHandle, + ((ModifyRequest)request).DistinguishedName, + modArray, + serverControlArray, clientControlArray, ref messageID); } } else if (request is ExtendedRequest extendedRequest) @@ -744,10 +740,11 @@ private int SendRequestHelper(DirectoryRequest request, ref int messageID) Marshal.Copy(val, 0, berValuePtr.bv_val, val.Length); } - error = Wldap32.ldap_extended_operation(_ldapHandle, - name, - berValuePtr, - serverControlArray, clientControlArray, ref messageID); + error = LdapPal.ExtendedDirectoryOperation( + _ldapHandle, + name, + berValuePtr, + serverControlArray, clientControlArray, ref messageID); } else if (request is SearchRequest searchRequest) { @@ -772,7 +769,7 @@ private int SendRequestHelper(DirectoryRequest request, ref int messageID) int i = 0; for (i = 0; i < attributeCount; i++) { - IntPtr controlPtr = Marshal.StringToHGlobalUni(searchRequest.Attributes[i]); + IntPtr controlPtr = LdapPal.StringToPtr(searchRequest.Attributes[i]); tempPtr = (IntPtr)((long)searchAttributes + IntPtr.Size * i); Marshal.WriteIntPtr(tempPtr, controlPtr); } @@ -793,17 +790,18 @@ private int SendRequestHelper(DirectoryRequest request, ref int messageID) try { - error = Wldap32.ldap_search(_ldapHandle, - searchRequest.DistinguishedName, - searchScope, - searchRequestFilter, - searchAttributes, - searchRequest.TypesOnly, - serverControlArray, - clientControlArray, - searchTimeLimit, - searchRequest.SizeLimit, - ref messageID); + error = LdapPal.SearchDirectory( + _ldapHandle, + searchRequest.DistinguishedName, + searchScope, + searchRequestFilter, + searchAttributes, + searchRequest.TypesOnly, + serverControlArray, + clientControlArray, + searchTimeLimit, + searchRequest.SizeLimit, + ref messageID); } finally { @@ -1006,7 +1004,7 @@ private void Connect() // Set the certificate callback routine here if user adds the certifcate to the certificate collection. if (ClientCertificates.Count != 0) { - int certError = Wldap32.ldap_set_option_clientcert(_ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _clientCertificateRoutine); + int certError = LdapPal.SetClientCertOption(_ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _clientCertificateRoutine); if (certError != (int)ResultCode.Success) { if (Utility.IsLdapError((LdapError)certError)) @@ -1025,19 +1023,13 @@ private void Connect() // Set the LDAP_OPT_AREC_EXCLUSIVE flag if necessary. if (((LdapDirectoryIdentifier)Directory).FullyQualifiedDnsHostName && !_setFQDNDone) { - SessionOptions.FQDN = true; + SessionOptions.SetFqdnRequired(); _setFQDNDone = true; } - // Connect explicitly to the server. - var timeout = new LDAP_TIMEVAL() - { - tv_sec = (int)(_connectionTimeOut.Ticks / TimeSpan.TicksPerSecond) - }; - Debug.Assert(!_ldapHandle.IsInvalid); - int error = Wldap32.ldap_connect(_ldapHandle, timeout); + int error = InternalConnectToServer(); - // Filed, throw an exception. + // Failed, throw an exception. if (error != (int)ResultCode.Success) { if (Utility.IsLdapError((LdapError)error)) @@ -1106,7 +1098,7 @@ private void BindHelper(NetworkCredential newCredential, bool needSetCredential) int error; if (AuthType == AuthType.Anonymous) { - error = Wldap32.ldap_simple_bind_s(_ldapHandle, null, null); + error = LdapPal.BindToDirectory(_ldapHandle, null, null); } else if (AuthType == AuthType.Basic) { @@ -1118,19 +1110,19 @@ private void BindHelper(NetworkCredential newCredential, bool needSetCredential) } tempDomainName.Append(username); - error = Wldap32.ldap_simple_bind_s(_ldapHandle, tempDomainName.ToString(), password); + error = LdapPal.BindToDirectory(_ldapHandle, tempDomainName.ToString(), password); } else { var cred = new SEC_WINNT_AUTH_IDENTITY_EX() { - version = Wldap32.SEC_WINNT_AUTH_IDENTITY_VERSION, + version = Interop.SEC_WINNT_AUTH_IDENTITY_VERSION, length = Marshal.SizeOf(typeof(SEC_WINNT_AUTH_IDENTITY_EX)), - flags = Wldap32.SEC_WINNT_AUTH_IDENTITY_UNICODE + flags = Interop.SEC_WINNT_AUTH_IDENTITY_UNICODE }; if (AuthType == AuthType.Kerberos) { - cred.packageList = Wldap32.MICROSOFT_KERBEROS_NAME_W; + cred.packageList = Interop.MICROSOFT_KERBEROS_NAME_W; cred.packageListLength = cred.packageList.Length; } @@ -1173,14 +1165,7 @@ private void BindHelper(NetworkCredential newCredential, bool needSetCredential) break; } - if (tempCredential == null && AuthType == AuthType.External) - { - error = Wldap32.ldap_bind_s(_ldapHandle, null, null, method); - } - else - { - error = Wldap32.ldap_bind_s(_ldapHandle, null, cred, method); - } + error = InternalBind(tempCredential, cred, method); } // Failed, throw exception. @@ -1275,7 +1260,7 @@ internal LdapControl[] BuildControlArray(DirectoryControlCollection controls, bo managedControls[i] = new LdapControl() { // Get the control type. - ldctl_oid = Marshal.StringToHGlobalUni(((DirectoryControl)controlList[i]).Type), + ldctl_oid = LdapPal.StringToPtr(((DirectoryControl)controlList[i]).Type), // Get the control cricality. ldctl_iscritical = ((DirectoryControl)controlList[i]).IsCritical @@ -1358,7 +1343,7 @@ internal LdapMod[] BuildAttributes(CollectionBase directoryAttributes, ArrayList attributes[i].type |= LDAP_MOD_BVALUES; // Write the attribute name. - attributes[i].attribute = Marshal.StringToHGlobalUni(modAttribute.Name); + attributes[i].attribute = LdapPal.StringToPtr(modAttribute.Name); // Write the values. int valuesCount = 0; @@ -1451,7 +1436,7 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat needAbandon = false; } - int error = Wldap32.ldap_result(_ldapHandle, messageId, (int)resultType, timeout, ref ldapResult); + int error = LdapPal.GetResultFromAsyncOperation(_ldapHandle, messageId, (int)resultType, timeout, ref ldapResult); if (error != -1 && error != 0) { // parsing the result @@ -1499,13 +1484,13 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat response = new ExtendedResponse(responseDn, responseControl, (ResultCode)resultError, responseMessage, responseReferral); if (resultError == (int)ResultCode.Success) { - resultError = Wldap32.ldap_parse_extended_result(_ldapHandle, ldapResult, ref requestName, ref requestValue, 0 /*not free it*/); + resultError = LdapPal.ParseExtendedResult(_ldapHandle, ldapResult, ref requestName, ref requestValue, 0 /*not free it*/); if (resultError == 0) { string name = null; if (requestName != IntPtr.Zero) { - name = Marshal.PtrToStringUni(requestName); + name = LdapPal.PtrToString(requestName); } berval val = null; @@ -1542,7 +1527,7 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat SearchResultReferenceCollection searchResultReferences = new SearchResultReferenceCollection(); // parsing the resultentry - entryMessage = Wldap32.ldap_first_entry(_ldapHandle, ldapResult); + entryMessage = LdapPal.GetFirstEntryFromResult(_ldapHandle, ldapResult); int entrycount = 0; while (entryMessage != IntPtr.Zero) @@ -1554,11 +1539,11 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat } entrycount++; - entryMessage = Wldap32.ldap_next_entry(_ldapHandle, entryMessage); + entryMessage = LdapPal.GetNextEntryFromResult(_ldapHandle, entryMessage); } // Parse the reference. - IntPtr referenceMessage = Wldap32.ldap_first_reference(_ldapHandle, ldapResult); + IntPtr referenceMessage = LdapPal.GetFirstReferenceFromResult(_ldapHandle, ldapResult); while (referenceMessage != IntPtr.Zero) { @@ -1568,7 +1553,7 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat searchResultReferences.Add(reference); } - referenceMessage = Wldap32.ldap_next_reference(_ldapHandle, referenceMessage); + referenceMessage = LdapPal.GetNextReferenceFromResult(_ldapHandle, referenceMessage); } ((SearchResponse)response).Entries = searchResultEntries; @@ -1601,17 +1586,17 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat { if (requestName != IntPtr.Zero) { - Wldap32.ldap_memfree(requestName); + LdapPal.FreeMemory(requestName); } if (requestValue != IntPtr.Zero) { - Wldap32.ldap_memfree(requestValue); + LdapPal.FreeMemory(requestValue); } if (ldapResult != IntPtr.Zero) { - Wldap32.ldap_msgfree(ldapResult); + LdapPal.FreeMemory(ldapResult); } } } @@ -1634,13 +1619,13 @@ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operat } else { - error = Wldap32.LdapGetLastError(); + error = LdapPal.GetLastErrorFromConnection(_ldapHandle); } // Abandon the request. if (needAbandon) { - Wldap32.ldap_abandon(_ldapHandle, messageId); + LdapPal.CancelDirectoryAsyncOperation(_ldapHandle, messageId); } } @@ -1657,15 +1642,15 @@ internal unsafe int ConstructParsedResult(IntPtr ldapResult, ref int serverError try { - int resultError = Wldap32.ldap_parse_result(_ldapHandle, ldapResult, ref serverError, ref dn, ref message, ref referral, ref control, 0 /* not free it */); + int resultError = LdapPal.ParseResult(_ldapHandle, ldapResult, ref serverError, ref dn, ref message, ref referral, ref control, 0 /* not free it */); if (resultError == 0) { // Parse the dn. - responseDn = Marshal.PtrToStringUni(dn); + responseDn = LdapPal.PtrToString(dn); // Parse the message. - responseMessage = Marshal.PtrToStringUni(message); + responseMessage = LdapPal.PtrToString(message); // Parse the referral. if (referral != IntPtr.Zero) @@ -1676,7 +1661,7 @@ internal unsafe int ConstructParsedResult(IntPtr ldapResult, ref int serverError var referralList = new ArrayList(); while (singleReferral != null) { - string s = Marshal.PtrToStringUni((IntPtr)singleReferral); + string s = LdapPal.PtrToString((IntPtr)singleReferral); referralList.Add(s); i++; @@ -1718,7 +1703,7 @@ internal unsafe int ConstructParsedResult(IntPtr ldapResult, ref int serverError // we need to take care of one special case, when can't connect to the server, ldap_parse_result fails with local error if (resultError == (int)LdapError.LocalError) { - int tmpResult = Wldap32.ldap_result2error(_ldapHandle, ldapResult, 0 /* not free it */); + int tmpResult = LdapPal.ResultToErrorCode(_ldapHandle, ldapResult, 0 /* not free it */); if (tmpResult != 0) { resultError = tmpResult; @@ -1732,22 +1717,22 @@ internal unsafe int ConstructParsedResult(IntPtr ldapResult, ref int serverError { if (dn != IntPtr.Zero) { - Wldap32.ldap_memfree(dn); + LdapPal.FreeMemory(dn); } if (message != IntPtr.Zero) { - Wldap32.ldap_memfree(message); + LdapPal.FreeMemory(message); } if (referral != IntPtr.Zero) { - Wldap32.ldap_value_free(referral); + LdapPal.FreeValue(referral); } if (control != IntPtr.Zero) { - Wldap32.ldap_controls_free(control); + LdapPal.FreeDirectoryControls(control); } } } @@ -1762,11 +1747,11 @@ internal SearchResultEntry ConstructEntry(IntPtr entryMessage) { // Get the dn. string entryDn = null; - dn = Wldap32.ldap_get_dn(_ldapHandle, entryMessage); + dn = LdapPal.GetDistinguishedName(_ldapHandle, entryMessage); if (dn != IntPtr.Zero) { - entryDn = Marshal.PtrToStringUni(dn); - Wldap32.ldap_memfree(dn); + entryDn = LdapPal.PtrToString(dn); + LdapPal.FreeMemory(dn); dn = IntPtr.Zero; } @@ -1774,7 +1759,7 @@ internal SearchResultEntry ConstructEntry(IntPtr entryMessage) SearchResultAttributeCollection attributes = resultEntry.Attributes; // Get attributes. - attribute = Wldap32.ldap_first_attribute(_ldapHandle, entryMessage, ref address); + attribute = LdapPal.GetFirstAttributeFromEntry(_ldapHandle, entryMessage, ref address); int tempcount = 0; while (attribute != IntPtr.Zero) @@ -1782,14 +1767,14 @@ internal SearchResultEntry ConstructEntry(IntPtr entryMessage) DirectoryAttribute attr = ConstructAttribute(entryMessage, attribute); attributes.Add(attr.Name, attr); - Wldap32.ldap_memfree(attribute); + LdapPal.FreeMemory(attribute); tempcount++; - attribute = Wldap32.ldap_next_attribute(_ldapHandle, entryMessage, address); + attribute = LdapPal.GetNextAttributeFromResult(_ldapHandle, entryMessage, address); } if (address != IntPtr.Zero) { - Wldap32.ber_free(address, 0); + BerPal.FreeBerElement(address, 0); address = IntPtr.Zero; } @@ -1799,17 +1784,17 @@ internal SearchResultEntry ConstructEntry(IntPtr entryMessage) { if (dn != IntPtr.Zero) { - Wldap32.ldap_memfree(dn); + LdapPal.FreeMemory(dn); } if (attribute != IntPtr.Zero) { - Wldap32.ldap_memfree(attribute); + LdapPal.FreeMemory(attribute); } if (address != IntPtr.Zero) { - Wldap32.ber_free(address, 0); + BerPal.FreeBerElement(address, 0); } } } @@ -1821,10 +1806,9 @@ internal DirectoryAttribute ConstructAttribute(IntPtr entryMessage, IntPtr attri _isSearchResult = true }; - string name = Marshal.PtrToStringUni(attributeName); + string name = LdapPal.PtrToString(attributeName); attribute.Name = name; - - IntPtr valuesArray = Wldap32.ldap_get_values_len(_ldapHandle, entryMessage, name); + IntPtr valuesArray = LdapPal.GetValuesFromAttribute(_ldapHandle, entryMessage, name); try { if (valuesArray != IntPtr.Zero) @@ -1852,7 +1836,7 @@ internal DirectoryAttribute ConstructAttribute(IntPtr entryMessage, IntPtr attri { if (valuesArray != IntPtr.Zero) { - Wldap32.ldap_value_free_len(valuesArray); + LdapPal.FreeAttributes(valuesArray); } } @@ -1862,8 +1846,7 @@ internal DirectoryAttribute ConstructAttribute(IntPtr entryMessage, IntPtr attri internal SearchResultReference ConstructReference(IntPtr referenceMessage) { IntPtr referenceArray = IntPtr.Zero; - - int error = Wldap32.ldap_parse_reference(_ldapHandle, referenceMessage, ref referenceArray); + int error = LdapPal.ParseReference(_ldapHandle, referenceMessage, ref referenceArray); try { @@ -1877,14 +1860,14 @@ internal SearchResultReference ConstructReference(IntPtr referenceMessage) tempPtr = Marshal.ReadIntPtr(referenceArray, IntPtr.Size * count); while (tempPtr != IntPtr.Zero) { - string s = Marshal.PtrToStringUni(tempPtr); + string s = LdapPal.PtrToString(tempPtr); referralList.Add(s); count++; tempPtr = Marshal.ReadIntPtr(referenceArray, IntPtr.Size * count); } - Wldap32.ldap_value_free(referenceArray); + LdapPal.FreeValue(referenceArray); referenceArray = IntPtr.Zero; } @@ -1904,7 +1887,7 @@ internal SearchResultReference ConstructReference(IntPtr referenceMessage) { if (referenceArray != IntPtr.Zero) { - Wldap32.ldap_value_free(referenceArray); + LdapPal.FreeValue(referenceArray); } } @@ -1973,7 +1956,7 @@ private DirectoryControl ConstructControl(IntPtr controlPtr) Marshal.PtrToStructure(controlPtr, control); Debug.Assert(control.ldctl_oid != IntPtr.Zero); - string controlType = Marshal.PtrToStringUni(control.ldctl_oid); + string controlType = LdapPal.PtrToString(control.ldctl_oid); byte[] bytes = new byte[control.ldctl_value.bv_len]; Marshal.Copy(control.ldctl_value.bv_val, bytes, 0, control.ldctl_value.bv_len); diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs index 0477e494f9f2d..3d6b85838ca01 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs @@ -214,7 +214,7 @@ private void GetResultsHelper(LdapPartialAsyncResult asyncResult) asyncResult._resultStatus = ResultsStatus.Done; // Need to abandon this request. - Wldap32.ldap_abandon(connection._ldapHandle, asyncResult._messageID); + LdapPal.CancelDirectoryAsyncOperation(connection._ldapHandle, asyncResult._messageID); } } diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs new file mode 100644 index 0000000000000..209aa7447abd8 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs @@ -0,0 +1,17 @@ +// 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. + +namespace System.DirectoryServices.Protocols +{ + public partial class LdapSessionOptions + { + private static void PALCertFreeCRLContext(IntPtr certPtr) { /* No op */ } + + public bool SecureSocketLayer + { + get => throw new PlatformNotSupportedException(); + set => throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs new file mode 100644 index 0000000000000..e78154995ea79 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs @@ -0,0 +1,25 @@ +// 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. + +namespace System.DirectoryServices.Protocols +{ + public partial class LdapSessionOptions + { + private static void PALCertFreeCRLContext(IntPtr certPtr) => Interop.CertFreeCRLContext(certPtr); + + public bool SecureSocketLayer + { + get + { + int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_SSL); + return outValue == 1; + } + set + { + int temp = value ? 1 : 0; + SetIntValueHelper(LdapOption.LDAP_OPT_SSL, temp); + } + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs index 2ff8d02bc4eb2..e59d8352ab68e 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs @@ -116,7 +116,7 @@ internal struct SecurityHandle public IntPtr Upper; } - public class LdapSessionOptions + public partial class LdapSessionOptions { private readonly LdapConnection _connection = null; private ReferralCallback _callbackRoutine = new ReferralCallback(); @@ -155,20 +155,6 @@ public ReferralChasingOptions ReferralChasing } } - public bool SecureSocketLayer - { - get - { - int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_SSL); - return outValue == 1; - } - set - { - int temp = value ? 1 : 0; - SetIntValueHelper(LdapOption.LDAP_OPT_SSL, temp); - } - } - public int ReferralHopLimit { get => GetIntValueHelper(LdapOption.LDAP_OPT_REFERRAL_HOP_LIMIT); @@ -319,7 +305,7 @@ public SecurityPackageContextConnectionInformation SslInformation } var secInfo = new SecurityPackageContextConnectionInformation(); - int error = Wldap32.ldap_get_option_secInfo(_connection._ldapHandle, LdapOption.LDAP_OPT_SSL_INFO, secInfo); + int error = LdapPal.GetSecInfoOption(_connection._ldapHandle, LdapOption.LDAP_OPT_SSL_INFO, secInfo); ErrorChecking.CheckAndSetLdapError(error); return secInfo; @@ -337,7 +323,7 @@ public object SecurityContext SecurityHandle tempHandle = default; - int error = Wldap32.ldap_get_option_sechandle(_connection._ldapHandle, LdapOption.LDAP_OPT_SECURITY_CONTEXT, ref tempHandle); + int error = LdapPal.GetSecurityHandleOption(_connection._ldapHandle, LdapOption.LDAP_OPT_SECURITY_CONTEXT, ref tempHandle); ErrorChecking.CheckAndSetLdapError(error); return tempHandle; @@ -489,7 +475,7 @@ public QueryClientCertificateCallback QueryClientCertificate if (value != null) { - int certError = Wldap32.ldap_set_option_clientcert(_connection._ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _connection._clientCertificateRoutine); + int certError = LdapPal.SetClientCertOption(_connection._ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _connection._clientCertificateRoutine); if (certError != (int)ResultCode.Success) { if (Utility.IsLdapError((LdapError)certError)) @@ -531,7 +517,7 @@ public VerifyServerCertificateCallback VerifyServerCertificate if (value != null) { - int error = Wldap32.ldap_set_option_servercert(_connection._ldapHandle, LdapOption.LDAP_OPT_SERVER_CERTIFICATE, _serverCertificateRoutine); + int error = LdapPal.SetServerCertOption(_connection._ldapHandle, LdapOption.LDAP_OPT_SERVER_CERTIFICATE, _serverCertificateRoutine); ErrorChecking.CheckAndSetLdapError(error); } @@ -547,13 +533,9 @@ internal DereferenceAlias DerefAlias set => SetIntValueHelper(LdapOption.LDAP_OPT_DEREF, (int)value); } - internal bool FQDN + internal void SetFqdnRequired() { - set - { - // set the value to true - SetIntValueHelper(LdapOption.LDAP_OPT_AREC_EXCLUSIVE, 1); - } + SetIntValueHelper(LdapOption.LDAP_OPT_AREC_EXCLUSIVE, 1); } public void FastConcurrentBind() @@ -569,7 +551,7 @@ public void FastConcurrentBind() // Do the fast concurrent bind. int inValue = 1; - int error = Wldap32.ldap_set_option_int(_connection._ldapHandle, LdapOption.LDAP_OPT_FAST_CONCURRENT_BIND, ref inValue); + int error = LdapPal.SetIntOption(_connection._ldapHandle, LdapOption.LDAP_OPT_FAST_CONCURRENT_BIND, ref inValue); ErrorChecking.CheckAndSetLdapError(error); } @@ -629,11 +611,11 @@ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection contro Marshal.WriteIntPtr(tempPtr, IntPtr.Zero); } - int error = Wldap32.ldap_start_tls(_connection._ldapHandle, ref serverError, ref ldapResult, serverControlArray, clientControlArray); + int error = LdapPal.StartTls(_connection._ldapHandle, ref serverError, ref ldapResult, serverControlArray, clientControlArray); if (ldapResult != IntPtr.Zero) { // Parse the referral. - int resultError = Wldap32.ldap_parse_result_referral(_connection._ldapHandle, ldapResult, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref referral, IntPtr.Zero, 0 /* not free it */); + int resultError = LdapPal.ParseResultReferral(_connection._ldapHandle, ldapResult, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref referral, IntPtr.Zero, 0 /* not free it */); if (resultError == 0 && referral != IntPtr.Zero) { char** referralPtr = (char**)referral; @@ -642,7 +624,7 @@ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection contro ArrayList referralList = new ArrayList(); while (singleReferral != null) { - string s = Marshal.PtrToStringUni((IntPtr)singleReferral); + string s = LdapPal.PtrToString((IntPtr)singleReferral); referralList.Add(s); i++; @@ -652,7 +634,7 @@ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection contro // Free heap memory. if (referral != IntPtr.Zero) { - Wldap32.ldap_value_free(referral); + LdapPal.FreeValue(referral); referral = IntPtr.Zero; } @@ -759,7 +741,7 @@ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection contro if (referral != IntPtr.Zero) { - Wldap32.ldap_value_free(referral); + LdapPal.FreeValue(referral); } } } @@ -771,7 +753,7 @@ public void StopTransportLayerSecurity() throw new ObjectDisposedException(GetType().Name); } - byte result = Wldap32.ldap_stop_tls(_connection._ldapHandle); + byte result = LdapPal.StopTls(_connection._ldapHandle); if (result == 0) { throw new TlsOperationException(null, SR.TLSStopFailure); @@ -786,7 +768,7 @@ private int GetIntValueHelper(LdapOption option) } int outValue = 0; - int error = Wldap32.ldap_get_option_int(_connection._ldapHandle, option, ref outValue); + int error = LdapPal.GetIntOption(_connection._ldapHandle, option, ref outValue); ErrorChecking.CheckAndSetLdapError(error); return outValue; @@ -800,7 +782,7 @@ private void SetIntValueHelper(LdapOption option, int value) } int temp = value; - int error = Wldap32.ldap_set_option_int(_connection._ldapHandle, option, ref temp); + int error = LdapPal.SetIntOption(_connection._ldapHandle, option, ref temp); ErrorChecking.CheckAndSetLdapError(error); } @@ -813,18 +795,18 @@ private string GetStringValueHelper(LdapOption option, bool releasePtr) } IntPtr outValue = new IntPtr(0); - int error = Wldap32.ldap_get_option_ptr(_connection._ldapHandle, option, ref outValue); + int error = LdapPal.GetPtrOption(_connection._ldapHandle, option, ref outValue); ErrorChecking.CheckAndSetLdapError(error); string stringValue = null; if (outValue != IntPtr.Zero) { - stringValue = Marshal.PtrToStringUni(outValue); + stringValue = LdapPal.PtrToString(outValue); } if (releasePtr) { - Wldap32.ldap_memfree(outValue); + LdapPal.FreeMemory(outValue); } return stringValue; @@ -840,12 +822,12 @@ private void SetStringValueHelper(LdapOption option, string value) IntPtr inValue = IntPtr.Zero; if (value != null) { - inValue = Marshal.StringToHGlobalUni(value); + inValue = LdapPal.StringToPtr(value); } try { - int error = Wldap32.ldap_set_option_ptr(_connection._ldapHandle, option, ref inValue); + int error = LdapPal.SetPtrOption(_connection._ldapHandle, option, ref inValue); ErrorChecking.CheckAndSetLdapError(error); } finally @@ -866,8 +848,7 @@ private void ProcessCallBackRoutine(ReferralCallback tempCallback) notify = tempCallback.NotifyNewConnection == null ? null : _notifiyDelegate, dereference = tempCallback.DereferenceConnection == null ? null : _dereferenceDelegate }; - - int error = Wldap32.ldap_set_option_referral(_connection._ldapHandle, LdapOption.LDAP_OPT_REFERRAL_CALLBACK, ref value); + int error = LdapPal.SetReferralOption(_connection._ldapHandle, LdapOption.LDAP_OPT_REFERRAL_CALLBACK, ref value); ErrorChecking.CheckAndSetLdapError(error); } @@ -884,7 +865,7 @@ private int ProcessQueryConnection(IntPtr PrimaryConnection, IntPtr ReferralFrom { if (NewDNPtr != IntPtr.Zero) { - NewDN = Marshal.PtrToStringUni(NewDNPtr); + NewDN = LdapPal.PtrToString(NewDNPtr); } var target = new StringBuilder(); @@ -951,7 +932,7 @@ private bool ProcessNotifyConnection(IntPtr primaryConnection, IntPtr referralFr string newDN = null; if (newDNPtr != IntPtr.Zero) { - newDN = Marshal.PtrToStringUni(newDNPtr); + newDN = LdapPal.PtrToString(newDNPtr); } var target = new StringBuilder(); @@ -1099,7 +1080,7 @@ private bool ProcessServerCertificate(IntPtr connection, IntPtr serverCert) } finally { - Wldap32.CertFreeCRLContext(certPtr); + PALCertFreeCRLContext(certPtr); } value = _serverCertificateDelegate(_connection, certificate); diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs deleted file mode 100644 index 34605a49366b2..0000000000000 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs +++ /dev/null @@ -1,376 +0,0 @@ -// 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.Runtime.InteropServices; -using System.Security; - -namespace System.DirectoryServices.Protocols -{ - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal class Luid - { - private readonly int _lowPart; - private readonly int _highPart; - - public int LowPart => _lowPart; - public int HighPart => _highPart; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal sealed class SEC_WINNT_AUTH_IDENTITY_EX - { - public int version; - public int length; - public string user; - public int userLength; - public string domain; - public int domainLength; - public string password; - public int passwordLength; - public int flags; - public string packageList; - public int packageListLength; - } - - internal enum BindMethod : uint - { - LDAP_AUTH_OTHERKIND = 0x86, - LDAP_AUTH_SICILY = LDAP_AUTH_OTHERKIND | 0x0200, - LDAP_AUTH_MSN = LDAP_AUTH_OTHERKIND | 0x0800, - LDAP_AUTH_NTLM = LDAP_AUTH_OTHERKIND | 0x1000, - LDAP_AUTH_DPA = LDAP_AUTH_OTHERKIND | 0x2000, - LDAP_AUTH_NEGOTIATE = LDAP_AUTH_OTHERKIND | 0x0400, - LDAP_AUTH_SSPI = LDAP_AUTH_NEGOTIATE, - LDAP_AUTH_DIGEST = LDAP_AUTH_OTHERKIND | 0x4000, - LDAP_AUTH_EXTERNAL = LDAP_AUTH_OTHERKIND | 0x0020 - } - - internal enum LdapOption - { - LDAP_OPT_DESC = 0x01, - LDAP_OPT_DEREF = 0x02, - LDAP_OPT_SIZELIMIT = 0x03, - LDAP_OPT_TIMELIMIT = 0x04, - LDAP_OPT_REFERRALS = 0x08, - LDAP_OPT_RESTART = 0x09, - LDAP_OPT_SSL = 0x0a, - LDAP_OPT_REFERRAL_HOP_LIMIT = 0x10, - LDAP_OPT_VERSION = 0x11, - LDAP_OPT_API_FEATURE_INFO = 0x15, - LDAP_OPT_HOST_NAME = 0x30, - LDAP_OPT_ERROR_NUMBER = 0x31, - LDAP_OPT_ERROR_STRING = 0x32, - LDAP_OPT_SERVER_ERROR = 0x33, - LDAP_OPT_SERVER_EXT_ERROR = 0x34, - LDAP_OPT_HOST_REACHABLE = 0x3E, - LDAP_OPT_PING_KEEP_ALIVE = 0x36, - LDAP_OPT_PING_WAIT_TIME = 0x37, - LDAP_OPT_PING_LIMIT = 0x38, - LDAP_OPT_DNSDOMAIN_NAME = 0x3B, - LDAP_OPT_GETDSNAME_FLAGS = 0x3D, - LDAP_OPT_PROMPT_CREDENTIALS = 0x3F, - LDAP_OPT_TCP_KEEPALIVE = 0x40, - LDAP_OPT_FAST_CONCURRENT_BIND = 0x41, - LDAP_OPT_SEND_TIMEOUT = 0x42, - LDAP_OPT_REFERRAL_CALLBACK = 0x70, - LDAP_OPT_CLIENT_CERTIFICATE = 0x80, - LDAP_OPT_SERVER_CERTIFICATE = 0x81, - LDAP_OPT_AUTO_RECONNECT = 0x91, - LDAP_OPT_SSPI_FLAGS = 0x92, - LDAP_OPT_SSL_INFO = 0x93, - LDAP_OPT_SIGN = 0x95, - LDAP_OPT_ENCRYPT = 0x96, - LDAP_OPT_SASL_METHOD = 0x97, - LDAP_OPT_AREC_EXCLUSIVE = 0x98, - LDAP_OPT_SECURITY_CONTEXT = 0x99, - LDAP_OPT_ROOTDSE_CACHE = 0x9a - } - - internal enum ResultAll - { - LDAP_MSG_ALL = 1, - LDAP_MSG_RECEIVED = 2, - LDAP_MSG_POLLINGALL = 3 - } - - [StructLayout(LayoutKind.Sequential)] - internal sealed class LDAP_TIMEVAL - { - public int tv_sec; - public int tv_usec; - } - - [StructLayout(LayoutKind.Sequential)] - internal sealed class berval - { - public int bv_len = 0; - public IntPtr bv_val = IntPtr.Zero; - - public berval() { } - } - - [StructLayout(LayoutKind.Sequential)] - internal sealed class SafeBerval - { - public int bv_len = 0; - public IntPtr bv_val = IntPtr.Zero; - - ~SafeBerval() - { - if (bv_val != IntPtr.Zero) - { - Marshal.FreeHGlobal(bv_val); - } - } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal sealed class LdapControl - { - public IntPtr ldctl_oid = IntPtr.Zero; - public berval ldctl_value = null; - public bool ldctl_iscritical = false; - - public LdapControl() { } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct LdapReferralCallback - { - public int sizeofcallback; - public QUERYFORCONNECTIONInternal query; - public NOTIFYOFNEWCONNECTIONInternal notify; - public DEREFERENCECONNECTIONInternal dereference; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct CRYPTOAPI_BLOB - { - public int cbData; - public IntPtr pbData; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct SecPkgContext_IssuerListInfoEx - { - public IntPtr aIssuers; - public int cIssuers; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal sealed class LdapMod - { - public int type = 0; - public IntPtr attribute = IntPtr.Zero; - public IntPtr values = IntPtr.Zero; - - ~LdapMod() - { - if (attribute != IntPtr.Zero) - { - Marshal.FreeHGlobal(attribute); - } - - if (values != IntPtr.Zero) - { - Marshal.FreeHGlobal(values); - } - } - } - - internal class Wldap32 - { - private const string Wldap32dll = "wldap32.dll"; - - public const int SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2; - public const int SEC_WINNT_AUTH_IDENTITY_VERSION = 0x200; - public const string MICROSOFT_KERBEROS_NAME_W = "Kerberos"; - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_bind_sW", CharSet = CharSet.Unicode)] - public static extern int ldap_bind_s([In]ConnectionHandle ldapHandle, string dn, SEC_WINNT_AUTH_IDENTITY_EX credentials, BindMethod method); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_initW", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_init(string hostName, int portNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_connect", CharSet = CharSet.Unicode)] - public static extern int ldap_connect([In] ConnectionHandle ldapHandle, LDAP_TIMEVAL timeout); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_unbind", CharSet = CharSet.Unicode)] - public static extern int ldap_unbind([In] IntPtr ldapHandle); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_get_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_set_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int inValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_get_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_set_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr inValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_get_option_sechandle([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref SecurityHandle outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)] - public static extern int ldap_set_option_servercert([In] ConnectionHandle ldapHandle, [In] LdapOption option, VERIFYSERVERCERT outValue); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LdapGetLastError")] - public static extern int LdapGetLastError(); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "cldap_openW", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr cldap_open(string hostName, int portNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_simple_bind_sW", CharSet = CharSet.Unicode)] - public static extern int ldap_simple_bind_s([In] ConnectionHandle ldapHandle, string distinguishedName, string password); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_delete_extW", CharSet = CharSet.Unicode)] - public static extern int ldap_delete_ext([In] ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern int ldap_result([In] ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Mesage); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)] - public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)] - public static extern int ldap_parse_result_referral([In] ConnectionHandle ldapHandle, [In] IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_memfreeW", CharSet = CharSet.Unicode)] - public static extern void ldap_memfree([In] IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_freeW", CharSet = CharSet.Unicode)] - public static extern int ldap_value_free([In] IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_controls_freeW", CharSet = CharSet.Unicode)] - public static extern int ldap_controls_free([In] IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_abandon", CharSet = CharSet.Unicode)] - public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_start_tls_sW", CharSet = CharSet.Unicode)] - public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_stop_tls_s", CharSet = CharSet.Unicode)] - public static extern byte ldap_stop_tls(ConnectionHandle ldapHandle); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_rename_extW", CharSet = CharSet.Unicode)] - public static extern int ldap_rename([In] ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_compare_extW", CharSet = CharSet.Unicode)] - public static extern int ldap_compare([In] ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_add_extW", CharSet = CharSet.Unicode)] - public static extern int ldap_add([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_modify_extW", CharSet = CharSet.Unicode)] - public static extern int ldap_modify([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_extended_operationW", CharSet = CharSet.Unicode)] - public static extern int ldap_extended_operation([In] ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_extended_resultW", CharSet = CharSet.Unicode)] - public static extern int ldap_parse_extended_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_msgfree", CharSet = CharSet.Unicode)] - public static extern int ldap_msgfree([In] IntPtr result); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_search_extW", CharSet = CharSet.Unicode)] - public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_entry", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_entry", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_reference", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_reference", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_dnW", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_attributeW", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_first_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr address); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_attributeW", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_next_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, [In, Out] IntPtr address); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_free", CharSet = CharSet.Unicode)] - public static extern IntPtr ber_free([In] IntPtr berelement, int option); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_values_lenW", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_get_values_len([In] ConnectionHandle ldapHandle, [In] IntPtr result, string name); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Unicode)] - public static extern IntPtr ldap_value_free_len([In] IntPtr berelement); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_referenceW", CharSet = CharSet.Unicode)] - public static extern int ldap_parse_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr referrals); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_alloc_t", CharSet = CharSet.Unicode)] - public static extern IntPtr ber_alloc(int option); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] - public static extern int ber_printf_emptyarg(BerSafeHandle berElement, string format); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] - public static extern int ber_printf_int(BerSafeHandle berElement, string format, int value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] - public static extern int ber_printf_bytearray(BerSafeHandle berElement, string format, HGlobalMemHandle value, int length); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)] - public static extern int ber_printf_berarray(BerSafeHandle berElement, string format, IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)] - public static extern int ber_flatten(BerSafeHandle berElement, ref IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_init", CharSet = CharSet.Unicode)] - public static extern IntPtr ber_init(berval value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] - public static extern int ber_scanf(BerSafeHandle berElement, string format); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] - public static extern int ber_scanf_int(BerSafeHandle berElement, string format, ref int value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] - public static extern int ber_scanf_ptr(BerSafeHandle berElement, string format, ref IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)] - public static extern int ber_scanf_bitstring(BerSafeHandle berElement, string format, ref IntPtr value, ref int length); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)] - public static extern int ber_bvfree(IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvecfree", CharSet = CharSet.Unicode)] - public static extern int ber_bvecfree(IntPtr value); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_create_sort_controlW", CharSet = CharSet.Unicode)] - public static extern int ldap_create_sort_control(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_control_freeW", CharSet = CharSet.Unicode)] - public static extern int ldap_control_free(IntPtr control); - - [DllImport("Crypt32.dll", EntryPoint = "CertFreeCRLContext", CharSet = CharSet.Unicode)] - public static extern int CertFreeCRLContext(IntPtr certContext); - - [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result2error", CharSet = CharSet.Unicode)] - public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt); - } -} diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs index 4c4f335a7933f..97c70bf4c081c 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs @@ -2,10 +2,13 @@ // 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.Collections.Generic; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class AsqRequestControlTests { [Fact] @@ -17,13 +20,29 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.1504", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } : new byte[] { 48, 2, 4, 0 }; + + Assert.Equal(expected, control.GetValue()); + } + + public static IEnumerable Ctor_String_Test_data() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + yield return new object[] { null, new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } }; + yield return new object[] { "", new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } }; + yield return new object[] { "A", new byte[] { 48, 132, 0, 0, 0, 3, 4, 1, 65 } }; + } + else + { + yield return new object[] { null, new byte[] { 48, 2, 4, 0 } }; + yield return new object[] { "", new byte[] { 48, 2, 4, 0 } }; + yield return new object[] { "A", new byte[] { 48, 3, 4, 1, 65 } }; + } } [Theory] - [InlineData(null, new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 })] - [InlineData("", new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 })] - [InlineData("A", new byte[] { 48, 132, 0, 0, 0, 3, 4, 1, 65 })] + [MemberData(nameof(Ctor_String_Test_data))] public void Ctor_String(string attributeName, byte[] expectedValue) { var control = new AsqRequestControl(attributeName); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs index 54f85a9e9783a..890ce024efbb6 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs @@ -2,11 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.DotNet.XUnitExtensions; using System.Collections.Generic; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class BerConverterTests { public static IEnumerable Encode_TestData() @@ -15,22 +18,28 @@ public static IEnumerable Encode_TestData() yield return new object[] { "", new object[10], new byte[0] }; yield return new object[] { "b", new object[] { true, false, true, false }, new byte[] { 1, 1, 255 } }; - yield return new object[] { "{", new object[] { "a" }, new byte[] { 48, 0, 0, 0, 0, 0 } }; - yield return new object[] { "{}", new object[] { "a" }, new byte[] { 48, 132, 0, 0, 0, 0 } }; - yield return new object[] { "[", new object[] { "a" }, new byte[] { 49, 0, 0, 0, 0, 0 } }; - yield return new object[] { "[]", new object[] { "a" }, new byte[] { 49, 132, 0, 0, 0, 0 } }; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + yield return new object[] { "{", new object[] { "a" }, new byte[] { 48, 0, 0, 0, 0, 0 } }; // This format is not supported by Linux OpenLDAP + } + yield return new object[] { "{}", new object[] { "a" }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 0 } : new byte[] { 48, 0 } }; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + yield return new object[] { "[", new object[] { "a" }, new byte[] { 49, 0, 0, 0, 0, 0 } }; // This format is not supported by Linux OpenLDAP + } + yield return new object[] { "[]", new object[] { "a" }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 49, 132, 0, 0, 0, 0 } : new byte[] { 49, 0 } }; yield return new object[] { "n", new object[] { "a" }, new byte[] { 5, 0 } }; - yield return new object[] { "tetie", new object[] { -1, 0, 1, 2, 3 }, new byte[] { 255, 1, 0, 1, 1, 2, 10, 1, 3 } }; - yield return new object[] { "{tetie}", new object[] { -1, 0, 1, 2, 3 }, new byte[] { 48, 132, 0, 0, 0, 9, 255, 1, 0, 1, 1, 2, 10, 1, 3 } }; + yield return new object[] { "tetie", new object[] { 128, 0, 133, 2, 3 }, new byte[] { 128, 1, 0, 133, 1, 2, 10, 1, 3 } }; + yield return new object[] { "{tetie}", new object[] { 128, 0, 133, 2, 3 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 128, 1, 0, 133, 1, 2, 10, 1, 3 } : new byte[] { 48, 9, 128, 1, 0, 133, 1, 2, 10, 1, 3 } }; yield return new object[] { "bb", new object[] { true, false }, new byte[] { 1, 1, 255, 1, 1, 0 } }; - yield return new object[] { "{bb}", new object[] { true, false }, new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + yield return new object[] { "{bb}", new object[] { true, false }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } : new byte[] { 48, 6, 1, 1, 255, 1, 1, 0 } }; yield return new object[] { "ssss", new object[] { null, "", "abc", "\0" }, new byte[] { 4, 0, 4, 0, 4, 3, 97, 98, 99, 4, 1, 0 } }; - yield return new object[] { "oXo", new object[] { null, new byte[] { 0, 1, 2, 255 }, new byte[0] }, new byte[] { 4, 0, 3, 4, 0, 1, 2, 255, 4, 0 } }; + yield return new object[] { "oXo", new object[] { null, new byte[] { 0, 1, 2, 255 }, new byte[0] }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 4, 0, 3, 4, 0, 1, 2, 255, 4, 0 } : new byte[] { 4, 0, 3, 2, 4, 0, 4, 0 } }; yield return new object[] { "vv", new object[] { null, new string[] { "abc", "", null } }, new byte[] { 4, 3, 97, 98, 99, 4, 0, 4, 0 } }; - yield return new object[] { "{vv}", new object[] { null, new string[] { "abc", "", null } }, new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 } }; + yield return new object[] { "{vv}", new object[] { null, new string[] { "abc", "", null } }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 } : new byte[] { 48, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 } }; yield return new object[] { "VVVV", new object[] { null, new byte[][] { new byte[] { 0, 1, 2, 3 }, null }, new byte[][] { new byte[0] }, new byte[0][] }, new byte[] { 4, 4, 0, 1, 2, 3, 4, 0, 4, 0 } }; } @@ -112,10 +121,13 @@ public static IEnumerable Decode_TestData() yield return new object[] { "{bb}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { true, false } }; yield return new object[] { "{OO}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[] { 255 }, new byte[] { 0 } } }; yield return new object[] { "{BB}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[] { 255 }, new byte[] { 0 } } }; - yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } }; - yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new string[] { "\x01" }, null } }; - yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } }; - yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[][] { new byte[] { 1 } }, null } }; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // vv and VV formats are not supported yet in Linux + { + yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } }; + yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new string[] { "\x01" }, null } }; + yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } }; + yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[][] { new byte[] { 1 } }, null } }; + } } [Theory] @@ -139,18 +151,29 @@ public void UnknownFormat_ThrowsArgumentException(string format, byte[] values) AssertExtensions.Throws(null, () => BerConverter.Decode(format, values)); } + public static IEnumerable Decode_Invalid_ThrowsBerConversionException_Data() + { + yield return new object[] { "n", null }; + yield return new object[] { "n", new byte[0] }; + yield return new object[] { "{", new byte[] { 1 } }; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + yield return new object[] { "}", new byte[] { 1 } }; // This is considered a valid case in Linux + } + yield return new object[] { "{}{}{}{}{}{}{}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + yield return new object[] { "aaa", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + } + yield return new object[] { "iii", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + yield return new object[] { "eee", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + yield return new object[] { "bbb", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + yield return new object[] { "OOO", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + yield return new object[] { "BBB", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } }; + } + [Theory] - [InlineData("n", null)] - [InlineData("n", new byte[0])] - [InlineData("{", new byte[] { 1 })] - [InlineData("}", new byte[] { 1 })] - [InlineData("{}{}{}{}{}{}{}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] - [InlineData("aaa", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] - [InlineData("iii", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] - [InlineData("eee", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] - [InlineData("bbb", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] - [InlineData("OOO", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] - [InlineData("BBB", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })] + [MemberData(nameof(Decode_Invalid_ThrowsBerConversionException_Data))] public void Decode_Invalid_ThrowsBerConversionException(string format, byte[] values) { Assert.Throws(() => BerConverter.Decode(format, values)); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs index 09f212987f652..8a494282e67f1 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs @@ -2,10 +2,13 @@ // 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.Collections.Generic; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class DirSyncRequestControlTests { [Fact] @@ -20,13 +23,19 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.841", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 }; + Assert.Equal(expected, control.GetValue()); + } + + public static IEnumerable Ctor_Cookie_Data() + { + yield return new object[] { null, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } }; + yield return new object[] { new byte[0], (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } }; + yield return new object[] { new byte[] { 97, 98, 99 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 0, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } : new byte[] { 48, 13, 2, 1, 0, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } }; } [Theory] - [InlineData(null, new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })] - [InlineData(new byte[0], new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })] - [InlineData(new byte[] { 97, 98, 99 }, new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 0, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 })] + [MemberData(nameof(Ctor_Cookie_Data))] public void Ctor_Cookie(byte[] cookie, byte[] expectedValue) { var control = new DirSyncRequestControl(cookie); @@ -41,10 +50,15 @@ public void Ctor_Cookie(byte[] cookie, byte[] expectedValue) Assert.Equal(expectedValue, control.GetValue()); } + public static IEnumerable Ctor_Cookie_Options_Data() + { + yield return new object[] { null, DirectorySynchronizationOptions.None, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } }; + yield return new object[] { new byte[0], DirectorySynchronizationOptions.None - 1, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 13, 2, 4, 255, 255, 255, 255, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 255, 2, 3, 16, 0, 0, 4, 0 } }; + yield return new object[] { new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 1, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } : new byte[] { 48, 13, 2, 1, 1, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } }; + } + [Theory] - [InlineData(null, DirectorySynchronizationOptions.None, new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })] - [InlineData(new byte[0], DirectorySynchronizationOptions.None - 1, new byte[] { 48, 132, 0, 0, 0, 13, 2, 4, 255, 255, 255, 255, 2, 3, 16, 0, 0, 4, 0 })] - [InlineData(new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 1, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 })] + [MemberData(nameof(Ctor_Cookie_Options_Data))] public void Ctor_Cookie_Options(byte[] cookie, DirectorySynchronizationOptions option, byte[] expectedValue) { var control = new DirSyncRequestControl(cookie, option); @@ -59,10 +73,15 @@ public void Ctor_Cookie_Options(byte[] cookie, DirectorySynchronizationOptions o Assert.Equal(expectedValue, control.GetValue()); } + public static IEnumerable Ctor_Cookie_Options_AttributeCount_Data() + { + yield return new object[] { null, DirectorySynchronizationOptions.None, 1048576, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } }; + yield return new object[] { new byte[0], DirectorySynchronizationOptions.None - 1, 0, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 4, 255, 255, 255, 255, 2, 1, 0, 4, 0 } : new byte[] { 48, 8, 2, 1, 255, 2, 1, 0, 4, 0 } }; + yield return new object[] { new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 1, 2, 1, 10, 4, 3, 97, 98, 99 } : new byte[] { 48, 11, 2, 1, 1, 2, 1, 10, 4, 3, 97, 98, 99 } }; + } + [Theory] - [InlineData(null, DirectorySynchronizationOptions.None, 1048576, new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })] - [InlineData(new byte[0], DirectorySynchronizationOptions.None - 1, 0, new byte[] { 48, 132, 0, 0, 0, 11, 2, 4, 255, 255, 255, 255, 2, 1, 0, 4, 0 })] - [InlineData(new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, 10, new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 1, 2, 1, 10, 4, 3, 97, 98, 99 })] + [MemberData(nameof(Ctor_Cookie_Options_AttributeCount_Data))] public void Ctor_Cookie_Options_AttributeCount(byte[] cookie, DirectorySynchronizationOptions option, int attributeCount , byte[] expectedValue) { var control = new DirSyncRequestControl(cookie, option, attributeCount); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs index f520df26b2b4d..af065dfd6a393 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs @@ -2,17 +2,12 @@ // 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.Runtime.InteropServices; -using System.Collections.Generic; -using System.Collections; +using System.DirectoryServices.Tests; using System.Globalization; using System.Net; using Xunit; -using System.Threading; -using System.DirectoryServices.Tests; -using System.DirectoryServices.Protocols; -namespace System.DirectoryServicesProtocols.Tests +namespace System.DirectoryServices.Protocols.Tests { public partial class DirectoryServicesProtocolsTests { diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs new file mode 100644 index 0000000000000..98d45457c7ae7 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs @@ -0,0 +1,46 @@ +// 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.Runtime.InteropServices; +using Xunit; + +[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/35912", TestRuntimes.Mono)] + +namespace System.DirectoryServices.Protocols.Tests +{ + public static class DirectoryServicesTestHelpers + { + public static bool IsWindowsOrLibLdapIsInstalled => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || IsLibLdapInstalled; + + // Cache the check once we have performed it once + private static bool? _isLibLdapInstalled = null; + + /// + /// Returns true if able to PInvoke into Linux or OSX, false otherwise + /// + public static bool IsLibLdapInstalled + { + get + { +#if NETCOREAPP + if (!_isLibLdapInstalled.HasValue) + { + if (PlatformDetection.IsOSX) + { + _isLibLdapInstalled = NativeLibrary.TryLoad("libldap.dylib", out _); + } + else + { + _isLibLdapInstalled = NativeLibrary.TryLoad("libldap-2.4.so.2", out _); + } + } + return _isLibLdapInstalled.Value; +#else + _isLibLdapInstalled = true; // In .NET Framework ldap is always installed. + return _isLibLdapInstalled.Value; +#endif + } + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs index 7a759afeb07ba..ade556afd0d9f 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs @@ -3,10 +3,12 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class ExtendedDNControlTests { [Fact] @@ -18,7 +20,8 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.529", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 } : new byte[] { 48, 3, 2, 1, 0 }; + Assert.Equal(expected, control.GetValue()); } [Fact] @@ -30,7 +33,8 @@ public void Ctor_Flag() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.529", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 } : new byte[] { 48, 3, 2, 1, 1 }; + Assert.Equal(expected, control.GetValue()); } [Theory] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs index ee262ec1a03c1..c8b8fb0a5be95 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs @@ -5,13 +5,12 @@ using System.Collections.Generic; using System.ComponentModel; using System.Net; -using System.Net.Sockets; using System.Threading; -using System.Threading.Tasks; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class LdapConnectionTests { [Theory] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs index f8ea1cceea2e4..30abf231c1942 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs @@ -8,9 +8,11 @@ namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class LdapSessionOptionsTests { [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(ReferralChasingOptions.None)] [InlineData(ReferralChasingOptions.External)] public void ReferralChasing_Set_GetReturnsExpected(ReferralChasingOptions value) @@ -47,6 +49,7 @@ public void ReferralChasing_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] [InlineData(false)] public void SecureSocketLayer_Set_GetReturnsExpected(bool value) @@ -62,6 +65,7 @@ public void SecureSocketLayer_Set_GetReturnsExpected(bool value) } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void SecureSocketLayer_GetSetWhenDisposed_ThrowsObjectDisposedException() { var connection = new LdapConnection("server"); @@ -72,6 +76,7 @@ public void SecureSocketLayer_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void ReferralHopLimit_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -142,6 +147,7 @@ public void ProtocolVersion_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void HostName_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -168,6 +174,7 @@ public void HostName_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void DomainName_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -194,6 +201,7 @@ public void DomainName_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(LocatorFlags.AvoidSelf)] [InlineData(LocatorFlags.None - 1)] public void LocatorFlag_Set_GetReturnsExpected(LocatorFlags value) @@ -219,6 +227,7 @@ public void LocatorFlag_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void HostReachable_Get_ReturnsTrue() { using (var connection = new LdapConnection("server")) @@ -238,6 +247,7 @@ public void HostReachable_GetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void PingKeepAliveTimeout_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -272,6 +282,7 @@ public void PingKeepAliveTimeout_GetSetWhenDisposed_ThrowsObjectDisposedExceptio } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void PingLimit_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -304,6 +315,7 @@ public void PingLimit_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void PingWaitTimeout_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -338,6 +350,7 @@ public void PingWaitTimeout_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] [InlineData(false)] public void AutoReconnect_Set_GetReturnsExpected(bool value) @@ -363,6 +376,7 @@ public void AutoReconnect_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(-1)] [InlineData(10)] public void SspiFlag_Set_GetReturnsExpected(int value) @@ -388,6 +402,7 @@ public void SspiFlag_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void SslInformation_GetNotStarted_ThrowsDirectoryOperationException() { using (var connection = new LdapConnection("server")) @@ -407,6 +422,7 @@ public void SslInformation_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void SecurityContext_GetNotStarted_ThrowsDirectoryOperationException() { using (var connection = new LdapConnection("server")) @@ -426,6 +442,7 @@ public void SecurityContext_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] [InlineData(false)] public void Signing_Set_GetReturnsExpected(bool value) @@ -451,6 +468,7 @@ public void Signing_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] [InlineData(false)] public void Sealing_Set_GetReturnsExpected(bool value) @@ -476,6 +494,7 @@ public void Sealing_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void SaslMethod_Set_ThrowsLdapException() { using (var connection = new LdapConnection("server")) @@ -498,6 +517,7 @@ public void SaslMethod_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] [InlineData(false)] public void RootDseCache_Set_GetReturnsExpected(bool value) @@ -523,6 +543,7 @@ public void RootDseCache_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] [InlineData(false)] public void TcpKeepAlive_Set_GetReturnsExpected(bool value) @@ -548,6 +569,7 @@ public void TcpKeepAlive_GetSetWhenDisposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void SendTimeout_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -595,6 +617,7 @@ public void ReferralCallback_Get_ReturnsException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void ReferralCallback_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -625,6 +648,7 @@ public void ReferralCallback_GetGetSetWhenDisposed_ThrowsObjectDisposedException } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void QueryClientCertificate_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -653,6 +677,7 @@ public void QueryClientCertificate_GetGetSetWhenDisposed_ThrowsObjectDisposedExc } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void VerifyServerCertificate_Set_GetReturnsExpected() { using (var connection = new LdapConnection("server")) @@ -699,6 +724,7 @@ public void StartTransportLayerSecurity_Disposed_ThrowsObjectDisposedException() } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] public void StopTransportLayerSecurity_NotStarted_ThrowsTlsOperationException() { using (var connection = new LdapConnection("server")) diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs index 6ce552719fb78..e629b5327b636 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs @@ -3,12 +3,12 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.ComponentModel; -using System.Security.Principal; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class PageResultRequestControlTests { [Fact] @@ -21,12 +21,18 @@ public void Ctor_Default() Assert.Equal(512, control.PageSize); Assert.Equal("1.2.840.113556.1.4.319", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 } : new byte[] { 48, 6, 2, 2, 2, 0, 4, 0 }; + Assert.Equal(expected, control.GetValue()); + } + + public static IEnumerable Ctor_PageSize_Data() + { + yield return new object[] { 0, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 } : new byte[] { 48, 5, 2, 1, 0, 4, 0 } }; + yield return new object[] { 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 10, 4, 0 } : new byte[] { 48, 5, 2, 1, 10, 4, 0 } }; } [Theory] - [InlineData(0, new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 })] - [InlineData(10, new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 10, 4, 0 })] + [MemberData(nameof(Ctor_PageSize_Data))] public void Ctor_PageSize(int pageSize, byte[] expectedValue) { var control = new PageResultRequestControl(pageSize); @@ -45,10 +51,15 @@ public void Ctor_NegativePageSize_ThrowsArgumentException() AssertExtensions.Throws("value", () => new PageResultRequestControl(-1)); } + public static IEnumerable Ctor_Cookie_Data() + { + yield return new object[] { null, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 } : new byte[] { 48, 6, 2, 2, 2, 0, 4, 0 } }; + yield return new object[] { new byte[0], (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 } : new byte[] { 48, 6, 2, 2, 2, 0, 4, 0 } }; + yield return new object[] { new byte[] { 1, 2, 3, }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 2, 2, 2, 0, 4, 3, 1, 2, 3 } : new byte[] { 48, 9, 2, 2, 2, 0, 4, 3, 1, 2, 3 } }; + } + [Theory] - [InlineData(null, new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 })] - [InlineData(new byte[0], new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 })] - [InlineData(new byte[] { 1, 2, 3, }, new byte[] { 48, 132, 0, 0, 0, 9, 2, 2, 2, 0, 4, 3, 1, 2, 3 })] + [MemberData(nameof(Ctor_Cookie_Data))] public void Ctor_Cookie(byte[] cookie, byte[] expectedValue) { var control = new PageResultRequestControl(cookie); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs index 590da560d8383..300bf8c4874f1 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs @@ -3,12 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.ComponentModel; +using System.Runtime.InteropServices; using System.Security.Principal; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class QuotaControlTests { [Fact] @@ -20,7 +21,8 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.1852", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } : new byte[] { 48, 2, 4, 0 }; + Assert.Equal(expected, control.GetValue()); } public static IEnumerable Ctor_QuerySid_TestData() @@ -30,6 +32,7 @@ public static IEnumerable Ctor_QuerySid_TestData() } [Theory] + [PlatformSpecific(TestPlatforms.Windows)] //Security Identifiers only work on Windows [MemberData(nameof(Ctor_QuerySid_TestData))] public void Ctor_QuerySid_Test(SecurityIdentifier querySid, byte[] expectedValue) { diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs index fbf5fc0dc87dc..7fd2878537bb8 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs @@ -3,10 +3,12 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class SearchOptionsControlTests { [Fact] @@ -18,7 +20,8 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.1340", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 } : new byte[] { 48, 3, 2, 1, 1 }; + Assert.Equal(expected, control.GetValue()); } [Fact] @@ -30,7 +33,8 @@ public void Ctor_Flags() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.1340", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 } : new byte[] { 48, 3, 2, 1, 2 }; + Assert.Equal(expected, control.GetValue()); } [Theory] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs index 3d0fc4e6d5024..8c7fabf0ed8bb 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs @@ -2,11 +2,13 @@ // 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.ComponentModel; +using System.Collections.Generic; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class SecurityDescriptorFlagControlTests { [Fact] @@ -18,12 +20,18 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.801", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 } : new byte[] { 48, 3, 2, 1, 0 }; + Assert.Equal(expected, control.GetValue()); + } + + public static IEnumerable Ctor_Flags_Data() + { + yield return new object[] { SecurityMasks.Group, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 } : new byte[] { 48, 3, 2, 1, 2 } }; + yield return new object[] { SecurityMasks.None - 1, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 4, 255, 255, 255, 255 } : new byte[] { 48, 3, 2, 1, 255 } }; } [Theory] - [InlineData(SecurityMasks.Group, new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 })] - [InlineData(SecurityMasks.None - 1, new byte[] { 48, 132, 0, 0, 0, 6, 2, 4, 255, 255, 255, 255 })] + [MemberData(nameof(Ctor_Flags_Data))] public void Ctor_Flags(SecurityMasks masks, byte[] expectedValue) { var control = new SecurityDescriptorFlagControl(masks); @@ -31,7 +39,6 @@ public void Ctor_Flags(SecurityMasks masks, byte[] expectedValue) Assert.Equal(masks, control.SecurityMasks); Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.801", control.Type); - Assert.Equal(expectedValue, control.GetValue()); } } diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SortRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SortRequestControlTests.cs index 24c57e840cf52..197a8f91c9b9c 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SortRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SortRequestControlTests.cs @@ -3,10 +3,12 @@ // See the LICENSE file in the project root for more information. using System.Reflection; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class SortRequestControlTests { [Theory] @@ -30,13 +32,13 @@ public void Ctor_SortKeys(bool critical) } control.IsCritical = critical; - Assert.Equal(new byte[] - { - 48, 132, 0, 0, 0, 43, 48, 132, 0, 0, 0, 17, 4, 5,110, + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? + new byte[] { 48, 132, 0, 0, 0, 43, 48, 132, 0, 0, 0, 17, 4, 5,110, 97, 109, 101, 49, 128, 5, 114, 117, 108, 101, 49, 129, 1, 255, 48, 132, 0, 0, 0, 14, 4, 5, 110, 97, 109, 101, - 50, 128, 5, 114, 117, 108, 101, 50 - }, control.GetValue()); + 50, 128, 5, 114, 117, 108, 101, 50} : + new byte[] { 48, 19, 48, 9, 4, 1, 110, 128, 1, 114, 129, 1, 255, 48, 6, 4, 1, 110, 128, 1, 114 }; + Assert.Equal(expected, control.GetValue()); } [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/System.DirectoryServices.Protocols.Tests.csproj b/src/libraries/System.DirectoryServices.Protocols/tests/System.DirectoryServices.Protocols.Tests.csproj index 7cf3cdc3988f9..4c621fb35408b 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/System.DirectoryServices.Protocols.Tests.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/tests/System.DirectoryServices.Protocols.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-Windows_NT;$(NetFrameworkCurrent) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) @@ -47,6 +47,7 @@ + diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs index 73db25a571759..93b790224c950 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs @@ -2,10 +2,13 @@ // 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.Collections.Generic; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class VerifyNameControlTests { [Fact] @@ -18,12 +21,18 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("1.2.840.113556.1.4.1338", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 } : new byte[] { 48, 5, 2, 1, 0, 4, 0 }; + Assert.Equal(expected, control.GetValue()); + } + + public static IEnumerable Ctor_ServerName_Data() + { + yield return new object[] { "", (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 } : new byte[] { 48, 5, 2, 1, 0, 4, 0 } }; + yield return new object[] { "S", (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 0, 4, 2, 83, 0 } : new byte[] { 48, 7, 2, 1, 0, 4, 2, 83, 0 } }; } [Theory] - [InlineData("", new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 })] - [InlineData("S", new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 0, 4, 2, 83, 0 })] + [MemberData(nameof(Ctor_ServerName_Data))] public void Ctor_ServerName(string serverName, byte[] expectedValue) { var control = new VerifyNameControl(serverName); @@ -36,9 +45,14 @@ public void Ctor_ServerName(string serverName, byte[] expectedValue) Assert.Equal(expectedValue, control.GetValue()); } + public static IEnumerable Ctor_ServerName_Flag_Data() + { + yield return new object[] { "", -1, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 8, 2, 4, 255, 255, 255, 255, 4, 0 } : new byte[] { 48, 5, 2, 1, 255, 4, 0 } }; + yield return new object[] { "S", 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 10, 4, 2, 83, 0 } : new byte[] { 48, 7, 2, 1, 10, 4, 2, 83, 0 } }; + } + [Theory] - [InlineData("", -1, new byte[] { 48, 132, 0, 0, 0, 8, 2, 4, 255, 255, 255, 255, 4, 0 })] - [InlineData("S", 10, new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 10, 4, 2, 83, 0 })] + [MemberData(nameof(Ctor_ServerName_Flag_Data))] public void Ctor_ServerName_Flag(string serverName, int flag, byte[] expectedValue) { var control = new VerifyNameControl(serverName, flag); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs index d2f42a65fd6ce..7d1844b601e05 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs @@ -2,10 +2,13 @@ // 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.Collections.Generic; +using System.Runtime.InteropServices; using Xunit; namespace System.DirectoryServices.Protocols.Tests { + [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] public class VlvRequestControlTests { [Fact] @@ -22,12 +25,18 @@ public void Ctor_Default() Assert.True(control.ServerSide); Assert.Equal("2.16.840.1.113730.3.4.9", control.Type); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 }; + Assert.Equal(expected, control.GetValue()); + } + + public static IEnumerable Ctor_BeforeCount_AfterCount_Offset_Data() + { + yield return new object[] { 0, 0, 0, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 } }; + yield return new object[] { 10, 10, 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 10, 2, 1, 10, 160, 132, 0, 0, 0, 6, 2, 1, 10, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 10, 2, 1, 10, 160, 6, 2, 1, 10, 2, 1, 0 } }; } [Theory] - [InlineData(0, 0, 0, new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 })] - [InlineData(10, 10, 10, new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 10, 2, 1, 10, 160, 132, 0, 0, 0, 6, 2, 1, 10, 2, 1, 0 })] + [MemberData(nameof(Ctor_BeforeCount_AfterCount_Offset_Data))] public void Ctor_BeforeCount_AfterCount_Offset(int beforeCount, int afterCount, int offset, byte[] expectedValue) { var control = new VlvRequestControl(beforeCount, afterCount, offset); @@ -44,9 +53,14 @@ public void Ctor_BeforeCount_AfterCount_Offset(int beforeCount, int afterCount, Assert.Equal(expectedValue, control.GetValue()); } + public static IEnumerable Ctor_BeforeCount_AfterCount_StringTarget_Data() + { + yield return new object[] { 0, 0, null, new byte[0], (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 } }; + yield return new object[] { 10, 10, "abc", new byte[] { 97, 98, 99 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 97, 98, 99 } : new byte[] { 48, 11, 2, 1, 10, 2, 1, 10, 129, 3, 97, 98, 99 } }; + } + [Theory] - [InlineData(0, 0, null, new byte[0], new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 })] - [InlineData(10, 10, "abc", new byte[] { 97, 98, 99 }, new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 97, 98, 99 })] + [MemberData(nameof(Ctor_BeforeCount_AfterCount_StringTarget_Data))] public void Ctor_BeforeCount_AfterCount_StringTarget(int beforeCount, int afterCount, string target, byte[] expectedTarget, byte[] expectedValue) { var control = new VlvRequestControl(beforeCount, afterCount, target); @@ -64,9 +78,14 @@ public void Ctor_BeforeCount_AfterCount_StringTarget(int beforeCount, int afterC Assert.Equal(expectedValue, control.GetValue()); } + public static IEnumerable Ctor_BeforeCount_AfterCount_ByteArrayTarget_Data() + { + yield return new object[] { 0, 0, null, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 } }; + yield return new object[] { 10, 10, new byte[] { 1, 2, 3 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 1, 2, 3 } : new byte[] { 48, 11, 2, 1, 10, 2, 1, 10, 129, 3, 1, 2, 3 } }; + } + [Theory] - [InlineData(0, 0, null, new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 })] - [InlineData(10, 10, new byte[] { 1, 2, 3 }, new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 1, 2, 3 })] + [MemberData(nameof(Ctor_BeforeCount_AfterCount_ByteArrayTarget_Data))] public void Ctor_BeforeCount_AfterCount_ByteArrayTarget(int beforeCount, int afterCount, byte[] target, byte[] expectedValue) { var control = new VlvRequestControl(beforeCount, afterCount, target); @@ -128,7 +147,8 @@ public void ContextId_Set_GetReturnsExpected() Assert.NotSame(contextId, control.ContextId); Assert.Equal(contextId, control.ContextId); - Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 23, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0, 4, 3, 1, 2, 3 }, control.GetValue()); + var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 23, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0, 4, 3, 1, 2, 3 } : new byte[] { 48, 19, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0, 4, 3, 1, 2, 3 }; + Assert.Equal(expected, control.GetValue()); } } } diff --git a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj index 940e568b35d08..e8ca838dc2aff 100644 --- a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj +++ b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj @@ -1,6 +1,5 @@ - System.DirectoryServices true $(NoWarn);0649 $(NetCoreAppCurrent)-Windows_NT;netstandard2.0;netcoreapp2.0-Windows_NT;_$(NetFrameworkCurrent) @@ -8,9 +7,9 @@ - SR.DirectoryServices_PlatformNotSupported + SR.DirectoryServices_PlatformNotSupported - + @@ -150,7 +149,7 @@ - + diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs index e4eee6a47e26d..2ae4757c6f3b9 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs @@ -59,7 +59,7 @@ public ActiveDirectorySchedule() public ActiveDirectorySchedule(ActiveDirectorySchedule schedule) : this() { if (schedule == null) - throw new ArgumentNullException(); + throw new ArgumentNullException(nameof(schedule)); bool[] tmpSchedule = schedule._scheduleArray; for (int i = 0; i < 672; i++) diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs index ae07de8d521e5..c506669acc835 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs @@ -111,7 +111,7 @@ public void AddRange(ActiveDirectorySchemaClass[] schemaClasses) { if (schemaClass == null) { - throw new ArgumentException(nameof(schemaClasses)); + throw new ArgumentException(null, nameof(schemaClasses)); } } @@ -132,7 +132,7 @@ public void AddRange(ActiveDirectorySchemaClassCollection schemaClasses) { if (schemaClass == null) { - throw new ArgumentException(nameof(schemaClasses)); + throw new ArgumentException(null, nameof(schemaClasses)); } } @@ -154,7 +154,7 @@ public void AddRange(ReadOnlyActiveDirectorySchemaClassCollection schemaClasses) { if (schemaClass == null) { - throw new ArgumentException(nameof(schemaClasses)); + throw new ArgumentException(null, nameof(schemaClasses)); } } @@ -360,7 +360,7 @@ protected override void OnValidate(object value) if (!(value is ActiveDirectorySchemaClass)) { - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); } if (!((ActiveDirectorySchemaClass)value).isBound) diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs index 0e312f9b392cb..5bea1fa12e76e 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs @@ -109,7 +109,7 @@ public void AddRange(ActiveDirectorySchemaProperty[] properties) { if (property == null) { - throw new ArgumentException(nameof(properties)); + throw new ArgumentException(null, nameof(properties)); } } @@ -130,7 +130,7 @@ public void AddRange(ActiveDirectorySchemaPropertyCollection properties) { if (property == null) { - throw new ArgumentException(nameof(properties)); + throw new ArgumentException(null, nameof(properties)); } } @@ -153,7 +153,7 @@ public void AddRange(ReadOnlyActiveDirectorySchemaPropertyCollection properties) { if (property == null) { - throw new ArgumentException(nameof(properties)); + throw new ArgumentException(null, nameof(properties)); } } @@ -369,7 +369,7 @@ protected override void OnValidate(object value) if (value == null) throw new ArgumentNullException(nameof(value)); if (!(value is ActiveDirectorySchemaProperty)) - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); if (!((ActiveDirectorySchemaProperty)value).isBound) throw new InvalidOperationException(SR.Format(SR.SchemaObjectNotCommitted, ((ActiveDirectorySchemaProperty)value).Name)); diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs index 88beabbb7b375..5e85364b26da9 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs @@ -232,7 +232,7 @@ protected override void OnValidate(object value) if (value == null) throw new ArgumentNullException(nameof(value)); if (!(value is ActiveDirectorySite)) - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); if (!((ActiveDirectorySite)value).existing) throw new InvalidOperationException(SR.Format(SR.SiteNotCommitted, ((ActiveDirectorySite)value).Name)); diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs index e35ece7285cfe..244b020f7b3f3 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs @@ -268,7 +268,7 @@ public int Cost throw new ObjectDisposedException(GetType().Name); if (value < 0) - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); try { diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs index 24d230c920a80..3f6afc747b36a 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs @@ -226,7 +226,7 @@ protected override void OnValidate(object value) if (value == null) throw new ArgumentNullException(nameof(value)); if (!(value is ActiveDirectorySiteLink)) - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); if (!((ActiveDirectorySiteLink)value).existing) throw new InvalidOperationException(SR.Format(SR.SiteLinkNotCommitted, ((ActiveDirectorySiteLink)value).Name)); diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs index b270eab2247fb..540be8cbfc5c0 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs @@ -68,7 +68,7 @@ public void AddRange(ActiveDirectorySubnet[] subnets) { if (s == null) { - throw new ArgumentException(nameof(subnets)); + throw new ArgumentException(null, nameof(subnets)); } } @@ -263,7 +263,7 @@ protected override void OnValidate(object value) if (value == null) throw new ArgumentNullException(nameof(value)); if (!(value is ActiveDirectorySubnet)) - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); if (!((ActiveDirectorySubnet)value).existing) throw new InvalidOperationException(SR.Format(SR.SubnetNotCommitted, ((ActiveDirectorySubnet)value).Name)); diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs index 20ee51fd55c60..64de6d61b67e8 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs @@ -115,7 +115,7 @@ public void AddRange(DirectoryServer[] servers) { if (s == null) { - throw new ArgumentException(nameof(servers)); + throw new ArgumentException(null, nameof(servers)); } } @@ -386,7 +386,7 @@ protected override void OnValidate(object value) else { if (!(value is DirectoryServer)) - throw new ArgumentException(nameof(value)); + throw new ArgumentException(null, nameof(value)); } } diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.csproj b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.csproj index 46ac878a5842e..34d6599a3369a 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.csproj +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.csproj @@ -1,6 +1,6 @@ - netcoreapp3.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netcoreapp3.0 true enable diff --git a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj index b165ae7c6e4de..0291615e11c0b 100644 --- a/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj +++ b/src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj @@ -5,7 +5,7 @@ CS0618 $(DefineConstants);FEATURE_WINDOWS_SYSTEM_COLORS;FEATURE_SYSTEM_EVENTS true - netcoreapp3.0-Windows_NT;netcoreapp3.0-Unix;$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix + $(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix;netcoreapp3.0-Windows_NT;netcoreapp3.0-Unix true enable diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/BitmapSelector.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/BitmapSelector.cs index 06ccdf8e3c9c5..ae11c6e29d640 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/BitmapSelector.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/BitmapSelector.cs @@ -64,7 +64,7 @@ internal static string AppendSuffix(string filePath) /// public static string GetFileName(string originalPath) { - if (Suffix == string.Empty) + if (string.IsNullOrEmpty(Suffix)) return originalPath; string newPath = AppendSuffix(originalPath); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/LinearGradientBrush.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/LinearGradientBrush.cs index 19228b5266f03..666eb631d7b37 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/LinearGradientBrush.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/LinearGradientBrush.cs @@ -232,14 +232,14 @@ public bool GammaCorrection throw new NullReferenceException(); if (value.Positions == null) - throw new ArgumentNullException("source"); + throw new ArgumentException(SR.Format(SR.InvalidArgumentValue, "value.Positions", value.Positions), nameof(value)); int count = value.Factors.Length; if (count == 0 || value.Positions.Length == 0) throw new ArgumentException(SR.BlendObjectMustHaveTwoElements); if (count >= 2 && count != value.Positions.Length) - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(value)); if (count >= 2 && value.Positions[0] != 0.0F) throw new ArgumentException(SR.BlendObjectFirstElementInvalid); if (count >= 2 && value.Positions[count - 1] != 1.0F) diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/PathGradientBrush.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/PathGradientBrush.cs index bae8b7a6121d2..f416ff221aa69 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/PathGradientBrush.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Drawing2D/PathGradientBrush.cs @@ -185,10 +185,8 @@ public Blend Blend if (value == null || value.Factors == null) throw new NullReferenceException(); - // The Desktop implementation throws ArgumentNullException("source") because it never validates the value of value.Positions, and then passes it - // on to Marshal.Copy(value.Positions, 0, positions, count);. The first argument of Marshal.Copy is source, hence this exception. if (value.Positions == null) - throw new ArgumentNullException("source"); + throw new ArgumentException(SR.Format(SR.InvalidArgumentValue, "value.Positions", value.Positions), nameof(value)); int count = value.Factors.Length; @@ -196,7 +194,7 @@ public Blend Blend if (count == 0 || value.Positions.Length == 0) throw new ArgumentException(SR.BlendObjectMustHaveTwoElements); if (count >= 2 && count != value.Positions.Length) - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(value)); if (count >= 2 && value.Positions[0] != 0.0F) throw new ArgumentException(SR.BlendObjectFirstElementInvalid); if (count >= 2 && value.Positions[count - 1] != 1.0F) @@ -298,16 +296,12 @@ public ColorBlend InterpolationColors } set { - // The Desktop implementation will throw various exceptions - ranging from NullReferenceExceptions to Argument(OutOfRange)Exceptions - // depending on how sane the input is. These checks exist to replicate the exact Desktop behavior. int count = value.Colors.Length; if (value.Positions == null) - throw new ArgumentNullException("source"); - if (value.Colors.Length > value.Positions.Length) - throw new ArgumentOutOfRangeException(); - if (value.Colors.Length < value.Positions.Length) - throw new ArgumentException(); + throw new ArgumentException(SR.Format(SR.InvalidArgumentValue, "value.Positions", value.Positions), nameof(value)); + if (value.Colors.Length != value.Positions.Length) + throw new ArgumentOutOfRangeException(nameof(value)); float[] positions = value.Positions; int[] argbs = new int[count]; diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Font.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Font.Windows.cs index bfa06594420bc..41ed7b89b7b40 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Font.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Font.Windows.cs @@ -306,7 +306,7 @@ public static unsafe Font FromLogFont(object lf, IntPtr hdc) { // If we don't actually have an object that is LOGFONT in size, trying to pass // it to GDI+ is likely to cause an AV. - throw new ArgumentException(); + throw new ArgumentException(null, nameof(lf)); } // Now that we know the marshalled size is the same as LOGFONT, copy in the data diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs index b030638dda613..bbabbf88ed0b8 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs @@ -285,7 +285,7 @@ public unsafe void ToLogFont(object logFont, Graphics graphics) { // If we don't actually have an object that is LOGFONT in size, trying to pass // it to GDI+ is likely to cause an AV. - throw new ArgumentException(); + throw new ArgumentException(null, nameof(logFont)); } Interop.User32.LOGFONT nativeLogFont = ToLogFontInternal(graphics); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiPlusStreamHelper.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiPlusStreamHelper.Unix.cs index 23494a11bef72..abe50711c9fd6 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiPlusStreamHelper.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiPlusStreamHelper.Unix.cs @@ -43,10 +43,10 @@ internal sealed partial class GdiPlusStreamHelper { private Stream _stream; - public unsafe GdiPlusStreamHelper(Stream stream, bool seekToOrigin) + public unsafe GdiPlusStreamHelper(Stream stream, bool seekToOrigin, bool makeSeekable = true) { // Seeking required - if (!stream.CanSeek) + if (makeSeekable && !stream.CanSeek) { var memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs index 02021231f9f29..a71a09d6e793e 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs @@ -639,9 +639,8 @@ public void Save(Stream outputStream) { try { - // We threw this way on NetFX if (outputStream == null) - throw new ArgumentNullException("dataStream"); + throw new ArgumentNullException(nameof(outputStream)); picture.SaveAsFile(new GPStream(outputStream, makeSeekable: false), -1, out int temp); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs index ab88eaf44305f..7398b5e2c98bb 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs @@ -74,7 +74,7 @@ private protected static IntPtr InitializeFromStream(Stream stream) // We use a custom API for this, because there's no easy way // to get the Stream down to libgdiplus. So, we wrap the stream // with a set of delegates. - GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, true); + GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, seekToOrigin: true); int st = Gdip.GdipLoadImageFromDelegate_linux(sh.GetHeaderDelegate, sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, out IntPtr imagePtr); @@ -247,7 +247,7 @@ public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters? encod try { - GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, false); + GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, seekToOrigin: false, makeSeekable: false); st = Gdip.GdipSaveImageToDelegate_linux(nativeImage, sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, ref guid, nativeEncoderParams); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs index 4747b9c9ca436..da4dd3eac2fc6 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs @@ -243,7 +243,7 @@ public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters? encod { Gdip.CheckStatus(Gdip.GdipSaveImageToStream( new HandleRef(this, nativeImage), - new GPStream(stream), + new GPStream(stream, makeSeekable: false), ref g, new HandleRef(encoderParams, encoderParamsMemory))); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs index d101b970b63f8..596a2e097fbf9 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs @@ -54,7 +54,7 @@ public Metafile(Stream stream) // With libgdiplus we use a custom API for this, because there's no easy way // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates. - GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, false); + GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, seekToOrigin: false); int status = Gdip.GdipCreateMetafileFromDelegate_linux(sh.GetHeaderDelegate, sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, out nativeImage); @@ -101,7 +101,7 @@ public Metafile(IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader) // With libgdiplus we use a custom API for this, because there's no easy way // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates. - GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, false); + GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, seekToOrigin: false); int status = Gdip.GdipRecordMetafileFromDelegateI_linux(sh.GetHeaderDelegate, sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, referenceHdc, type, ref frameRect, frameUnit, description, out nativeImage); @@ -120,7 +120,7 @@ public Metafile(IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader) // With libgdiplus we use a custom API for this, because there's no easy way // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates. - GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, false); + GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, seekToOrigin: false); int status = Gdip.GdipRecordMetafileFromDelegate_linux(sh.GetHeaderDelegate, sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, referenceHdc, type, ref frameRect, frameUnit, description, out nativeImage); @@ -189,7 +189,7 @@ public static MetafileHeader GetMetafileHeader(Stream stream) { // With libgdiplus we use a custom API for this, because there's no easy way // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates. - GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, false); + GdiPlusStreamHelper sh = new GdiPlusStreamHelper(stream, seekToOrigin: false); int status = Gdip.GdipGetMetafileHeaderFromDelegate_linux(sh.GetHeaderDelegate, sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, header); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/PrintingServices.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/PrintingServices.Unix.cs index c9da109eb951d..baf19efb84f6c 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/PrintingServices.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/PrintingServices.Unix.cs @@ -422,9 +422,9 @@ internal static void LoadPrinterResolutions(string printer, PrinterSettings sett int x_resolution, y_resolution; try { - if (resolution.Contains("x")) // string.Contains(char) is .NetCore2.1+ specific + if (resolution.Contains('x')) { - string[] resolutions = resolution.Split(new[] { 'x' }); + string[] resolutions = resolution.Split('x'); x_resolution = Convert.ToInt32(resolutions[0]); y_resolution = Convert.ToInt32(resolutions[1]); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Text/PrivateFontCollection.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Text/PrivateFontCollection.cs index 3b150283b5dd6..60c016124d99e 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Text/PrivateFontCollection.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Text/PrivateFontCollection.cs @@ -60,16 +60,16 @@ public void AddFontFile(string filename) { if (_nativeFontCollection == IntPtr.Zero) { +#pragma warning disable CA2208 // Instantiate argument exceptions correctly // This is the default behavior on Desktop. The ArgumentException originates from GdipPrivateAddFontFile which would // refuse the null pointer. throw new ArgumentException(); +#pragma warning restore CA2208 } if (filename == null) { - // This is the default behavior on Desktop. The name "path" originates from Path.GetFullPath or similar which would refuse - // a null value. - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(filename)); } // this ensure the filename is valid (or throw the correct exception) diff --git a/src/libraries/System.Drawing.Common/tests/BitmapTests.cs b/src/libraries/System.Drawing.Common/tests/BitmapTests.cs index 997b2069ad995..9c5ca385b9f99 100644 --- a/src/libraries/System.Drawing.Common/tests/BitmapTests.cs +++ b/src/libraries/System.Drawing.Common/tests/BitmapTests.cs @@ -1741,7 +1741,7 @@ public void FromNonSeekableStream() using (FileStream stream = new FileStream(path, FileMode.Open)) { - using (Bitmap bitmap = new Bitmap(new NonSeekableStream(stream))) + using (Bitmap bitmap = new Bitmap(new TestStream(stream, canSeek: false))) { Assert.Equal(100, bitmap.Height); Assert.Equal(100, bitmap.Width); @@ -1750,22 +1750,55 @@ public void FromNonSeekableStream() } } - private class NonSeekableStream : Stream + [ConditionalTheory(Helpers.IsDrawingSupported)] + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(false, true)] + public void SaveToRestrictiveStream(bool canRead, bool canSeek) + { + using (Stream backingStream = new MemoryStream()) + using (Stream restrictiveStream = new TestStream(backingStream, canRead, canSeek)) + { + using (Bitmap bitmap = new Bitmap(100, 100)) + { + bitmap.Save(restrictiveStream, ImageFormat.Png); + } + + backingStream.Position = 0; + + using (Bitmap bitmap = new Bitmap(backingStream)) + { + Assert.Equal(100, bitmap.Height); + Assert.Equal(100, bitmap.Width); + Assert.Equal(ImageFormat.Png, bitmap.RawFormat); + } + } + } + + private class TestStream : Stream { private Stream _stream; + private bool _canRead; + private bool _canSeek; - public NonSeekableStream(Stream stream) + public TestStream(Stream stream, bool canRead = true, bool canSeek = true) { _stream = stream; + _canRead = canRead; + _canSeek = canSeek; } - public override bool CanRead => _stream.CanRead; - public override bool CanSeek => false; + public override bool CanRead => _canRead && _stream.CanRead; + public override bool CanSeek => _canSeek && _stream.CanSeek; public override bool CanWrite => _stream.CanWrite; public override long Length => _stream.Length; - public override long Position { get => _stream.Position; set => throw new InvalidOperationException(); } + public override long Position + { + get => _stream.Position; + set => _stream.Position = _canSeek ? value : throw new NotSupportedException(); + } public override void Flush() => _stream.Flush(); - public override int Read(byte[] buffer, int offset, int count) => _stream.Read(buffer, offset, count); + public override int Read(byte[] buffer, int offset, int count) => _canRead ? _stream.Read(buffer, offset, count) : throw new NotSupportedException(); public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin); public override void SetLength(long value) => _stream.SetLength(value); public override void Write(byte[] buffer, int offset, int count) => _stream.Write(buffer, offset, count); diff --git a/src/libraries/System.Drawing.Common/tests/Drawing2D/LinearGradientBrushTests.cs b/src/libraries/System.Drawing.Common/tests/Drawing2D/LinearGradientBrushTests.cs index bcc33b61b72d5..2140688e8e8ba 100644 --- a/src/libraries/System.Drawing.Common/tests/Drawing2D/LinearGradientBrushTests.cs +++ b/src/libraries/System.Drawing.Common/tests/Drawing2D/LinearGradientBrushTests.cs @@ -358,11 +358,11 @@ public void Blend_SetNullBlendFactors_ThrowsNullReferenceException() } [ConditionalFact(Helpers.IsDrawingSupported)] - public void Blend_SetNullBlendPositions_ThrowsArgumentNullException() + public void Blend_SetNullBlendPositions_ThrowsArgumentException() { using (var brush = new LinearGradientBrush(new Rectangle(1, 2, 3, 4), Color.Plum, Color.Red, 45, true)) { - AssertExtensions.Throws("source", () => brush.Blend = new Blend { Factors = new float[2], Positions = null }); + AssertExtensions.Throws("value", "source", () => brush.Blend = new Blend { Factors = new float[2], Positions = null }); } } @@ -371,7 +371,7 @@ public void Blend_SetFactorsLengthGreaterThanPositionsLength_ThrowsArgumentOutOf { using (var brush = new LinearGradientBrush(new Rectangle(1, 2, 3, 4), Color.Plum, Color.Red, 45, true)) { - AssertExtensions.Throws(null, () => brush.Blend = new Blend { Factors = new float[2], Positions = new float[1] }); + AssertExtensions.Throws("value", null, () => brush.Blend = new Blend { Factors = new float[2], Positions = new float[1] }); } } diff --git a/src/libraries/System.Drawing.Common/tests/Drawing2D/PathGradientBrushTests.cs b/src/libraries/System.Drawing.Common/tests/Drawing2D/PathGradientBrushTests.cs index 3046c01641846..3019394844d4d 100644 --- a/src/libraries/System.Drawing.Common/tests/Drawing2D/PathGradientBrushTests.cs +++ b/src/libraries/System.Drawing.Common/tests/Drawing2D/PathGradientBrushTests.cs @@ -350,7 +350,7 @@ public void Blend_InvalidFactorPositionsLengthMismatch_ThrowsArgumentOutOfRangeE using (PathGradientBrush brush = new PathGradientBrush(_defaultFloatPoints)) { - AssertExtensions.Throws(null, () => brush.Blend = invalidBlend); + AssertExtensions.Throws("value", null, () => brush.Blend = invalidBlend); } } @@ -366,11 +366,11 @@ public void Blend_Null_ThrowsNullReferenceException() } [ConditionalFact(Helpers.IsDrawingSupported)] - public void Blend_NullBlendProperites_ThrowsArgumentNullException() + public void Blend_NullBlendProperites_ThrowsArgumentException() { using (PathGradientBrush brush = new PathGradientBrush(_defaultFloatPoints)) { - AssertExtensions.Throws("source", () => + AssertExtensions.Throws("value", "source", () => brush.Blend = new Blend() { Factors = new float[0], Positions = null }); } } @@ -651,11 +651,11 @@ public void InterpolationColors_NullColors_ThrowsNullReferenceException() } [ConditionalFact(Helpers.IsDrawingSupported)] - public void InterpolationColors_NullPoints_ArgumentNullException() + public void InterpolationColors_NullPoints_ArgumentException() { using (PathGradientBrush brush = new PathGradientBrush(_defaultFloatPoints)) { - AssertExtensions.Throws("source", () => + AssertExtensions.Throws("value", "source", () => brush.InterpolationColors = new ColorBlend() { Colors = new Color[1], Positions = null }); } } @@ -680,11 +680,11 @@ public void InterpolationColors_EmptyColors_ArgumentException() } [ConditionalFact(Helpers.IsDrawingSupported)] - public void InterpolationColors_PointsLengthGreaterThenColorsLength_ArgumentException() + public void InterpolationColors_PointsLengthGreaterThenColorsLength_ArgumentOutOfRangeException() { using (PathGradientBrush brush = new PathGradientBrush(_defaultFloatPoints)) { - AssertExtensions.Throws(null, () => + AssertExtensions.Throws("value", null, () => brush.InterpolationColors = new ColorBlend() { Colors = new Color[1], Positions = new float[2] }); } } diff --git a/src/libraries/System.Drawing.Common/tests/IconTests.cs b/src/libraries/System.Drawing.Common/tests/IconTests.cs index a201c9bce16e3..25b8c5b9631e6 100644 --- a/src/libraries/System.Drawing.Common/tests/IconTests.cs +++ b/src/libraries/System.Drawing.Common/tests/IconTests.cs @@ -266,28 +266,6 @@ public void Ctor_NullIcon_ThrowsArgumentNullException() AssertExtensions.Throws("original", null, () => new Icon((Icon)null, new Size(32, 32))); } - // libgdiplus causes a segfault when given an invalid Icon handle. - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalFact(Helpers.IsDrawingSupported)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34591", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - public void Ctor_InvalidHandle_Success() - { - using (Icon icon = Icon.FromHandle((IntPtr)1)) - using (var stream = new MemoryStream()) - { - Exception ex = Assert.ThrowsAny(() => icon.Save(stream)); - Assert.True(ex is COMException || ex is ObjectDisposedException || ex is FileNotFoundException, $"{ex.GetType().ToString()} was thrown."); - - AssertExtensions.Throws(null, () => icon.ToBitmap()); - Assert.Equal(Size.Empty, icon.Size); - - using (var newIcon = new Icon(icon, 10, 10)) - { - Assert.Throws(() => newIcon.Handle); - } - } - } - [ConditionalFact(Helpers.IsDrawingSupported)] public void Ctor_Type_Resource() { @@ -525,7 +503,7 @@ public void Save_NullOutputStreamNoIconData_ThrowsArgumentNullException() var icon = Icon.FromHandle(source.Handle); icon.Dispose(); - AssertExtensions.Throws("dataStream", () => icon.Save(null)); + AssertExtensions.Throws("outputStream", "dataStream", () => icon.Save(null)); } } diff --git a/src/libraries/System.Drawing.Common/tests/Text/PrivateFontCollectionTests.cs b/src/libraries/System.Drawing.Common/tests/Text/PrivateFontCollectionTests.cs index af934a15f458a..364ba09bdb9dd 100644 --- a/src/libraries/System.Drawing.Common/tests/Text/PrivateFontCollectionTests.cs +++ b/src/libraries/System.Drawing.Common/tests/Text/PrivateFontCollectionTests.cs @@ -107,7 +107,7 @@ public void AddFontFile_NullFileName_ThrowsArgumentNullException() { using (var fontCollection = new PrivateFontCollection()) { - AssertExtensions.Throws("path", () => fontCollection.AddFontFile(null)); + AssertExtensions.Throws("filename", "path", () => fontCollection.AddFontFile(null)); } } diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoData.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoData.cs index ed232bbf21593..3d370acb84319 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoData.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoData.cs @@ -29,7 +29,7 @@ public static string JaJPAbbreviatedEraName() public static string[] FrFRDayNames() { - if (PlatformDetection.IsOSX && PlatformDetection.OSXVersion < new Version(10, 12)) + if (PlatformDetection.IsOSX && Environment.OSVersion.Version < new Version(10, 12)) { return new string[] { "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" }; } @@ -38,7 +38,7 @@ public static string[] FrFRDayNames() public static string[] FrFRAbbreviatedDayNames() { - if (PlatformDetection.IsOSX && PlatformDetection.OSXVersion < new Version(10, 12)) + if (PlatformDetection.IsOSX && Environment.OSVersion.Version < new Version(10, 12)) { return new string[] { "Dim.", "Lun.", "Mar.", "Mer.", "Jeu.", "Ven.", "Sam." }; } diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs index 5899092a5cf4f..e15b89b064ac1 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs @@ -36,6 +36,17 @@ public void LongDatePattern_Set_GetReturnsExpected(string value) Assert.Equal(value, format.LongDatePattern); } + [Fact] + public void LongDatePattern_Set_InvalidatesDerivedPattern() + { + const string Pattern = "#$"; + var format = new DateTimeFormatInfo(); + var d = DateTimeOffset.Now; + d.ToString("F", format); // FullDateTimePattern + format.LongDatePattern = Pattern; + Assert.Contains(Pattern, d.ToString("F", format)); + } + [Fact] public void LongDatePattern_SetNullValue_ThrowsArgumentNullException() { diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs index 8e783154aa9ef..5367dc0f1e3b6 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs @@ -35,6 +35,21 @@ public void LongTimePattern_Set_GetReturnsExpected(string value) Assert.Equal(value, format.LongTimePattern); } + [Fact] + public void LongTimePattern_Set_InvalidatesDerivedPatterns() + { + const string Pattern = "#$"; + var format = new DateTimeFormatInfo(); + var d = DateTimeOffset.Now; + d.ToString("F", format); // FullDateTimePattern + d.ToString("G", format); // GeneralLongTimePattern + d.ToString(format); // DateTimeOffsetPattern + format.LongTimePattern = Pattern; + Assert.Contains(Pattern, d.ToString("F", format)); + Assert.Contains(Pattern, d.ToString("G", format)); + Assert.Contains(Pattern, d.ToString(format)); + } + [Fact] public void LongTimePattern_SetNullValue_ThrowsArgumentNullException() { diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs index 4e67e1dcc7b08..b0dcb3705f26c 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs @@ -33,6 +33,21 @@ public void ShortDatePattern_Set_GetReturnsExpected(string value) Assert.Equal(value, format.ShortDatePattern); } + [Fact] + public void ShortDatePattern_Set_InvalidatesDerivedPatterns() + { + const string Pattern = "#$"; + var format = new DateTimeFormatInfo(); + var d = DateTimeOffset.Now; + d.ToString("G", format); // GeneralLongTimePattern + d.ToString("g", format); // GeneralShortTimePattern + d.ToString(format); // DateTimeOffsetPattern + format.ShortDatePattern = Pattern; + Assert.Contains(Pattern, d.ToString("G", format)); + Assert.Contains(Pattern, d.ToString("g", format)); + Assert.Contains(Pattern, d.ToString(format)); + } + [Fact] public void ShortDatePattern_SetNullValue_ThrowsArgumentNullException() { diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs index bcea88b745296..8c87f92ae81fa 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs @@ -33,6 +33,17 @@ public void ShortTimePattern_Set_GetReturnsExpected(string value) Assert.Equal(value, format.ShortTimePattern); } + [Fact] + public void ShortTimePattern_Set_InvalidatesDerivedPattern() + { + const string Pattern = "#$"; + var format = new DateTimeFormatInfo(); + var d = DateTimeOffset.Now; + d.ToString("g", format); // GeneralShortTimePattern + format.ShortTimePattern = Pattern; + Assert.Contains(Pattern, d.ToString("g", format)); + } + [Fact] public void ShortTimePattern_SetNull_ThrowsArgumentNullException() { diff --git a/src/libraries/System.Globalization/tests/IcuTests.cs b/src/libraries/System.Globalization/tests/IcuTests.cs index 8e862c910195f..80533da8fb7d1 100644 --- a/src/libraries/System.Globalization/tests/IcuTests.cs +++ b/src/libraries/System.Globalization/tests/IcuTests.cs @@ -11,8 +11,7 @@ namespace System.Globalization.Tests public class IcuTests { private static bool IsIcuCompatiblePlatform => PlatformDetection.IsNotWindows || - (!PlatformDetection.IsMonoRuntime && - PlatformDetection.IsWindows10Version1903OrGreater); + PlatformDetection.IsWindows10Version1903OrGreater; [ConditionalFact(nameof(IsIcuCompatiblePlatform))] public static void IcuShouldBeUsedByDefault() diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj b/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj index 323535b72d781..ac6c8e8a6690c 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj +++ b/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj @@ -1,7 +1,5 @@ - true - SR.PlatformNotSupported_AccessControl $(NetCoreAppCurrent)-Windows_NT;netstandard2.0;netstandard2.0-Windows_NT;net461-Windows_NT;$(NetFrameworkCurrent)-Windows_NT true true @@ -10,6 +8,8 @@ true + true + SR.PlatformNotSupported_AccessControl diff --git a/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj b/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj index 50792a3e761b6..abc8eb70f910d 100644 --- a/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj +++ b/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj @@ -1,7 +1,5 @@ - System.IO.FileSystem.DriveInfo - System.IO.FileSystem.DriveInfo true $(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix enable diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj index 300a25ad55691..5872cdfcf1703 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj @@ -66,6 +66,8 @@ Link="Common\Interop\Linux\Interop.inotify.cs" /> + diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs index def4ae5681fe6..5b04282c713d6 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs @@ -680,11 +680,11 @@ private void ProcessEvents() // that's actually what's needed (otherwise it'd be fine to block indefinitely waiting // for the next event to arrive). const int MillisecondsTimeout = 2; - Interop.Sys.PollEvents events; - Interop.Sys.Poll(_inotifyHandle, Interop.Sys.PollEvents.POLLIN, MillisecondsTimeout, out events); + Interop.PollEvents events; + Interop.Sys.Poll(_inotifyHandle, Interop.PollEvents.POLLIN, MillisecondsTimeout, out events); // If we error or don't have any signaled handles, send the deleted event - if (events == Interop.Sys.PollEvents.POLLNONE) + if (events == Interop.PollEvents.POLLNONE) { // There isn't any more data in the queue so this is a deleted event watcher.NotifyFileSystemEventArgs(WatcherChangeTypes.Deleted, expandedName); diff --git a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs index d7d09f9bf3ff6..1d13427bb6659 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs +++ b/src/libraries/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/IsolatedStorageFile.cs @@ -262,7 +262,7 @@ public DateTimeOffset GetCreationTime(string path) if (path == null) throw new ArgumentNullException(nameof(path)); - if (path == string.Empty) + if (path.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); } @@ -284,7 +284,7 @@ public DateTimeOffset GetLastAccessTime(string path) if (path == null) throw new ArgumentNullException(nameof(path)); - if (path == string.Empty) + if (path.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); } @@ -306,7 +306,7 @@ public DateTimeOffset GetLastWriteTime(string path) if (path == null) throw new ArgumentNullException(nameof(path)); - if (path == string.Empty) + if (path.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); } @@ -331,12 +331,12 @@ public void CopyFile(string sourceFileName, string destinationFileName) if (destinationFileName == null) throw new ArgumentNullException(nameof(destinationFileName)); - if (sourceFileName == string.Empty) + if (sourceFileName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(sourceFileName)); } - if (destinationFileName == string.Empty) + if (destinationFileName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(destinationFileName)); } @@ -352,12 +352,12 @@ public void CopyFile(string sourceFileName, string destinationFileName, bool ove if (destinationFileName == null) throw new ArgumentNullException(nameof(destinationFileName)); - if (sourceFileName == string.Empty) + if (sourceFileName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(sourceFileName)); } - if (destinationFileName == string.Empty) + if (destinationFileName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(destinationFileName)); } @@ -393,12 +393,12 @@ public void MoveFile(string sourceFileName, string destinationFileName) if (destinationFileName == null) throw new ArgumentNullException(nameof(destinationFileName)); - if (sourceFileName == string.Empty) + if (sourceFileName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(sourceFileName)); } - if (destinationFileName == string.Empty) + if (destinationFileName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(destinationFileName)); } @@ -434,12 +434,12 @@ public void MoveDirectory(string sourceDirectoryName, string destinationDirector if (destinationDirectoryName == null) throw new ArgumentNullException(nameof(destinationDirectoryName)); - if (sourceDirectoryName == string.Empty) + if (sourceDirectoryName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(sourceDirectoryName)); } - if (destinationDirectoryName == string.Empty) + if (destinationDirectoryName.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(destinationDirectoryName)); } diff --git a/src/libraries/System.IO.Packaging/ref/System.IO.Packaging.csproj b/src/libraries/System.IO.Packaging/ref/System.IO.Packaging.csproj index 6a1068da49eaa..56941538f8b06 100644 --- a/src/libraries/System.IO.Packaging/ref/System.IO.Packaging.csproj +++ b/src/libraries/System.IO.Packaging/ref/System.IO.Packaging.csproj @@ -1,11 +1,11 @@ - $(DefineConstants);netcoreapp netstandard2.0;netstandard1.3;net46;$(NetFrameworkCurrent) true + $(DefineConstants);netcoreapp true diff --git a/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj b/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj index 6dd1b630bc739..49d04496c3c32 100644 --- a/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj +++ b/src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj @@ -1,12 +1,12 @@ true - $(DefineConstants);FEATURE_SERIALIZATION - net46;netstandard1.3;netstandard2.0;$(NetFrameworkCurrent)-Windows_NT + netstandard2.0;net46;netstandard1.3;$(NetFrameworkCurrent)-Windows_NT true + $(DefineConstants);FEATURE_SERIALIZATION true diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs index 09413c8a38444..db8cdf81d8b8e 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs @@ -161,7 +161,7 @@ internal void Flush() internal static void ThrowIfInvalidRelationshipType(string relationshipType) { // Look for empty string or string with just spaces - if (relationshipType.Trim() == string.Empty) + if (string.IsNullOrWhiteSpace(relationshipType)) throw new ArgumentException(SR.InvalidRelationshipType); } diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs index c2c79ee231837..c43ca1ac61cd6 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs @@ -79,7 +79,7 @@ public static Uri Create(Uri packageUri, Uri partUri, string fragment) if (fragment != null) { - if (fragment == string.Empty || fragment[0] != '#') + if (fragment.Length == 0 || fragment[0] != '#') throw new ArgumentException(SR.Format(SR.FragmentMustStartWithHash, nameof(fragment))); } @@ -323,7 +323,7 @@ private static PackUriHelper.ValidatedPartUri GetPartUriComponent(Uri packUri) string partName = GetStringForPartUriFromAnyUri(packUri); - if (partName == string.Empty) + if (partName.Length == 0) return null; else return ValidatePartUri(new Uri(partName, UriKind.Relative)); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs index 2b50ad0791ffa..404e5e6fe9e24 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs @@ -49,7 +49,7 @@ public static Uri CreatePartUri(Uri partUri) string partName = GetStringForPartUriFromAnyUri(resolvedUri); - if (partName == string.Empty) + if (partName.Length == 0) throw new ArgumentException(SR.PartUriIsEmpty); ThrowIfPartNameEndsWithSlash(partName); @@ -399,7 +399,7 @@ private static Exception GetExceptionIfPartUriInvalid(Uri partUri, out string pa //We need to make sure that the URI passed to us is not just "/" //"/" is a valid relative uri, but is not a valid partname - if (partName == string.Empty) + if (partName.Length == 0) return new ArgumentException(SR.PartUriIsEmpty); if (partName[0] != ForwardSlashChar) @@ -804,7 +804,7 @@ private bool IsRelationshipUri() // String.Split, will always return an empty string as the // first member in the array as the string starts with a "/" - Debug.Assert(segments.Length > 0 && segments[0] == string.Empty); + Debug.Assert(segments.Length > 0 && segments[0].Length == 0); //If the extension was not equal to .rels, we would have exited early. Debug.Assert(string.CompareOrdinal((Path.GetExtension(segments[segments.Length - 1])), RelationshipPartUpperCaseExtension) == 0); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs index f044bf76c1682..f44daf64e07a0 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs @@ -964,7 +964,7 @@ private void ValidateXmlAttribute(string attributeName, string attributeValue, s ThrowIfXmlAttributeMissing(attributeName, attributeValue, tagName, reader); //Checking for empty attribute - if (attributeValue == string.Empty) + if (attributeValue.Length == 0) throw new XmlException(SR.Format(SR.RequiredAttributeEmpty, tagName, attributeName), null, ((IXmlLineInfo)reader).LineNumber, ((IXmlLineInfo)reader).LinePosition); } diff --git a/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj b/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj index 7f1bb21bb6b55..2af41b5283fb6 100644 --- a/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj +++ b/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj @@ -2,9 +2,9 @@ netstandard2.0 enable - - netcoreapp2.0 + + netcoreapp2.0 diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/BufferSegment.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/BufferSegment.cs index ffc27059d504f..800b141426083 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/BufferSegment.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/BufferSegment.cs @@ -10,7 +10,8 @@ namespace System.IO.Pipelines { internal sealed class BufferSegment : ReadOnlySequenceSegment { - private object? _memoryOwner; + private IMemoryOwner? _memoryOwner; + private byte[]? _array; private BufferSegment? _next; private int _end; @@ -55,36 +56,35 @@ public void SetOwnedMemory(IMemoryOwner memoryOwner) public void SetOwnedMemory(byte[] arrayPoolBuffer) { - _memoryOwner = arrayPoolBuffer; + _array = arrayPoolBuffer; AvailableMemory = arrayPoolBuffer; } public void ResetMemory() { - if (_memoryOwner is IMemoryOwner owner) + IMemoryOwner? memoryOwner = _memoryOwner; + if (memoryOwner != null) { - owner.Dispose(); + _memoryOwner = null; + memoryOwner.Dispose(); } else { - Debug.Assert(_memoryOwner is byte[]); - byte[] poolArray = (byte[])_memoryOwner; - ArrayPool.Shared.Return(poolArray); + Debug.Assert(_array != null); + ArrayPool.Shared.Return(_array); + _array = null; } - // Order of below field clears is significant as it clears in a sequential order - // https://github.com/dotnet/corefx/pull/35256#issuecomment-462800477 Next = null; RunningIndex = 0; Memory = default; - _memoryOwner = null; _next = null; _end = 0; AvailableMemory = default; } // Exposed for testing - internal object? MemoryOwner => _memoryOwner; + internal object? MemoryOwner => (object?)_memoryOwner ?? _array; public Memory AvailableMemory { get; private set; } @@ -124,6 +124,5 @@ internal static long GetLength(long startPosition, BufferSegment endSegment, int { return (endSegment.RunningIndex + (uint)endIndex) - startPosition; } - } } diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs index d66d40d11e71c..b92832c053dad 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs @@ -69,6 +69,9 @@ public sealed partial class Pipe private BufferSegment? _readHead; private int _readHeadIndex; + private readonly int _maxPooledBufferSize; + private bool _disposed; + // The extent of the bytes available to the PipeReader to consume private BufferSegment? _readTail; private int _readTailIndex; @@ -81,7 +84,6 @@ public sealed partial class Pipe // Determines what current operation is in flight (reading/writing) private PipeOperationState _operationState; - private bool _disposed; internal long Length => _unconsumedBytes; @@ -111,6 +113,7 @@ public Pipe(PipeOptions options) // If we're using the default pool then mark it as null since we're just going to use the // array pool under the covers _pool = options.Pool == MemoryPool.Shared ? null : options.Pool; + _maxPooledBufferSize = _pool?.MaxBufferSize ?? 0; _minimumSegmentSize = options.MinimumSegmentSize; _pauseWriterThreshold = options.PauseWriterThreshold; _resumeWriterThreshold = options.ResumeWriterThreshold; @@ -223,16 +226,17 @@ private BufferSegment AllocateSegment(int sizeHint) { BufferSegment newSegment = CreateSegmentUnsynchronized(); - if (_pool is null || sizeHint > _pool.MaxBufferSize) + int maxSize = _maxPooledBufferSize; + if (_pool != null && sizeHint <= maxSize) { - // Use the array pool - int sizeToRequest = GetSegmentSize(sizeHint); - newSegment.SetOwnedMemory(ArrayPool.Shared.Rent(sizeToRequest)); + // Use the specified pool as it fits + newSegment.SetOwnedMemory(_pool.Rent(GetSegmentSize(sizeHint, maxSize))); } else { - // Use the specified pool as it fits - newSegment.SetOwnedMemory(_pool.Rent(GetSegmentSize(sizeHint, _pool.MaxBufferSize))); + // Use the array pool + int sizeToRequest = GetSegmentSize(sizeHint); + newSegment.SetOwnedMemory(ArrayPool.Shared.Rent(sizeToRequest)); } _writingHeadMemory = newSegment.AvailableMemory; @@ -245,7 +249,7 @@ private int GetSegmentSize(int sizeHint, int maxBufferSize = int.MaxValue) // First we need to handle case where hint is smaller than minimum segment size sizeHint = Math.Max(_minimumSegmentSize, sizeHint); // After that adjust it to fit into pools max buffer size - var adjustedToMaximumSize = Math.Min(maxBufferSize, sizeHint); + int adjustedToMaximumSize = Math.Min(maxBufferSize, sizeHint); return adjustedToMaximumSize; } diff --git a/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj b/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj index ee5dd288580e6..9c2991aedecb4 100644 --- a/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj +++ b/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj @@ -151,8 +151,6 @@ Link="Common\Interop\Unix\Interop.Permissions.cs" /> - + /// Reads a number of bytes from an open file descriptor into a specified buffer. + /// + /// The open file descriptor to try to read from + /// The buffer to read info into + /// The size of the buffer + /// + /// Returns the number of bytes read on success; otherwise, -1 is returned + /// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info + /// + [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_Read", SetLastError = true)] + internal static extern unsafe int Read(SafeHandle fd, byte* buffer, int count); + + /// + /// Writes the specified buffer to the provided open file descriptor + /// + /// The file descriptor to try and write to + /// The data to attempt to write + /// The amount of data to write, in bytes + /// + /// Returns the number of bytes written on success; otherwise, returns -1 and sets errno + /// + [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_Write", SetLastError = true)] + internal static extern unsafe int Write(SafeHandle fd, byte* buffer, int bufferSize); + + /// + /// Polls a set of file descriptors for signals and returns what signals have been set + /// + /// A list of PollEvent entries + /// The number of entries in pollEvents + /// The amount of time to wait; -1 for infinite, 0 for immediate return, and a positive number is the number of milliseconds + /// The number of events triggered (i.e. the number of entries in pollEvents with a non-zero TriggeredEvents). May be zero in the event of a timeout. + /// An error or Error.SUCCESS. + [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_Poll")] + private static extern unsafe Error Poll(PollEvent* pollEvents, uint eventCount, int timeout, uint* triggered); + + /// + /// Polls a File Descriptor for the passed in flags. + /// + /// The descriptor to poll + /// The events to poll for + /// The amount of time to wait; -1 for infinite, 0 for immediate return, and a positive number is the number of milliseconds + /// The events that were returned by the poll call. May be PollEvents.POLLNONE in the case of a timeout. + /// An error or Error.SUCCESS. + internal static unsafe Error Poll(SafeHandle fd, PollEvents events, int timeout, out PollEvents triggered) + { + bool gotRef = false; + try + { + fd.DangerousAddRef(ref gotRef); + + var pollEvent = new PollEvent + { + FileDescriptor = fd.DangerousGetHandle().ToInt32(), + Events = events, + }; + + uint unused; + Error err = Poll(&pollEvent, 1, timeout, &unused); + triggered = pollEvent.TriggeredEvents; + return err; + } + finally + { + if (gotRef) + { + fd.DangerousRelease(); + } + } + } } } diff --git a/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj b/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj index c4896b1f163f2..7dece0f9537c2 100644 --- a/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj +++ b/src/libraries/System.IO.Ports/src/System.IO.Ports.csproj @@ -1,17 +1,17 @@ true - $(DefineConstants);NOSPAN + $(DefineConstants);NOSPAN;SERIAL_PORTS true annotations netstandard2.0-Windows_NT;netstandard2.0-Linux;netstandard2.0-OSX;netstandard2.0;net461-Windows_NT;netstandard2.0-FreeBSD;$(NetFrameworkCurrent)-Windows_NT true - true true SR.PlatformNotSupported_IOPorts + true @@ -129,14 +129,8 @@ Link="Common\Interop\Unix\Interop.Errors.cs" /> - - - - + diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SafeSerialDeviceHandle.Unix.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SafeSerialDeviceHandle.Unix.cs index db9d881dec64a..a98bcd4954215 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SafeSerialDeviceHandle.Unix.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SafeSerialDeviceHandle.Unix.cs @@ -35,7 +35,7 @@ internal static SafeSerialDeviceHandle Open(string portName) protected override bool ReleaseHandle() { - Interop.Sys.Shutdown(handle, SocketShutdown.Both); + Interop.Serial.Shutdown(handle, SocketShutdown.Both); int result = Interop.Serial.SerialPortClose(handle); Debug.Assert(result == 0, $"Close failed with result {result} and error {Interop.Sys.GetLastErrorInfo()}"); diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Unix.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Unix.cs index 4616384198b9e..dd8ea97d7b96c 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Unix.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Unix.cs @@ -464,7 +464,7 @@ public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, A // Will wait `timeout` miliseconds or until reading or writing is possible // If no operation is requested it will throw // Returns event which has happened - private Interop.Sys.PollEvents PollEvents(int timeout, bool pollReadEvents, bool pollWriteEvents, out Interop.ErrorInfo? error) + private Interop.PollEvents PollEvents(int timeout, bool pollReadEvents, bool pollWriteEvents, out Interop.ErrorInfo? error) { if (!pollReadEvents && !pollWriteEvents) { @@ -472,20 +472,20 @@ private Interop.Sys.PollEvents PollEvents(int timeout, bool pollReadEvents, bool throw new Exception(); } - Interop.Sys.PollEvents eventsToPoll = Interop.Sys.PollEvents.POLLERR; + Interop.PollEvents eventsToPoll = Interop.PollEvents.POLLERR; if (pollReadEvents) { - eventsToPoll |= Interop.Sys.PollEvents.POLLIN; + eventsToPoll |= Interop.PollEvents.POLLIN; } if (pollWriteEvents) { - eventsToPoll |= Interop.Sys.PollEvents.POLLOUT; + eventsToPoll |= Interop.PollEvents.POLLOUT; } - Interop.Sys.PollEvents events = Interop.Sys.PollEvents.POLLNONE; - Interop.Error ret = Interop.Sys.Poll( + Interop.PollEvents events = Interop.PollEvents.POLLNONE; + Interop.Error ret = Interop.Serial.Poll( _handle, eventsToPoll, timeout, @@ -699,7 +699,7 @@ private unsafe int ProcessRead(SerialStreamIORequest r) fixed (byte* bufPtr = buff) { // assumes dequeue-ing happens on a single thread - int numBytes = Interop.Sys.Read(_handle, bufPtr, buff.Length); + int numBytes = Interop.Serial.Read(_handle, bufPtr, buff.Length); if (numBytes < 0) { @@ -731,7 +731,7 @@ private unsafe int ProcessWrite(SerialStreamIORequest r) fixed (byte* bufPtr = buff) { // assumes dequeue-ing happens on a single thread - int numBytes = Interop.Sys.Write(_handle, bufPtr, buff.Length); + int numBytes = Interop.Serial.Write(_handle, bufPtr, buff.Length); if (numBytes <= 0) { @@ -843,7 +843,7 @@ private unsafe void IOLoop() } else { - Interop.Sys.PollEvents events = PollEvents(1, + Interop.PollEvents events = PollEvents(1, pollReadEvents: hasPendingReads, pollWriteEvents: hasPendingWrites, out Interop.ErrorInfo? error); @@ -854,21 +854,21 @@ private unsafe void IOLoop() break; } - if (events.HasFlag(Interop.Sys.PollEvents.POLLNVAL) || - events.HasFlag(Interop.Sys.PollEvents.POLLERR)) + if (events.HasFlag(Interop.PollEvents.POLLNVAL) || + events.HasFlag(Interop.PollEvents.POLLERR)) { // bad descriptor or some other error we can't handle FinishPendingIORequests(); break; } - if (events.HasFlag(Interop.Sys.PollEvents.POLLIN)) + if (events.HasFlag(Interop.PollEvents.POLLIN)) { int bytesRead = DoIORequest(_readQueue, _processReadDelegate); _totalBytesRead += bytesRead; } - if (events.HasFlag(Interop.Sys.PollEvents.POLLOUT)) + if (events.HasFlag(Interop.PollEvents.POLLOUT)) { DoIORequest(_writeQueue, _processWriteDelegate); } diff --git a/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs b/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs index f52a771eba278..196c19e62d903 100644 --- a/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs +++ b/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs @@ -142,7 +142,7 @@ public sealed partial class ExpandoObject : System.Collections.Generic.ICollecti bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair item) { throw null; } void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) { } bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair item) { throw null; } - void System.Collections.Generic.IDictionary.Add(string key, object value) { } + void System.Collections.Generic.IDictionary.Add(string key, object? value) { } bool System.Collections.Generic.IDictionary.ContainsKey(string key) { throw null; } bool System.Collections.Generic.IDictionary.Remove(string key) { throw null; } bool System.Collections.Generic.IDictionary.TryGetValue(string key, out object? value) { throw null; } @@ -1193,11 +1193,11 @@ public sealed partial class ReadOnlyCollectionBuilder : System.Collections.Ge public void Reverse(int index, int count) { } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.IList.Add(object value) { throw null; } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + int System.Collections.IList.Add(object? value) { throw null; } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } public T[] ToArray() { throw null; } public System.Collections.ObjectModel.ReadOnlyCollection ToReadOnlyCollection() { throw null; } } diff --git a/src/libraries/System.Linq/src/System/Linq/First.cs b/src/libraries/System.Linq/src/System/Linq/First.cs index 95ada9a81cf4e..8763d207c133d 100644 --- a/src/libraries/System.Linq/src/System/Linq/First.cs +++ b/src/libraries/System.Linq/src/System/Linq/First.cs @@ -89,11 +89,6 @@ private static TSource TryGetFirst(this IEnumerable source, Fu ThrowHelper.ThrowArgumentNullException(ExceptionArgument.predicate); } - if (source is OrderedEnumerable ordered) - { - return ordered.TryGetFirst(predicate, out found); - } - foreach (TSource element in source) { if (predicate(element)) diff --git a/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.cs b/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.cs index da0ed0c7c4769..f28f7efa672de 100644 --- a/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.cs +++ b/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.cs @@ -73,40 +73,6 @@ internal IEnumerator GetEnumerator(int minIdx, int maxIdx) IOrderedEnumerable IOrderedEnumerable.CreateOrderedEnumerable(Func keySelector, IComparer? comparer, bool descending) => new OrderedEnumerable(_source, keySelector, comparer, @descending, this); - [return: MaybeNull] - public TElement TryGetFirst(Func predicate, out bool found) - { - CachingComparer comparer = GetComparer(); - using (IEnumerator e = _source.GetEnumerator()) - { - TElement value; - do - { - if (!e.MoveNext()) - { - found = false; - return default!; - } - - value = e.Current; - } - while (!predicate(value)); - - comparer.SetElement(value); - while (e.MoveNext()) - { - TElement x = e.Current; - if (predicate(x) && comparer.Compare(x, true) < 0) - { - value = x; - } - } - - found = true; - return value; - } - } - [return: MaybeNull] public TElement TryGetLast(Func predicate, out bool found) { diff --git a/src/libraries/System.Linq/tests/OrderByTests.cs b/src/libraries/System.Linq/tests/OrderByTests.cs index 8c99b5668c763..627becd98800b 100644 --- a/src/libraries/System.Linq/tests/OrderByTests.cs +++ b/src/libraries/System.Linq/tests/OrderByTests.cs @@ -291,6 +291,38 @@ public void FirstOnEmptyOrderedThrows() Assert.Throws(() => Enumerable.Empty().OrderBy(i => i).First()); } + [Fact] + public void FirstWithPredicateOnOrdered() + { + IEnumerable orderBy = Enumerable.Range(0, 10).Shuffle().OrderBy(i => i); + IEnumerable orderByDescending = Enumerable.Range(0, 10).Shuffle().OrderByDescending(i => i); + int counter; + + counter = 0; + Assert.Equal(0, orderBy.First(i => { counter++; return true; })); + Assert.Equal(1, counter); + + counter = 0; + Assert.Equal(9, orderBy.First(i => { counter++; return i == 9; })); + Assert.Equal(10, counter); + + counter = 0; + Assert.Throws(() => orderBy.First(i => { counter++; return false; })); + Assert.Equal(10, counter); + + counter = 0; + Assert.Equal(9, orderByDescending.First(i => { counter++; return true; })); + Assert.Equal(1, counter); + + counter = 0; + Assert.Equal(0, orderByDescending.First(i => { counter++; return i == 0; })); + Assert.Equal(10, counter); + + counter = 0; + Assert.Throws(() => orderByDescending.First(i => { counter++; return false; })); + Assert.Equal(10, counter); + } + [Fact] public void FirstOrDefaultOnOrdered() { @@ -300,6 +332,38 @@ public void FirstOrDefaultOnOrdered() Assert.Equal(0, Enumerable.Empty().OrderBy(i => i).FirstOrDefault()); } + [Fact] + public void FirstOrDefaultWithPredicateOnOrdered() + { + IEnumerable orderBy = Enumerable.Range(0, 10).Shuffle().OrderBy(i => i); + IEnumerable orderByDescending = Enumerable.Range(0, 10).Shuffle().OrderByDescending(i => i); + int counter; + + counter = 0; + Assert.Equal(0, orderBy.FirstOrDefault(i => { counter++; return true; })); + Assert.Equal(1, counter); + + counter = 0; + Assert.Equal(9, orderBy.FirstOrDefault(i => { counter++; return i == 9; })); + Assert.Equal(10, counter); + + counter = 0; + Assert.Equal(0, orderBy.FirstOrDefault(i => { counter++; return false; })); + Assert.Equal(10, counter); + + counter = 0; + Assert.Equal(9, orderByDescending.FirstOrDefault(i => { counter++; return true; })); + Assert.Equal(1, counter); + + counter = 0; + Assert.Equal(0, orderByDescending.FirstOrDefault(i => { counter++; return i == 0; })); + Assert.Equal(10, counter); + + counter = 0; + Assert.Equal(0, orderByDescending.FirstOrDefault(i => { counter++; return false; })); + Assert.Equal(10, counter); + } + [Fact] public void LastOnOrdered() { diff --git a/src/libraries/System.Management/src/Resources/Strings.resx b/src/libraries/System.Management/src/Resources/Strings.resx index f740f60b40f99..40f915ba6f640 100644 --- a/src/libraries/System.Management/src/Resources/Strings.resx +++ b/src/libraries/System.Management/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -292,4 +293,7 @@ The native library '{0}' does not have all required functions. Please, update the .NET Framework. - + + The Query string supplied was invalid or improperly formed. Token `{0}` is expected + + \ No newline at end of file diff --git a/src/libraries/System.Management/src/System.Management.csproj b/src/libraries/System.Management/src/System.Management.csproj index 271afb85dff68..ac50cd7a9b1bf 100644 --- a/src/libraries/System.Management/src/System.Management.csproj +++ b/src/libraries/System.Management/src/System.Management.csproj @@ -8,9 +8,9 @@ - SR.PlatformNotSupported_SystemManagement + SR.PlatformNotSupported_SystemManagement - + - + diff --git a/src/libraries/System.Management/src/System/Management/ManagementDateTime.cs b/src/libraries/System.Management/src/System/Management/ManagementDateTime.cs index 27114f9453b21..6a71452dc1120 100644 --- a/src/libraries/System.Management/src/System/Management/ManagementDateTime.cs +++ b/src/libraries/System.Management/src/System/Management/ManagementDateTime.cs @@ -415,7 +415,7 @@ public static string ToDmtfTimeInterval(TimeSpan timespan) // and also negative timespan cannot be represented in DMTF if (timespan.Days > MAXDATE_INTIMESPAN || timespan < TimeSpan.Zero) { - throw new System.ArgumentOutOfRangeException(); + throw new System.ArgumentOutOfRangeException(nameof(timespan)); } dmtftimespan = (dmtftimespan + timespan.Hours.ToString(frmInt32).PadLeft(2, '0')); diff --git a/src/libraries/System.Management/src/System/Management/ManagementQuery.cs b/src/libraries/System.Management/src/System/Management/ManagementQuery.cs index 62797f9dbd3e5..1c49c3019e4de 100644 --- a/src/libraries/System.Management/src/System/Management/ManagementQuery.cs +++ b/src/libraries/System.Management/src/System/Management/ManagementQuery.cs @@ -1040,13 +1040,13 @@ protected internal override void ParseQuery(string query) // Should start with "select" if ((q.Length < keyword.Length) || (0 != string.Compare(q, 0, keyword, 0, keyword.Length, StringComparison.OrdinalIgnoreCase))) - throw new ArgumentException(SR.InvalidQuery, "select"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, keyword), nameof(query)); q = q.Remove(0, keyword.Length).TrimStart(null); // Next should be a '*' if (0 != q.IndexOf('*', 0)) - throw new ArgumentException(SR.InvalidQuery, "*"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, "*"), nameof(query)); q = q.Remove(0, 1).TrimStart(null); @@ -1055,7 +1055,7 @@ protected internal override void ParseQuery(string query) if ((q.Length < keyword.Length) || (0 != string.Compare(q, 0, keyword, 0, keyword.Length, StringComparison.OrdinalIgnoreCase))) - throw new ArgumentException(SR.InvalidQuery, "from"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, keyword), nameof(query)); q = q.Remove(0, keyword.Length).TrimStart(null); @@ -1064,7 +1064,7 @@ protected internal override void ParseQuery(string query) if ((q.Length < keyword.Length) || (0 != string.Compare(q, 0, keyword, 0, keyword.Length, StringComparison.OrdinalIgnoreCase))) - throw new ArgumentException(SR.InvalidQuery, "meta_class"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, keyword), nameof(query)); q = q.Remove(0, keyword.Length).TrimStart(null); @@ -1076,7 +1076,7 @@ protected internal override void ParseQuery(string query) if ((q.Length < keyword.Length) || (0 != string.Compare(q, 0, keyword, 0, keyword.Length, StringComparison.OrdinalIgnoreCase))) - throw new ArgumentException(SR.InvalidQuery, "where"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, keyword), nameof(query)); q = q.Remove(0, keyword.Length); @@ -1650,7 +1650,7 @@ protected internal override void ParseQuery(string query) //Find "associators" clause if (0 != string.Compare(q, 0, TokenAssociators, 0, TokenAssociators.Length, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(SR.InvalidQuery, "associators"); // Invalid query + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, TokenAssociators), nameof(query)); // Invalid query // Strip off the clause q = q.Remove(0, TokenAssociators.Length); @@ -1663,7 +1663,7 @@ protected internal override void ParseQuery(string query) // Next token should be "of" if (0 != string.Compare(q, 0, TokenOf, 0, TokenOf.Length, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(SR.InvalidQuery, "of"); // Invalid query + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, TokenOf), nameof(query)); // Invalid query // Strip off the clause and leading WS q = q.Remove(0, TokenOf.Length).TrimStart(null); @@ -1687,7 +1687,7 @@ protected internal override void ParseQuery(string query) { // Next should be the "where" clause if (0 != string.Compare(q, 0, TokenWhere, 0, TokenWhere.Length, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(SR.InvalidQuery, "where"); // Invalid query + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, TokenWhere), nameof(query)); // Invalid query q = q.Remove(0, TokenWhere.Length); @@ -2167,7 +2167,7 @@ protected internal override void ParseQuery(string query) //Find "references" clause if (0 != string.Compare(q, 0, TokenReferences, 0, TokenReferences.Length, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(SR.InvalidQuery, "references"); // Invalid query + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, TokenReferences), nameof(query)); // Invalid query // Strip off the clause q = q.Remove(0, TokenReferences.Length); @@ -2180,7 +2180,7 @@ protected internal override void ParseQuery(string query) // Next token should be "of" if (0 != string.Compare(q, 0, TokenOf, 0, TokenOf.Length, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(SR.InvalidQuery, "of"); // Invalid query + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, TokenOf), nameof(query)); // Invalid query // Strip off the clause and leading WS q = q.Remove(0, TokenOf.Length).TrimStart(null); @@ -2204,7 +2204,7 @@ protected internal override void ParseQuery(string query) { // Next should be the "where" clause if (0 != string.Compare(q, 0, TokenWhere, 0, TokenWhere.Length, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException(SR.InvalidQuery, "where"); // Invalid query + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, TokenWhere), nameof(query)); // Invalid query q = q.Remove(0, TokenWhere.Length); @@ -3043,13 +3043,13 @@ protected internal override void ParseQuery(string query) q = q.Remove(0, keyword.Length).TrimStart(null); if (!q.StartsWith("*", StringComparison.Ordinal)) - throw new ArgumentException(SR.InvalidQuery, "*"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, "*"), nameof(query)); q = q.Remove(0, 1).TrimStart(null); //Find "from" clause keyword = "from "; if ((q.Length < keyword.Length) || (0 != string.Compare(q, 0, keyword, 0, keyword.Length, StringComparison.OrdinalIgnoreCase))) - throw new ArgumentException(SR.InvalidQuery, "from"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, keyword), nameof(query)); ParseToken(ref q, keyword, null, ref bFound, ref eventClassName); //Find "within" clause @@ -3119,7 +3119,7 @@ protected internal override void ParseQuery(string query) q = q.Remove(0, keyword.Length); if (q.Length == 0) //bad query - throw new ArgumentException(SR.InvalidQuery, "having"); + throw new ArgumentException(SR.Format(SR.InvalidQueryTokenExpected, keyword), nameof(query)); havingCondition = q; } diff --git a/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.csproj index 5a3ac5ef09098..af8add8a69fa8 100644 --- a/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/ref/System.Net.Http.Json.csproj @@ -1,6 +1,6 @@ - netstandard2.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0 enable diff --git a/src/libraries/System.Net.Http.Json/src/Resources/Strings.resx b/src/libraries/System.Net.Http.Json/src/Resources/Strings.resx index 1722e93d5009d..332b5e17c461c 100644 --- a/src/libraries/System.Net.Http.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http.Json/src/Resources/Strings.resx @@ -127,7 +127,7 @@ The character set provided in ContentType is not supported. - The provided ContentType is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'. + The provided ContentType '{0}' is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'. The specified type {0} must derive from the specific value's type {1}. diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs index 79ecf1addd362..0d76a030f9fca 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.cs @@ -84,7 +84,7 @@ private static void ValidateContent(HttpContent content) !mediaType.Equals(JsonContent.JsonMediaType, StringComparison.OrdinalIgnoreCase) && !IsValidStructuredSyntaxJsonSuffix(mediaType.AsSpan())) { - throw new NotSupportedException(SR.ContentTypeNotSupported); + throw new NotSupportedException(SR.Format(SR.ContentTypeNotSupported, mediaType)); } } diff --git a/src/libraries/System.Net.Http/ref/System.Net.Http.cs b/src/libraries/System.Net.Http/ref/System.Net.Http.cs index 0e0752189fe65..91d4676d3ab99 100644 --- a/src/libraries/System.Net.Http/ref/System.Net.Http.cs +++ b/src/libraries/System.Net.Http/ref/System.Net.Http.cs @@ -99,7 +99,7 @@ public partial class HttpClientHandler : System.Net.Http.HttpMessageHandler public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get { throw null; } } public System.Net.CookieContainer CookieContainer { get { throw null; } set { } } public System.Net.ICredentials? Credentials { get { throw null; } set { } } - public static System.Func DangerousAcceptAnyServerCertificateValidator { get { throw null; } } + public static System.Func DangerousAcceptAnyServerCertificateValidator { get { throw null; } } public System.Net.ICredentials? DefaultProxyCredentials { get { throw null; } set { } } public int MaxAutomaticRedirections { get { throw null; } set { } } public int MaxConnectionsPerServer { get { throw null; } set { } } @@ -209,7 +209,8 @@ public partial class HttpResponseMessage : System.IDisposable { public HttpResponseMessage() { } public HttpResponseMessage(System.Net.HttpStatusCode statusCode) { } - public System.Net.Http.HttpContent? Content { get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.AllowNull] + public System.Net.Http.HttpContent Content { get { throw null; } set { } } public System.Net.Http.Headers.HttpResponseHeaders Headers { get { throw null; } } public bool IsSuccessStatusCode { get { throw null; } } public string? ReasonPhrase { get { throw null; } set { } } diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 0744c3d731f13..2f7eb9dc48f43 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -18,12 +18,15 @@ + + + @@ -128,7 +131,6 @@ - @@ -142,7 +144,6 @@ - @@ -299,8 +300,6 @@ Link="Common\System\Net\NegotiationInfoClass.cs" /> - + Provides a zero-length HttpContent implementation. + internal sealed class EmptyContent : HttpContent + { + protected internal override bool TryComputeLength(out long length) + { + length = 0; + return true; + } + + protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) => + Task.CompletedTask; + + protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : + SerializeToStreamAsync(stream, context); + + protected override Task CreateContentReadStreamAsync() => + Task.FromResult(EmptyReadStream.Instance); + + protected override Task CreateContentReadStreamAsync(CancellationToken cancellationToken) => + cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : + CreateContentReadStreamAsync(); + + internal override Stream? TryCreateContentReadStream() => EmptyReadStream.Instance; + + internal override bool AllowDuplex => false; + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/EmptyReadStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/EmptyReadStream.cs similarity index 100% rename from src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/EmptyReadStream.cs rename to src/libraries/System.Net.Http/src/System/Net/Http/EmptyReadStream.cs diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpResponseHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpResponseHeaders.cs index 8da6741d18748..38643801d34e2 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpResponseHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpResponseHeaders.cs @@ -147,6 +147,8 @@ internal HttpResponseHeaders(bool containsTrailingHeaders = false) _containsTrailingHeaders = containsTrailingHeaders; } + internal bool ContainsTrailingHeaders => _containsTrailingHeaders; + internal override void AddHeaders(HttpHeaders sourceHeaders) { base.AddHeaders(sourceHeaders); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpBaseStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpBaseStream.cs similarity index 100% rename from src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpBaseStream.cs rename to src/libraries/System.Net.Http/src/System/Net/Http/HttpBaseStream.cs diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs index 1851c5aa3da6a..304b810d54874 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs @@ -222,7 +222,7 @@ public SslProtocols SslProtocols _socketsHttpHandler.SendAsync(request, cancellationToken); } - public static Func DangerousAcceptAnyServerCertificateValidator { get; } = delegate { return true; }; + public static Func DangerousAcceptAnyServerCertificateValidator { get; } = delegate { return true; }; private void ThrowForModifiedManagedSslOptionsIfStarted() { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs index dbe85b55dea63..9873b4246f554 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs @@ -2,6 +2,8 @@ // 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.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Net.Http.Headers; using System.Text; @@ -39,9 +41,10 @@ public Version Version internal void SetVersionWithoutValidation(Version value) => _version = value; - public HttpContent? Content + [AllowNull] + public HttpContent Content { - get { return _content; } + get { return _content ??= new EmptyContent(); } set { CheckDisposed(); @@ -104,28 +107,28 @@ public HttpStatusCode StatusCode internal void SetReasonPhraseWithoutValidation(string value) => _reasonPhrase = value; - public HttpResponseHeaders Headers + public HttpResponseHeaders Headers => _headers ??= new HttpResponseHeaders(); + + public HttpResponseHeaders TrailingHeaders => _trailingHeaders ??= new HttpResponseHeaders(containsTrailingHeaders: true); + + /// Stores the supplied trailing headers into this instance. + /// + /// In the common/desired case where response.TrailingHeaders isn't accessed until after the whole payload has been + /// received, will still be null, and we can simply store the supplied instance into + /// and assume ownership of the instance. In the uncommon case where it was accessed, + /// we add all of the headers to the existing instance. + /// + internal void StoreReceivedTrailingHeaders(HttpResponseHeaders headers) { - get + Debug.Assert(headers.ContainsTrailingHeaders); + + if (_trailingHeaders is null) { - if (_headers == null) - { - _headers = new HttpResponseHeaders(); - } - return _headers; + _trailingHeaders = headers; } - } - - public HttpResponseHeaders TrailingHeaders - { - get + else { - if (_trailingHeaders == null) - { - _trailingHeaders = new HttpResponseHeaders(containsTrailingHeaders: true); - } - - return _trailingHeaders; + _trailingHeaders.AddHeaders(headers); } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs index 7f88b005bfdfd..288022837e832 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs @@ -136,7 +136,12 @@ public static ValueTask EstablishSslConnectionAsync(SslClientAuthenti Func localFromHttpClientHandler = mapper.FromHttpClientHandler; HttpRequestMessage localRequest = request; sslOptions.RemoteCertificateValidationCallback = (object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) => - localFromHttpClientHandler(localRequest, certificate as X509Certificate2, chain, sslPolicyErrors); + { + Debug.Assert(localRequest != null); + bool result = localFromHttpClientHandler(localRequest, certificate as X509Certificate2, chain, sslPolicyErrors); + localRequest = null!; // ensure the SslOptions and this callback don't keep the first HttpRequestMessage alive indefinitely + return result; + }; } // Create the SslStream, authenticate, and return it. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index 00b9bc1d2cb6b..9af644504a03e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -5,6 +5,7 @@ using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net.Http.Headers; using System.Net.Http.HPack; @@ -133,17 +134,17 @@ public async ValueTask SetupAsync() s_http2ConnectionPreface.AsSpan().CopyTo(_outgoingBuffer.AvailableSpan); _outgoingBuffer.Commit(s_http2ConnectionPreface.Length); - // Send SETTINGS frame - WriteFrameHeader(new FrameHeader(FrameHeader.SettingLength, FrameType.Settings, FrameFlags.None, 0)); - - // Disable push promise + // Send SETTINGS frame. Disable push promise. + FrameHeader.WriteTo(_outgoingBuffer.AvailableSpan, FrameHeader.SettingLength, FrameType.Settings, FrameFlags.None, streamId: 0); + _outgoingBuffer.Commit(FrameHeader.Size); BinaryPrimitives.WriteUInt16BigEndian(_outgoingBuffer.AvailableSpan, (ushort)SettingId.EnablePush); _outgoingBuffer.Commit(2); BinaryPrimitives.WriteUInt32BigEndian(_outgoingBuffer.AvailableSpan, 0); _outgoingBuffer.Commit(4); // Send initial connection-level WINDOW_UPDATE - WriteFrameHeader(new FrameHeader(FrameHeader.WindowUpdateLength, FrameType.WindowUpdate, FrameFlags.None, 0)); + FrameHeader.WriteTo(_outgoingBuffer.AvailableSpan, FrameHeader.WindowUpdateLength, FrameType.WindowUpdate, FrameFlags.None, streamId: 0); + _outgoingBuffer.Commit(FrameHeader.Size); BinaryPrimitives.WriteUInt32BigEndian(_outgoingBuffer.AvailableSpan, (ConnectionWindowSize - DefaultInitialWindowSize)); _outgoingBuffer.Commit(4); @@ -195,7 +196,7 @@ private async ValueTask ReadFrameAsync(bool initialFrame = false) // Parse the frame header from our read buffer and validate it. FrameHeader frameHeader = FrameHeader.ReadFrom(_incomingBuffer.ActiveSpan); - if (frameHeader.Length > FrameHeader.MaxLength) + if (frameHeader.PayloadLength > FrameHeader.MaxPayloadLength) { if (initialFrame && NetEventSource.IsEnabled) { @@ -204,21 +205,21 @@ private async ValueTask ReadFrameAsync(bool initialFrame = false) } _incomingBuffer.Discard(FrameHeader.Size); - throw new Http2ConnectionException(initialFrame ? Http2ProtocolErrorCode.ProtocolError : Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(initialFrame ? Http2ProtocolErrorCode.ProtocolError : Http2ProtocolErrorCode.FrameSizeError); } _incomingBuffer.Discard(FrameHeader.Size); // Ensure we've read the frame contents into our buffer. - if (_incomingBuffer.ActiveLength < frameHeader.Length) + if (_incomingBuffer.ActiveLength < frameHeader.PayloadLength) { - _incomingBuffer.EnsureAvailableSpace(frameHeader.Length - _incomingBuffer.ActiveLength); + _incomingBuffer.EnsureAvailableSpace(frameHeader.PayloadLength - _incomingBuffer.ActiveLength); do { int bytesRead = await _stream.ReadAsync(_incomingBuffer.AvailableMemory).ConfigureAwait(false); _incomingBuffer.Commit(bytesRead); - if (bytesRead == 0) ThrowPrematureEOF(frameHeader.Length); + if (bytesRead == 0) ThrowPrematureEOF(frameHeader.PayloadLength); } - while (_incomingBuffer.ActiveLength < frameHeader.Length); + while (_incomingBuffer.ActiveLength < frameHeader.PayloadLength); } // Return the read frame header. @@ -236,7 +237,7 @@ private async Task ProcessIncomingFramesAsync() FrameHeader frameHeader = await ReadFrameAsync(initialFrame: true).ConfigureAwait(false); if (frameHeader.Type != FrameType.Settings || frameHeader.AckFlag) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } if (NetEventSource.IsEnabled) Trace($"Frame 0: {frameHeader}."); @@ -318,7 +319,8 @@ private async Task ProcessIncomingFramesAsync() case FrameType.PushPromise: // Should not happen, since we disable this in our initial SETTINGS case FrameType.Continuation: // Should only be received while processing headers in ProcessHeadersFrame default: - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); + break; } } } @@ -338,7 +340,7 @@ private async Task ProcessIncomingFramesAsync() { if (streamId <= 0 || streamId >= _nextStream) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } lock (SyncObject) @@ -369,10 +371,10 @@ private async ValueTask ProcessHeadersFrame(FrameHeader frameHeader) http2Stream?.OnHeadersStart(); _hpackDecoder.Decode( - GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length), frameHeader.PaddedFlag, frameHeader.PriorityFlag), + GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), frameHeader.PaddedFlag, frameHeader.PriorityFlag), frameHeader.EndHeadersFlag, http2Stream); - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); while (!frameHeader.EndHeadersFlag) { @@ -380,14 +382,14 @@ private async ValueTask ProcessHeadersFrame(FrameHeader frameHeader) if (frameHeader.Type != FrameType.Continuation || frameHeader.StreamId != streamId) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } _hpackDecoder.Decode( - _incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length), + _incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), frameHeader.EndHeadersFlag, http2Stream); - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); } _hpackDecoder.CompleteDecode(); @@ -404,7 +406,7 @@ private ReadOnlySpan GetFrameData(ReadOnlySpan frameData, bool hasPa { if (frameData.Length == 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } int padLength = frameData[0]; @@ -412,7 +414,7 @@ private ReadOnlySpan GetFrameData(ReadOnlySpan frameData, bool hasPa if (frameData.Length < padLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } frameData = frameData.Slice(0, frameData.Length - padLength); @@ -422,7 +424,7 @@ private ReadOnlySpan GetFrameData(ReadOnlySpan frameData, bool hasPa { if (frameData.Length < FrameHeader.PriorityInfoLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } // We ignore priority info. @@ -443,7 +445,7 @@ private void ProcessAltSvcFrame(FrameHeader frameHeader) if (NetEventSource.IsEnabled) Trace($"{frameHeader}"); Debug.Assert(frameHeader.Type == FrameType.AltSvc); - ReadOnlySpan span = _incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length); + ReadOnlySpan span = _incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength); if (BinaryPrimitives.TryReadUInt16BigEndian(span, out ushort originLength)) { @@ -464,7 +466,7 @@ private void ProcessAltSvcFrame(FrameHeader frameHeader) } } - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); } private void ProcessDataFrame(FrameHeader frameHeader) @@ -476,7 +478,7 @@ private void ProcessDataFrame(FrameHeader frameHeader) // Note, http2Stream will be null if this is a closed stream. // Just ignore the frame in this case. - ReadOnlySpan frameData = GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length), hasPad: frameHeader.PaddedFlag, hasPriority: false); + ReadOnlySpan frameData = GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), hasPad: frameHeader.PaddedFlag, hasPriority: false); if (http2Stream != null) { @@ -490,7 +492,7 @@ private void ProcessDataFrame(FrameHeader frameHeader) ExtendWindow(frameData.Length); } - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); } private void ProcessSettingsFrame(FrameHeader frameHeader) @@ -499,19 +501,19 @@ private void ProcessSettingsFrame(FrameHeader frameHeader) if (frameHeader.StreamId != 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } if (frameHeader.AckFlag) { - if (frameHeader.Length != 0) + if (frameHeader.PayloadLength != 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(Http2ProtocolErrorCode.FrameSizeError); } if (!_expectingSettingsAck) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } // We only send SETTINGS once initially, so we don't need to do anything in response to the ACK. @@ -520,13 +522,13 @@ private void ProcessSettingsFrame(FrameHeader frameHeader) } else { - if ((frameHeader.Length % 6) != 0) + if ((frameHeader.PayloadLength % 6) != 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(Http2ProtocolErrorCode.FrameSizeError); } // Parse settings and process the ones we care about. - ReadOnlySpan settings = _incomingBuffer.ActiveSpan.Slice(0, frameHeader.Length); + ReadOnlySpan settings = _incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength); while (settings.Length > 0) { Debug.Assert((settings.Length % 6) == 0); @@ -545,7 +547,7 @@ private void ProcessSettingsFrame(FrameHeader frameHeader) case SettingId.InitialWindowSize: if (settingValue > 0x7FFFFFFF) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FlowControlError); + ThrowProtocolError(Http2ProtocolErrorCode.FlowControlError); } ChangeInitialWindowSize((int)settingValue); @@ -554,7 +556,7 @@ private void ProcessSettingsFrame(FrameHeader frameHeader) case SettingId.MaxFrameSize: if (settingValue < 16384 || settingValue > 16777215) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } // We don't actually store this value; we always send frames of the minimum size (16K). @@ -567,7 +569,7 @@ private void ProcessSettingsFrame(FrameHeader frameHeader) } } - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); // Send acknowledgement // Don't wait for completion, which could happen asynchronously. @@ -611,14 +613,14 @@ private void ProcessPriorityFrame(FrameHeader frameHeader) { Debug.Assert(frameHeader.Type == FrameType.Priority); - if (frameHeader.StreamId == 0 || frameHeader.Length != FrameHeader.PriorityInfoLength) + if (frameHeader.StreamId == 0 || frameHeader.PayloadLength != FrameHeader.PriorityInfoLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } // Ignore priority info. - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); } private void ProcessPingFrame(FrameHeader frameHeader) @@ -627,18 +629,18 @@ private void ProcessPingFrame(FrameHeader frameHeader) if (frameHeader.StreamId != 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } if (frameHeader.AckFlag) { // We never send PING, so an ACK indicates a protocol error - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } - if (frameHeader.Length != FrameHeader.PingLength) + if (frameHeader.PayloadLength != FrameHeader.PingLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(Http2ProtocolErrorCode.FrameSizeError); } // We don't wait for SendPingAckAsync to complete before discarding @@ -650,16 +652,16 @@ private void ProcessPingFrame(FrameHeader frameHeader) LogExceptions(SendPingAckAsync(pingContentLong)); - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); } private void ProcessWindowUpdateFrame(FrameHeader frameHeader) { Debug.Assert(frameHeader.Type == FrameType.WindowUpdate); - if (frameHeader.Length != FrameHeader.WindowUpdateLength) + if (frameHeader.PayloadLength != FrameHeader.WindowUpdateLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(Http2ProtocolErrorCode.FrameSizeError); } int amount = BinaryPrimitives.ReadInt32BigEndian(_incomingBuffer.ActiveSpan) & 0x7FFFFFFF; @@ -668,10 +670,10 @@ private void ProcessWindowUpdateFrame(FrameHeader frameHeader) Debug.Assert(amount >= 0); if (amount == 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); if (frameHeader.StreamId == 0) { @@ -694,28 +696,28 @@ private void ProcessRstStreamFrame(FrameHeader frameHeader) { Debug.Assert(frameHeader.Type == FrameType.RstStream); - if (frameHeader.Length != FrameHeader.RstStreamLength) + if (frameHeader.PayloadLength != FrameHeader.RstStreamLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(Http2ProtocolErrorCode.FrameSizeError); } if (frameHeader.StreamId == 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } Http2Stream? http2Stream = GetStream(frameHeader.StreamId); if (http2Stream == null) { // Ignore invalid stream ID, as per RFC - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); return; } var protocolError = (Http2ProtocolErrorCode)BinaryPrimitives.ReadInt32BigEndian(_incomingBuffer.ActiveSpan); if (NetEventSource.IsEnabled) Trace(frameHeader.StreamId, $"{nameof(protocolError)}={protocolError}"); - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); if (protocolError == Http2ProtocolErrorCode.RefusedStream) { @@ -731,16 +733,16 @@ private void ProcessGoAwayFrame(FrameHeader frameHeader) { Debug.Assert(frameHeader.Type == FrameType.GoAway); - if (frameHeader.Length < FrameHeader.GoAwayMinLength) + if (frameHeader.PayloadLength < FrameHeader.GoAwayMinLength) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); + ThrowProtocolError(Http2ProtocolErrorCode.FrameSizeError); } // GoAway frames always apply to the whole connection, never to a single stream. // According to RFC 7540 section 6.8, this should be a connection error. if (frameHeader.StreamId != 0) { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + ThrowProtocolError(); } int lastValidStream = (int)(BinaryPrimitives.ReadUInt32BigEndian(_incomingBuffer.ActiveSpan) & 0x7FFFFFFF); @@ -749,7 +751,7 @@ private void ProcessGoAwayFrame(FrameHeader frameHeader) StartTerminatingConnection(lastValidStream, new Http2ConnectionException(errorCode)); - _incomingBuffer.Discard(frameHeader.Length); + _incomingBuffer.Discard(frameHeader.PayloadLength); } internal async Task FlushAsync(CancellationToken cancellationToken = default) @@ -800,7 +802,7 @@ private async ValueTask> StartWriteAsync(int writeBytes, Cancellati if (_abortException != null) { _writerLock.Exit(); - throw new IOException(SR.net_http_request_aborted, _abortException); + ThrowRequestAborted(_abortException); } // Flush anything necessary, and return back the write buffer to use. @@ -891,58 +893,12 @@ private void EndWrite(bool forceFlush) } } - private async ValueTask AcquireWriteLockAsync(CancellationToken cancellationToken) - { - ValueTask acquireLockTask = _writerLock.EnterAsync(cancellationToken); - if (acquireLockTask.IsCompletedSuccessfully) - { - acquireLockTask.GetAwaiter().GetResult(); // to enable the value task sources to be pooled - } - else - { - Interlocked.Increment(ref _pendingWriters); - - try - { - await acquireLockTask.ConfigureAwait(false); - } - catch - { - if (Interlocked.Decrement(ref _pendingWriters) == 0) - { - // If a pending waiter is canceled, we may end up in a situation where a previously written frame - // saw that there were pending writers and as such deferred its flush to them, but if/when that pending - // writer is canceled, nothing may end up flushing the deferred work (at least not promptly). To compensate, - // if a pending writer does end up being canceled, we flush asynchronously. We can't check whether there's such - // a pending operation because we failed to acquire the lock that protects that state. But we can at least only - // do the flush if our decrement caused the pending count to reach 0: if it's still higher than zero, then there's - // at least one other pending writer who can handle the flush. Worst case, we pay for a flush that ends up being - // a nop. Note: we explicitly do not pass in the cancellationToken; if we're here, it's almost certainly because - // cancellation was requested, and it's because of that cancellation that we need to flush. - LogExceptions(FlushAsync(cancellationToken: default)); - } - - throw; - } - - Interlocked.Decrement(ref _pendingWriters); - } - - // If the connection has been aborted, then fail now instead of trying to send more data. - if (_abortException != null) - { - _writerLock.Exit(); - throw new IOException(SR.net_http_request_aborted, _abortException); - } - } - private async Task SendSettingsAckAsync() { Memory writeBuffer = await StartWriteAsync(FrameHeader.Size).ConfigureAwait(false); if (NetEventSource.IsEnabled) Trace("Started writing."); - FrameHeader frameHeader = new FrameHeader(0, FrameType.Settings, FrameFlags.Ack, 0); - frameHeader.WriteTo(writeBuffer); + FrameHeader.WriteTo(writeBuffer.Span, 0, FrameType.Settings, FrameFlags.Ack, streamId: 0); FinishWrite(FlushTiming.AfterPendingWrites); } @@ -953,12 +909,9 @@ private async Task SendPingAckAsync(long pingContent) Memory writeBuffer = await StartWriteAsync(FrameHeader.Size + FrameHeader.PingLength).ConfigureAwait(false); if (NetEventSource.IsEnabled) Trace("Started writing."); - FrameHeader frameHeader = new FrameHeader(FrameHeader.PingLength, FrameType.Ping, FrameFlags.Ack, 0); - frameHeader.WriteTo(writeBuffer); - writeBuffer = writeBuffer.Slice(FrameHeader.Size); - Debug.Assert(sizeof(long) == FrameHeader.PingLength); - BinaryPrimitives.WriteInt64BigEndian(writeBuffer.Span, pingContent); + FrameHeader.WriteTo(writeBuffer.Span, FrameHeader.PingLength, FrameType.Ping, FrameFlags.Ack, streamId: 0); + BinaryPrimitives.WriteInt64BigEndian(writeBuffer.Span.Slice(FrameHeader.Size), pingContent); FinishWrite(FlushTiming.AfterPendingWrites); } @@ -968,11 +921,8 @@ private async Task SendRstStreamAsync(int streamId, Http2ProtocolErrorCode error Memory writeBuffer = await StartWriteAsync(FrameHeader.Size + FrameHeader.RstStreamLength).ConfigureAwait(false); if (NetEventSource.IsEnabled) Trace(streamId, $"Started writing. {nameof(errorCode)}={errorCode}"); - FrameHeader frameHeader = new FrameHeader(FrameHeader.RstStreamLength, FrameType.RstStream, FrameFlags.None, streamId); - frameHeader.WriteTo(writeBuffer); - writeBuffer = writeBuffer.Slice(FrameHeader.Size); - - BinaryPrimitives.WriteInt32BigEndian(writeBuffer.Span, (int)errorCode); + FrameHeader.WriteTo(writeBuffer.Span, FrameHeader.RstStreamLength, FrameType.RstStream, FrameFlags.None, streamId); + BinaryPrimitives.WriteInt32BigEndian(writeBuffer.Span.Slice(FrameHeader.Size), (int)errorCode); FinishWrite(FlushTiming.Now); // ensure cancellation is seen as soon as possible } @@ -1206,7 +1156,8 @@ private void WriteHeaders(HttpRequestMessage request, ref ArrayBuffer headerBuff } } - private HttpRequestException GetShutdownException() + [DoesNotReturn] + private void ThrowShutdownException() { Debug.Assert(Monitor.IsEntered(SyncObject)); @@ -1233,7 +1184,7 @@ private HttpRequestException GetShutdownException() innerException = new ObjectDisposedException(nameof(Http2Connection)); } - return new HttpRequestException(SR.net_http_client_execution_error, innerException, allowRetry: RequestRetryType.RetryOnSameOrNextProxy); + ThrowRetry(SR.net_http_client_execution_error, innerException); } private async ValueTask SendHeadersAsync(HttpRequestMessage request, CancellationToken cancellationToken, bool mustFlush) @@ -1261,7 +1212,8 @@ private async ValueTask SendHeadersAsync(HttpRequestMessage request { Debug.Assert(_disposed || _lastStreamId != -1); Debug.Assert(_httpStreams.Count == 0); - throw GetShutdownException(); + ThrowShutdownException(); + throw; // unreachable } } @@ -1276,15 +1228,20 @@ private async ValueTask SendHeadersAsync(HttpRequestMessage request Debug.Assert(remaining.Length > 0); // Calculate the total number of bytes we're going to use (content + headers). - int frameCount = ((remaining.Length - 1) / FrameHeader.MaxLength) + 1; + int frameCount = ((remaining.Length - 1) / FrameHeader.MaxPayloadLength) + 1; int totalSize = remaining.Length + (frameCount * FrameHeader.Size); ReadOnlyMemory current; - (current, remaining) = SplitBuffer(remaining, FrameHeader.MaxLength); + (current, remaining) = SplitBuffer(remaining, FrameHeader.MaxPayloadLength); FrameFlags flags = (remaining.Length == 0 ? FrameFlags.EndHeaders : FrameFlags.None) | (request.Content == null ? FrameFlags.EndStream : FrameFlags.None); + // Construct and initialize the new Http2Stream instance. It's stream ID must be set below + // before the instance is used and stored into the dictionary. However, we construct it here + // so as to avoid the allocation and initialization expense while holding multiple locks. + var http2Stream = new Http2Stream(request, this, _initialWindowSize); + // Start the write. This serializes access to write to the connection, and ensures that HEADERS // and CONTINUATION frames stay together, as they must do. We use the lock as well to ensure new // streams are created and started in order. @@ -1293,7 +1250,6 @@ private async ValueTask SendHeadersAsync(HttpRequestMessage request { // Allocate the next available stream ID. Note that if we fail before sending the headers, // we'll just skip this stream ID, which is fine. - int streamId; lock (SyncObject) { if (_nextStream == MaxStreamId || _disposed || _lastStreamId != -1) @@ -1301,44 +1257,43 @@ private async ValueTask SendHeadersAsync(HttpRequestMessage request // We ran out of stream IDs or we raced between acquiring the connection from the pool and shutting down. // Throw a retryable request exception. This will cause retry logic to kick in // and perform another connection attempt. The user should never see this exception. - throw GetShutdownException(); + ThrowShutdownException(); } - streamId = _nextStream; - // Client-initiated streams are always odd-numbered, so increase by 2. + http2Stream.StreamId = _nextStream; _nextStream += 2; + + // We're about to flush the HEADERS frame, so add the stream to the dictionary now. + // The lifetime of the stream is now controlled by the stream itself and the connection. + // This can fail if the connection is shutting down, in which case we will cancel sending this frame. + _httpStreams.Add(http2Stream.StreamId, http2Stream); } - if (NetEventSource.IsEnabled) Trace(streamId, $"Started writing. {nameof(totalSize)}={totalSize}"); + if (NetEventSource.IsEnabled) Trace(http2Stream.StreamId, $"Started writing. {nameof(totalSize)}={totalSize}"); // Copy the HEADERS frame. - new FrameHeader(current.Length, FrameType.Headers, flags, streamId).WriteTo(writeBuffer.Span); + FrameHeader.WriteTo(writeBuffer.Span, current.Length, FrameType.Headers, flags, http2Stream.StreamId); writeBuffer = writeBuffer.Slice(FrameHeader.Size); current.CopyTo(writeBuffer); writeBuffer = writeBuffer.Slice(current.Length); - if (NetEventSource.IsEnabled) Trace(streamId, $"Wrote HEADERS frame. Length={current.Length}, flags={flags}"); + if (NetEventSource.IsEnabled) Trace(http2Stream.StreamId, $"Wrote HEADERS frame. Length={current.Length}, flags={flags}"); // Copy CONTINUATION frames, if any. while (remaining.Length > 0) { - (current, remaining) = SplitBuffer(remaining, FrameHeader.MaxLength); + (current, remaining) = SplitBuffer(remaining, FrameHeader.MaxPayloadLength); flags = remaining.Length == 0 ? FrameFlags.EndHeaders : FrameFlags.None; - new FrameHeader(current.Length, FrameType.Continuation, flags, streamId).WriteTo(writeBuffer.Span); + FrameHeader.WriteTo(writeBuffer.Span, current.Length, FrameType.Continuation, flags, http2Stream.StreamId); writeBuffer = writeBuffer.Slice(FrameHeader.Size); current.CopyTo(writeBuffer); writeBuffer = writeBuffer.Slice(current.Length); - if (NetEventSource.IsEnabled) Trace(streamId, $"Wrote CONTINUATION frame. Length={current.Length}, flags={flags}"); + if (NetEventSource.IsEnabled) Trace(http2Stream.StreamId, $"Wrote CONTINUATION frame. Length={current.Length}, flags={flags}"); } Debug.Assert(writeBuffer.Length == 0); - // We're about to flush the HEADERS frame, so add the stream to the dictionary now. - // The lifetime of the stream is now controlled by the stream itself and the connection. - // This can fail if the connection is shutting down, in which case we will cancel sending this frame. - Http2Stream http2Stream = AddStream(streamId, request); - FinishWrite(mustFlush || (flags & FrameFlags.EndStream) != 0 ? FlushTiming.AfterPendingWrites : FlushTiming.Eventually); return http2Stream; } @@ -1365,7 +1320,7 @@ private async Task SendStreamDataAsync(int streamId, ReadOnlyMemory buffer while (remaining.Length > 0) { - int frameSize = Math.Min(remaining.Length, FrameHeader.MaxLength); + int frameSize = Math.Min(remaining.Length, FrameHeader.MaxPayloadLength); // Once credit had been granted, we want to actually consume those bytes. frameSize = await _connectionWindow.RequestCreditAsync(frameSize, cancellationToken).ConfigureAwait(false); @@ -1387,14 +1342,8 @@ private async Task SendStreamDataAsync(int streamId, ReadOnlyMemory buffer throw; } - FrameHeader frameHeader = new FrameHeader(current.Length, FrameType.Data, FrameFlags.None, streamId); - frameHeader.WriteTo(writeBuffer); - writeBuffer = writeBuffer.Slice(FrameHeader.Size); - - current.CopyTo(writeBuffer); - writeBuffer = writeBuffer.Slice(current.Length); - - Debug.Assert(writeBuffer.Length == 0); + FrameHeader.WriteTo(writeBuffer.Span, current.Length, FrameType.Data, FrameFlags.None, streamId); + current.CopyTo(writeBuffer.Slice(FrameHeader.Size)); FinishWrite(FlushTiming.Eventually); // no need to flush, as the request content may do so explicitly, or worst case we'll do so as part of the end data frame } @@ -1405,8 +1354,7 @@ private async Task SendEndStreamAsync(int streamId) Memory writeBuffer = await StartWriteAsync(FrameHeader.Size).ConfigureAwait(false); if (NetEventSource.IsEnabled) Trace(streamId, "Started writing."); - FrameHeader frameHeader = new FrameHeader(0, FrameType.Data, FrameFlags.EndStream, streamId); - frameHeader.WriteTo(writeBuffer); + FrameHeader.WriteTo(writeBuffer.Span, 0, FrameType.Data, FrameFlags.EndStream, streamId); FinishWrite(FlushTiming.AfterPendingWrites); // finished sending request body, so flush soon (but ok to wait for pending packets) } @@ -1419,11 +1367,8 @@ private async Task SendWindowUpdateAsync(int streamId, int amount) Memory writeBuffer = await StartWriteAsync(FrameHeader.Size + FrameHeader.WindowUpdateLength).ConfigureAwait(false); if (NetEventSource.IsEnabled) Trace(streamId, $"Started writing. {nameof(amount)}={amount}"); - FrameHeader frameHeader = new FrameHeader(FrameHeader.WindowUpdateLength, FrameType.WindowUpdate, FrameFlags.None, streamId); - frameHeader.WriteTo(writeBuffer); - writeBuffer = writeBuffer.Slice(FrameHeader.Size); - - BinaryPrimitives.WriteInt32BigEndian(writeBuffer.Span, amount); + FrameHeader.WriteTo(writeBuffer.Span, FrameHeader.WindowUpdateLength, FrameType.WindowUpdate, FrameFlags.None, streamId); + BinaryPrimitives.WriteInt32BigEndian(writeBuffer.Span.Slice(FrameHeader.Size), amount); FinishWrite(FlushTiming.Now); // make sure window updates are seen as soon as possible } @@ -1452,15 +1397,6 @@ private void ExtendWindow(int amount) LogExceptions(SendWindowUpdateAsync(0, windowUpdateSize)); } - private void WriteFrameHeader(FrameHeader frameHeader) - { - if (NetEventSource.IsEnabled) Trace($"{frameHeader}"); - Debug.Assert(_outgoingBuffer.AvailableMemory.Length >= FrameHeader.Size); - - frameHeader.WriteTo(_outgoingBuffer.AvailableSpan); - _outgoingBuffer.Commit(FrameHeader.Size); - } - /// Abort all streams and cause further processing to fail. /// Exception causing Abort to be called. private void Abort(Exception abortException) @@ -1648,15 +1584,15 @@ private enum FrameType : byte Last = 10 } - private struct FrameHeader + private readonly struct FrameHeader { - public int Length; - public FrameType Type; - public FrameFlags Flags; - public int StreamId; + public readonly int PayloadLength; + public readonly FrameType Type; + public readonly FrameFlags Flags; + public readonly int StreamId; public const int Size = 9; - public const int MaxLength = 16384; + public const int MaxPayloadLength = 16384; public const int SettingLength = 6; // per setting (total SETTINGS length must be a multiple of this) public const int PriorityInfoLength = 5; // for both PRIORITY frame and priority info within HEADERS @@ -1665,11 +1601,11 @@ private struct FrameHeader public const int RstStreamLength = 4; public const int GoAwayMinLength = 8; - public FrameHeader(int length, FrameType type, FrameFlags flags, int streamId) + public FrameHeader(int payloadLength, FrameType type, FrameFlags flags, int streamId) { Debug.Assert(streamId >= 0); - Length = length; + PayloadLength = payloadLength; Type = type; Flags = flags; StreamId = streamId; @@ -1685,36 +1621,31 @@ public static FrameHeader ReadFrom(ReadOnlySpan buffer) { Debug.Assert(buffer.Length >= Size); - return new FrameHeader( - (buffer[0] << 16) | (buffer[1] << 8) | buffer[2], - (FrameType)buffer[3], - (FrameFlags)buffer[4], - (int)((uint)((buffer[5] << 24) | (buffer[6] << 16) | (buffer[7] << 8) | buffer[8]) & 0x7FFFFFFF)); + FrameFlags flags = (FrameFlags)buffer[4]; // do first to avoid some bounds checks + int payloadLength = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; + FrameType type = (FrameType)buffer[3]; + int streamId = (int)(BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(5)) & 0x7FFFFFFF); + + return new FrameHeader(payloadLength, type, flags, streamId); } - public void WriteTo(Span buffer) + public static void WriteTo(Span destination, int payloadLength, FrameType type, FrameFlags flags, int streamId) { - Debug.Assert(buffer.Length >= Size); - Debug.Assert(Type <= FrameType.Last); - Debug.Assert((Flags & FrameFlags.ValidBits) == Flags); - Debug.Assert(Length <= MaxLength); + Debug.Assert(destination.Length >= Size); + Debug.Assert(type <= FrameType.Last); + Debug.Assert((flags & FrameFlags.ValidBits) == flags); + Debug.Assert((uint)payloadLength <= MaxPayloadLength); - buffer[0] = (byte)((Length & 0x00FF0000) >> 16); - buffer[1] = (byte)((Length & 0x0000FF00) >> 8); - buffer[2] = (byte)(Length & 0x000000FF); - - buffer[3] = (byte)Type; - buffer[4] = (byte)Flags; - - buffer[5] = (byte)((StreamId & 0xFF000000) >> 24); - buffer[6] = (byte)((StreamId & 0x00FF0000) >> 16); - buffer[7] = (byte)((StreamId & 0x0000FF00) >> 8); - buffer[8] = (byte)(StreamId & 0x000000FF); + // This ordering helps eliminate bounds checks. + BinaryPrimitives.WriteInt32BigEndian(destination.Slice(5), streamId); + destination[4] = (byte)flags; + destination[0] = (byte)((payloadLength & 0x00FF0000) >> 16); + destination[1] = (byte)((payloadLength & 0x0000FF00) >> 8); + destination[2] = (byte)(payloadLength & 0x000000FF); + destination[3] = (byte)type; } - public void WriteTo(Memory buffer) => WriteTo(buffer.Span); - - public override string ToString() => $"StreamId={StreamId}; Type={Type}; Flags={Flags}; Length={Length}"; // Description for diagnostic purposes + public override string ToString() => $"StreamId={StreamId}; Type={Type}; Flags={Flags}; PayloadLength={PayloadLength}"; // Description for diagnostic purposes } [Flags] @@ -1835,26 +1766,6 @@ public sealed override async Task SendAsync(HttpRequestMess } } - private Http2Stream AddStream(int streamId, HttpRequestMessage request) - { - lock (SyncObject) - { - if (_disposed || _lastStreamId != -1) - { - // The connection is shutting down. - // Throw a retryable request exception. This will cause retry logic to kick in - // and perform another connection attempt. The user should never see this exception. - throw GetShutdownException(); - } - - Http2Stream http2Stream = new Http2Stream(request, this, streamId, _initialWindowSize); - - _httpStreams.Add(streamId, http2Stream); - - return http2Stream; - } - } - private void RemoveStream(Http2Stream http2Stream) { if (NetEventSource.IsEnabled) Trace(http2Stream.StreamId, ""); @@ -1862,27 +1773,25 @@ private void RemoveStream(Http2Stream http2Stream) lock (SyncObject) { - if (!_httpStreams.Remove(http2Stream.StreamId, out Http2Stream? removed)) + if (!_httpStreams.Remove(http2Stream.StreamId)) { Debug.Fail($"Stream {http2Stream.StreamId} not found in dictionary during RemoveStream???"); return; } - _concurrentStreams.AdjustCredit(1); - - Debug.Assert(removed == http2Stream, "_httpStreams.TryRemove returned unexpected stream"); - if (_httpStreams.Count == 0) { // If this was last pending request, get timestamp so we can monitor idle time. _idleSinceTickCount = Environment.TickCount64; - } - if (_disposed || _lastStreamId != -1) - { - CheckForShutdown(); + if (_disposed || _lastStreamId != -1) + { + CheckForShutdown(); + } } } + + _concurrentStreams.AdjustCredit(1); } public sealed override string ToString() => $"{nameof(Http2Connection)}({_pool})"; // Description for diagnostic purposes @@ -1898,5 +1807,20 @@ private void RemoveStream(Http2Stream http2Stream) memberName, // method name message); // message + [DoesNotReturn] + private static void ThrowRetry(string message, Exception innerException) => + throw new HttpRequestException(message, innerException, allowRetry: RequestRetryType.RetryOnSameOrNextProxy); + + [DoesNotReturn] + private static void ThrowRequestAborted(Exception? innerException = null) => + throw new IOException(SR.net_http_request_aborted, innerException); + + [DoesNotReturn] + private static void ThrowProtocolError() => + ThrowProtocolError(Http2ProtocolErrorCode.ProtocolError); + + [DoesNotReturn] + private static void ThrowProtocolError(Http2ProtocolErrorCode errorCode) => + throw new Http2ConnectionException(errorCode); } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index 2948820a0aab1..146a48da27d18 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -18,7 +18,7 @@ namespace System.Net.Http { internal sealed partial class Http2Connection { - private sealed class Http2Stream : IValueTaskSource, IHttpTrace, IHttpHeadersHandler + private sealed class Http2Stream : IValueTaskSource, IHttpHeadersHandler, IHttpTrace { private const int InitialStreamBufferSize = #if DEBUG @@ -27,14 +27,13 @@ private sealed class Http2Stream : IValueTaskSource, IHttpTrace, IHttpHeadersHan 1024; #endif - private static readonly byte[] s_statusHeaderName = Encoding.ASCII.GetBytes(":status"); + private static ReadOnlySpan StatusHeaderName => new byte[] { (byte)':', (byte)'s', (byte)'t', (byte)'a', (byte)'t', (byte)'u', (byte)'s' }; private readonly Http2Connection _connection; - private readonly int _streamId; private readonly HttpRequestMessage _request; private HttpResponseMessage? _response; /// Stores any trailers received after returning the response content to the caller. - private List>? _trailers; + private HttpResponseHeaders? _trailers; private ArrayBuffer _responseBuffer; // mutable struct, do not make this readonly private int _pendingWindowUpdate; @@ -81,9 +80,6 @@ private sealed class Http2Stream : IValueTaskSource, IHttpTrace, IHttpHeadersHan private readonly CancellationTokenSource? _requestBodyCancellationSource; - // This is a linked token combining the above source and the user-supplied token to SendRequestBodyAsync - private CancellationToken _requestBodyCancellationToken; - private readonly TaskCompletionSource? _expect100ContinueWaiter; private int _headerBudgetRemaining; @@ -93,11 +89,10 @@ private sealed class Http2Stream : IValueTaskSource, IHttpTrace, IHttpHeadersHan // See comment on ConnectionWindowThreshold. private const int StreamWindowThreshold = StreamWindowSize / 8; - public Http2Stream(HttpRequestMessage request, Http2Connection connection, int streamId, int initialWindowSize) + public Http2Stream(HttpRequestMessage request, Http2Connection connection, int initialWindowSize) { _request = request; _connection = connection; - _streamId = streamId; _requestCompletionState = StreamCompletionState.InProgress; _responseCompletionState = StreamCompletionState.InProgress; @@ -134,12 +129,19 @@ public Http2Stream(HttpRequestMessage request, Http2Connection connection, int s } } + _response = new HttpResponseMessage() + { + Version = HttpVersion.Version20, + RequestMessage = _request, + Content = new HttpConnectionResponseContent() + }; + if (NetEventSource.IsEnabled) Trace($"{request}, {nameof(initialWindowSize)}={initialWindowSize}"); } private object SyncObject => this; // this isn't handed out to code that may lock on it - public int StreamId => _streamId; + public int StreamId { get; set; } public HttpResponseMessage GetAndClearResponse() { @@ -162,28 +164,44 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) } if (NetEventSource.IsEnabled) Trace($"{_request.Content}"); - Debug.Assert(_requestBodyCancellationSource != null); - // Create a linked cancellation token source so that we can cancel the request in the event of receiving RST_STREAM - // and similiar situations where we need to cancel the request body (see Cancel method). - _requestBodyCancellationToken = cancellationToken.CanBeCanceled ? - CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _requestBodyCancellationSource.Token).Token : - _requestBodyCancellationSource.Token; - + // Cancel the request body sending if cancellation is requested on the supplied cancellation token. + // Normally we might create a linked token, but once cancellation is requested, we can't recover anyway, + // so it's fine to cancel the source representing the whole request body, and doing so allows us to avoid + // creating another CTS instance and the associated nodes inside of it. With this, cancellation will be + // requested on _requestBodyCancellationSource when we need to cancel the request stream for any reason, + // such as receiving an RST_STREAM or when the passed in token has cancellation requested. However, to + // avoid unnecessarily registering with the cancellation token unless we have to, we wait to do so until + // either we know we need to do a Expect: 100-continue send or until we know that the copying of our + // content completed asynchronously. + CancellationTokenRegistration linkedRegistration = default; try { bool sendRequestContent = true; if (_expect100ContinueWaiter != null) { - sendRequestContent = await WaitFor100ContinueAsync(_requestBodyCancellationToken).ConfigureAwait(false); + linkedRegistration = RegisterRequestBodyCancellation(cancellationToken); + sendRequestContent = await WaitFor100ContinueAsync(_requestBodyCancellationSource.Token).ConfigureAwait(false); } if (sendRequestContent) { - using (Http2WriteStream writeStream = new Http2WriteStream(this)) + using var writeStream = new Http2WriteStream(this); + + ValueTask vt = _request.Content.InternalCopyToAsync(writeStream, context: null, _requestBodyCancellationSource.Token); + if (vt.IsCompleted) { - await _request.Content.InternalCopyToAsync(writeStream, null, _requestBodyCancellationToken).ConfigureAwait(false); + vt.GetAwaiter().GetResult(); + } + else + { + if (linkedRegistration.Equals(default)) + { + linkedRegistration = RegisterRequestBodyCancellation(cancellationToken); + } + + await vt.ConfigureAwait(false); } } @@ -192,9 +210,7 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) catch (Exception e) { if (NetEventSource.IsEnabled) Trace($"Failed to send request body: {e}"); - - bool signalWaiter = false; - bool sendReset = false; + bool signalWaiter; Debug.Assert(!Monitor.IsEntered(SyncObject)); lock (SyncObject) @@ -213,19 +229,15 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) } // This should not cause RST_STREAM to be sent because the request is still marked as in progress. + bool sendReset; (signalWaiter, sendReset) = CancelResponseBody(); Debug.Assert(!sendReset); _requestCompletionState = StreamCompletionState.Failed; - sendReset = true; Complete(); } - if (sendReset) - { - SendReset(); - } - + SendReset(); if (signalWaiter) { _waitSource.SetResult(true); @@ -233,6 +245,10 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) throw; } + finally + { + linkedRegistration.Dispose(); + } // New scope here to avoid variable name conflict on "sendReset" { @@ -241,21 +257,14 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) lock (SyncObject) { Debug.Assert(_requestCompletionState == StreamCompletionState.InProgress, $"Request already completed with state={_requestCompletionState}"); - _requestCompletionState = StreamCompletionState.Completed; - if (_responseCompletionState == StreamCompletionState.Failed) + + if (_responseCompletionState != StreamCompletionState.InProgress) { // Note, we can reach this point if the response stream failed but cancellation didn't propagate before we finished. - sendReset = true; + sendReset = _responseCompletionState == StreamCompletionState.Failed; Complete(); } - else - { - if (_responseCompletionState == StreamCompletionState.Completed) - { - Complete(); - } - } } if (sendReset) @@ -266,7 +275,7 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) { // Send EndStream asynchronously and without cancellation. // If this fails, it means that the connection is aborting and we will be reset. - _connection.LogExceptions(_connection.SendEndStreamAsync(_streamId)); + _connection.LogExceptions(_connection.SendEndStreamAsync(StreamId)); } } } @@ -277,29 +286,31 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken) // If we get response status >= 300, we will not send the request body. public async ValueTask WaitFor100ContinueAsync(CancellationToken cancellationToken) { - Debug.Assert(_request.Content != null); + Debug.Assert(_request?.Content != null); if (NetEventSource.IsEnabled) Trace($"Waiting to send request body content for 100-Continue."); - // use TCS created in constructor. It will complete when one of two things occurs: - // 1. if a timer fires before we receive the relevant response from the server. - // 2. if we receive the relevant response from the server before a timer fires. - // In the first case, we could run this continuation synchronously, but in the latter, we shouldn't, - // as we could end up starting the body copy operation on the main event loop thread, which could - // then starve the processing of other requests. So, we make the TCS RunContinuationsAsynchronously. - bool sendRequestContent; + // Use TCS created in constructor. It will complete when one of three things occurs: + // 1. we receive the relevant response from the server. + // 2. the timer fires before we receive the relevant response from the server. + // 3. cancellation is requested before we receive the relevant response from the server. + // We need to run the continuation asynchronously for cases 1 and 3 (for 1 so that we don't starve the body copy operation, and + // for 3 so that we don't run a lot of work as part of code calling Cancel), so the TCS is created to run continuations asynchronously. + // We await the created Timer's disposal so that we ensure any work associated with it has quiesced prior to this method + // returning, just in case this object is pooled and potentially reused for another operation in the future. TaskCompletionSource waiter = _expect100ContinueWaiter!; - using (var expect100Timer = new Timer(s => + using (cancellationToken.UnsafeRegister(s => ((TaskCompletionSource)s!).TrySetResult(false), waiter)) + await using (new Timer(s => { var thisRef = (Http2Stream)s!; if (NetEventSource.IsEnabled) thisRef.Trace($"100-Continue timer expired."); thisRef._expect100ContinueWaiter?.TrySetResult(true); - }, this, _connection._pool.Settings._expect100ContinueTimeout, Timeout.InfiniteTimeSpan)) + }, this, _connection._pool.Settings._expect100ContinueTimeout, Timeout.InfiniteTimeSpan).ConfigureAwait(false)) { - sendRequestContent = await waiter.Task.ConfigureAwait(false); - // By now, either we got a response from the server or the timer expired. + bool shouldSendContent = await waiter.Task.ConfigureAwait(false); + // By now, either we got a response from the server or the timer expired or cancellation was requested. + CancellationHelper.ThrowIfCancellationRequested(cancellationToken); + return shouldSendContent; } - - return sendRequestContent; } private void SendReset() @@ -315,7 +326,7 @@ private void SendReset() // Don't send a RST_STREAM if we've already received one from the server. if (_resetException == null) { - _connection.LogExceptions(_connection.SendRstStreamAsync(_streamId, Http2ProtocolErrorCode.Cancel)); + _connection.LogExceptions(_connection.SendRstStreamAsync(StreamId, Http2ProtocolErrorCode.Cancel)); } } @@ -329,14 +340,11 @@ private void Complete() _connection.RemoveStream(this); - lock (SyncObject) + CreditWaiter? w = _creditWaiter; + if (w != null) { - CreditWaiter? w = _creditWaiter; - if (w != null) - { - w.Dispose(); - _creditWaiter = null; - } + w.Dispose(); + _creditWaiter = null; } } @@ -360,11 +368,8 @@ private void Cancel() (signalWaiter, sendReset) = CancelResponseBody(); } - if (requestBodyCancellationSource != null) - { - // When cancellation propagates, SendRequestBodyAsync will set _requestCompletionState to Failed - requestBodyCancellationSource.Cancel(); - } + // When cancellation propagates, SendRequestBodyAsync will set _requestCompletionState to Failed + requestBodyCancellationSource?.Cancel(); if (sendReset) { @@ -439,7 +444,7 @@ void IHttpHeadersHandler.OnStaticIndexedHeader(int index, ReadOnlySpan val public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) { if (NetEventSource.IsEnabled) Trace($"{Encoding.ASCII.GetString(name)}: {Encoding.ASCII.GetString(value)}"); - Debug.Assert(name != null && name.Length > 0); + Debug.Assert(name.Length > 0); _headerBudgetRemaining -= name.Length + value.Length; if (_headerBudgetRemaining < 0) @@ -465,7 +470,7 @@ public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) throw new HttpRequestException(SR.net_http_invalid_response_pseudo_header_in_trailer); } - if (name.SequenceEqual(s_statusHeaderName)) + if (name.SequenceEqual(StatusHeaderName)) { if (_responseProtocolState != ResponseProtocolState.ExpectingStatus) { @@ -474,13 +479,8 @@ public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) } int statusValue = ParseStatusCode(value); - _response = new HttpResponseMessage() - { - Version = HttpVersion.Version20, - RequestMessage = _request, - Content = new HttpConnectionResponseContent(), - StatusCode = (HttpStatusCode)statusValue - }; + Debug.Assert(_response != null); + _response.StatusCode = (HttpStatusCode)statusValue; if (statusValue < 200) { @@ -540,7 +540,7 @@ public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) { Debug.Assert(_trailers != null); string headerValue = descriptor.GetHeaderValue(value); - _trailers.Add(KeyValuePair.Create((descriptor.HeaderType & HttpHeaderType.Request) == HttpHeaderType.Request ? descriptor.AsCustomHeader() : descriptor, headerValue)); + _trailers.TryAddWithoutValidation((descriptor.HeaderType & HttpHeaderType.Request) == HttpHeaderType.Request ? descriptor.AsCustomHeader() : descriptor, headerValue); } else if ((descriptor.HeaderType & HttpHeaderType.Content) == HttpHeaderType.Content) { @@ -563,20 +563,20 @@ public void OnHeadersStart() Debug.Assert(!Monitor.IsEntered(SyncObject)); lock (SyncObject) { - if (_responseProtocolState == ResponseProtocolState.Aborted) - { - return; - } - - if (_responseProtocolState != ResponseProtocolState.ExpectingStatus && _responseProtocolState != ResponseProtocolState.ExpectingData) - { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); - } - - if (_responseProtocolState == ResponseProtocolState.ExpectingData) + switch (_responseProtocolState) { - _responseProtocolState = ResponseProtocolState.ExpectingTrailingHeaders; - _trailers ??= new List>(); + case ResponseProtocolState.ExpectingStatus: + case ResponseProtocolState.Aborted: + break; + + case ResponseProtocolState.ExpectingData: + _responseProtocolState = ResponseProtocolState.ExpectingTrailingHeaders; + _trailers ??= new HttpResponseHeaders(containsTrailingHeaders: true); + break; + + default: + ThrowProtocolError(); + break; } } } @@ -587,45 +587,38 @@ public void OnHeadersComplete(bool endStream) bool signalWaiter; lock (SyncObject) { - if (_responseProtocolState == ResponseProtocolState.Aborted) + switch (_responseProtocolState) { - return; - } + case ResponseProtocolState.Aborted: + return; - if (_responseProtocolState != ResponseProtocolState.ExpectingHeaders && _responseProtocolState != ResponseProtocolState.ExpectingTrailingHeaders && _responseProtocolState != ResponseProtocolState.ExpectingIgnoredHeaders) - { - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); - } + case ResponseProtocolState.ExpectingHeaders: + _responseProtocolState = endStream ? ResponseProtocolState.Complete : ResponseProtocolState.ExpectingData; + break; - if (_responseProtocolState == ResponseProtocolState.ExpectingHeaders) - { - _responseProtocolState = endStream ? ResponseProtocolState.Complete : ResponseProtocolState.ExpectingData; - } - else if (_responseProtocolState == ResponseProtocolState.ExpectingTrailingHeaders) - { - if (!endStream) - { - if (NetEventSource.IsEnabled) Trace("Trailing headers received without endStream"); - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); - } + case ResponseProtocolState.ExpectingTrailingHeaders: + if (!endStream) + { + if (NetEventSource.IsEnabled) Trace("Trailing headers received without endStream"); + ThrowProtocolError(); + } + _responseProtocolState = ResponseProtocolState.Complete; + break; - _responseProtocolState = ResponseProtocolState.Complete; - } - else if (_responseProtocolState == ResponseProtocolState.ExpectingIgnoredHeaders) - { - if (endStream) - { - // we should not get endStream while processing 1xx response. - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); - } + case ResponseProtocolState.ExpectingIgnoredHeaders: + if (endStream) + { + // we should not get endStream while processing 1xx response. + ThrowProtocolError(); + } - _responseProtocolState = ResponseProtocolState.ExpectingStatus; - // We should wait for final response before signaling to waiter. - return; - } - else - { - _responseProtocolState = ResponseProtocolState.ExpectingData; + // We should wait for final response before signaling to waiter. + _responseProtocolState = ResponseProtocolState.ExpectingStatus; + return; + + default: + ThrowProtocolError(); + break; } if (endStream) @@ -659,21 +652,24 @@ public void OnResponseData(ReadOnlySpan buffer, bool endStream) bool signalWaiter; lock (SyncObject) { - if (_responseProtocolState == ResponseProtocolState.Aborted) + switch (_responseProtocolState) { - return; - } + case ResponseProtocolState.ExpectingData: + break; - if (_responseProtocolState != ResponseProtocolState.ExpectingData) - { - // Flow control messages are not valid in this state. - throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); + case ResponseProtocolState.Aborted: + return; + + default: + // Flow control messages are not valid in this state. + ThrowProtocolError(); + break; } if (_responseBuffer.ActiveLength + buffer.Length > StreamWindowSize) { // Window size exceeded. - throw new Http2ConnectionException(Http2ProtocolErrorCode.FlowControlError); + ThrowProtocolError(Http2ProtocolErrorCode.FlowControlError); } _responseBuffer.EnsureAvailableSpace(buffer.Length); @@ -785,19 +781,19 @@ private void CheckResponseBodyState() { Debug.Assert(Monitor.IsEntered(SyncObject)); - if (_resetException != null) + if (_resetException is Exception resetException) { if (_canRetry) { - throw new HttpRequestException(SR.net_http_request_aborted, _resetException, allowRetry: RequestRetryType.RetryOnSameOrNextProxy); + ThrowRetry(SR.net_http_request_aborted, resetException); } - throw new IOException(SR.net_http_request_aborted, _resetException); + ThrowRequestAborted(resetException); } if (_responseProtocolState == ResponseProtocolState.Aborted) { - throw new IOException(SR.net_http_request_aborted); + ThrowRequestAborted(); } } @@ -859,7 +855,7 @@ public async Task ReadResponseHeadersAsync(CancellationToken cancellationToken) { // If there are any trailers, copy them over to the response. Normally this would be handled by // the response stream hitting EOF, but if there is no response body, we do it here. - CopyTrailersToResponseMessage(_response); + MoveTrailersToResponseMessage(_response); responseContent.SetStream(EmptyReadStream.Instance); } else @@ -895,7 +891,7 @@ private void ExtendWindow(int amount) int windowUpdateSize = _pendingWindowUpdate; _pendingWindowUpdate = 0; - _connection.LogExceptions(_connection.SendWindowUpdateAsync(_streamId, windowUpdateSize)); + _connection.LogExceptions(_connection.SendWindowUpdateAsync(StreamId, windowUpdateSize)); } private (bool wait, int bytesRead) TryReadFromBuffer(Span buffer, bool partOfSyncRead = false) @@ -954,7 +950,7 @@ public int ReadData(Span buffer, HttpResponseMessage responseMessage) else { // We've hit EOF. Pull in from the Http2Stream any trailers that were temporarily stored there. - CopyTrailersToResponseMessage(responseMessage); + MoveTrailersToResponseMessage(responseMessage); } return bytesRead; @@ -983,7 +979,7 @@ public async ValueTask ReadDataAsync(Memory buffer, HttpResponseMessa else { // We've hit EOF. Pull in from the Http2Stream any trailers that were temporarily stored there. - CopyTrailersToResponseMessage(responseMessage); + MoveTrailersToResponseMessage(responseMessage); } return bytesRead; @@ -994,7 +990,7 @@ public void CopyTo(HttpResponseMessage responseMessage, Stream destination, int byte[] buffer = ArrayPool.Shared.Rent(bufferSize); try { - // Generallly the same logic as in ReadData, but wrapped in a loop where every read segment is written to the destination. + // Generally the same logic as in ReadData, but wrapped in a loop where every read segment is written to the destination. while (true) { (bool wait, int bytesRead) = TryReadFromBuffer(buffer, partOfSyncRead: true); @@ -1014,7 +1010,7 @@ public void CopyTo(HttpResponseMessage responseMessage, Stream destination, int else { // We've hit EOF. Pull in from the Http2Stream any trailers that were temporarily stored there. - CopyTrailersToResponseMessage(responseMessage); + MoveTrailersToResponseMessage(responseMessage); return; } } @@ -1030,7 +1026,7 @@ public async Task CopyToAsync(HttpResponseMessage responseMessage, Stream destin byte[] buffer = ArrayPool.Shared.Rent(bufferSize); try { - // Generallly the same logic as in ReadDataAsync, but wrapped in a loop where every read segment is written to the destination. + // Generally the same logic as in ReadDataAsync, but wrapped in a loop where every read segment is written to the destination. while (true) { (bool wait, int bytesRead) = TryReadFromBuffer(buffer); @@ -1050,7 +1046,7 @@ public async Task CopyToAsync(HttpResponseMessage responseMessage, Stream destin else { // We've hit EOF. Pull in from the Http2Stream any trailers that were temporarily stored there. - CopyTrailersToResponseMessage(responseMessage); + MoveTrailersToResponseMessage(responseMessage); return; } } @@ -1061,36 +1057,24 @@ public async Task CopyToAsync(HttpResponseMessage responseMessage, Stream destin } } - private void CopyTrailersToResponseMessage(HttpResponseMessage responseMessage) + private void MoveTrailersToResponseMessage(HttpResponseMessage responseMessage) { - if (_trailers != null && _trailers.Count > 0) + if (_trailers != null) { - foreach (KeyValuePair trailer in _trailers) - { - responseMessage.TrailingHeaders.TryAddWithoutValidation(trailer.Key, trailer.Value); - } - _trailers.Clear(); + responseMessage.StoreReceivedTrailingHeaders(_trailers); } } private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) { + Debug.Assert(_requestBodyCancellationSource != null); + // Deal with [ActiveIssue("https://github.com/dotnet/runtime/issues/17492")] // Custom HttpContent classes do not get passed the cancellationToken. // So, inject the expected CancellationToken here, to ensure we can cancel the request body send if needed. - CancellationTokenSource? customCancellationSource = null; - if (!cancellationToken.CanBeCanceled) - { - cancellationToken = _requestBodyCancellationToken; - } - else if (cancellationToken != _requestBodyCancellationToken) - { - // User passed a custom CancellationToken. - // We can't tell if it includes our Token or not, so assume it doesn't. - customCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _requestBodyCancellationSource!.Token); - cancellationToken = customCancellationSource.Token; - } - + CancellationTokenRegistration linkedRegistration = cancellationToken.CanBeCanceled && cancellationToken != _requestBodyCancellationSource.Token ? + RegisterRequestBodyCancellation(cancellationToken) : + default; try { while (buffer.Length > 0) @@ -1107,12 +1091,12 @@ private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationT { if (_creditWaiter is null) { - _creditWaiter = new CancelableCreditWaiter(SyncObject, cancellationToken); + _creditWaiter = new CancelableCreditWaiter(SyncObject, _requestBodyCancellationSource.Token); } else { Debug.Assert(!_creditWaiter.IsPending); - _creditWaiter.ResetForAwait(cancellationToken); + _creditWaiter.ResetForAwait(_requestBodyCancellationSource.Token); } _creditWaiter.Amount = buffer.Length; } @@ -1128,12 +1112,12 @@ private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationT ReadOnlyMemory current; (current, buffer) = SplitBuffer(buffer, sendSize); - await _connection.SendStreamDataAsync(_streamId, current, cancellationToken).ConfigureAwait(false); + await _connection.SendStreamDataAsync(StreamId, current, _requestBodyCancellationSource.Token).ConfigureAwait(false); } } finally { - customCancellationSource?.Dispose(); + linkedRegistration.Dispose(); } } @@ -1159,6 +1143,9 @@ private void CloseResponseBody() _responseBuffer.Dispose(); } + private CancellationTokenRegistration RegisterRequestBodyCancellation(CancellationToken cancellationToken) => + cancellationToken.UnsafeRegister(s => ((CancellationTokenSource)s!).Cancel(), _requestBodyCancellationSource); + // This object is itself usable as a backing source for ValueTask. Since there's only ever one awaiter // for this object's state transitions at a time, we allow the object to be awaited directly. All functionality // associated with the implementation is just delegated to the ManualResetValueTaskSourceCore. @@ -1215,7 +1202,7 @@ private ValueTask WaitForDataAsync(CancellationToken cancellationToken) { // Wake up the wait. It will then immediately check whether cancellation was requested and throw if it was. thisRef._waitSource.SetException(ExceptionDispatchInfo.SetCurrentStackTrace( - CancellationHelper.CreateOperationCanceledException(null, _waitSourceCancellation.Token))); + CancellationHelper.CreateOperationCanceledException(null, thisRef._waitSourceCancellation.Token))); } }, this); @@ -1231,7 +1218,7 @@ private ValueTask WaitForDataAsync(CancellationToken cancellationToken) } public void Trace(string message, [CallerMemberName] string? memberName = null) => - _connection.Trace(_streamId, message, memberName); + _connection.Trace(StreamId, message, memberName); private enum ResponseProtocolState : byte { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs index f02edd7461720..a516450542eb7 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs @@ -2,6 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net.Http.Headers; @@ -117,11 +118,27 @@ internal static void IgnoreExceptions(ValueTask task) } /// Awaits a task, logging any resulting exceptions (which are otherwise ignored). - internal void LogExceptions(Task task) => - task.ContinueWith(t => + internal void LogExceptions(Task task) + { + if (task.IsCompleted) + { + if (task.IsFaulted) + { + LogFaulted(this, task); + } + } + else { - Exception? e = t.Exception?.InnerException; // Access Exception even if not tracing, to avoid TaskScheduler.UnobservedTaskException firing - if (NetEventSource.IsEnabled) Trace($"Exception from asynchronous processing: {e}"); - }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default); + task.ContinueWith((t, state) => LogFaulted((HttpConnectionBase)state!, t), this, + CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default); + } + + static void LogFaulted(HttpConnectionBase connection, Task task) + { + Debug.Assert(task.IsFaulted); + Exception? e = task.Exception!.InnerException; // Access Exception even if not tracing, to avoid TaskScheduler.UnobservedTaskException firing + if (NetEventSource.IsEnabled) connection.Trace($"Exception from asynchronous processing: {e}"); + } + } } } diff --git a/src/libraries/System.Net.Http/src/System/Threading/AsyncMutex.cs b/src/libraries/System.Net.Http/src/System/Threading/AsyncMutex.cs index 6c85c584619ae..1065304f074b2 100644 --- a/src/libraries/System.Net.Http/src/System/Threading/AsyncMutex.cs +++ b/src/libraries/System.Net.Http/src/System/Threading/AsyncMutex.cs @@ -42,9 +42,11 @@ internal sealed class AsyncMutex /// with an initial count of 0. /// private bool _lockedSemaphoreFull = true; - /// The head of the double-linked waiting queue. Waiters are dequeued from the head. - private Waiter? _waitersHead; - /// The tail of the double-linked waiting queue. Waiters are added at the tail. + /// The tail of the double-linked circular waiting queue. + /// + /// Waiters are added at the tail. + /// Items are dequeued from the head (tail.Prev). + /// private Waiter? _waitersTail; /// A pool of waiter objects that are ready to be reused. /// @@ -94,25 +96,25 @@ ValueTask Contended(CancellationToken cancellationToken) // Now that we're holding the lock, check to see whether the async lock is acquirable. if (!_lockedSemaphoreFull) { + // If we are able to acquire the lock, we're done. _lockedSemaphoreFull = true; return default; } + + // The lock couldn't be acquired. + // Add the waiter to the linked list of waiters. + if (_waitersTail is null) + { + w.Next = w.Prev = w; + } else { - // Add it to the linked list of waiters. - if (_waitersTail is null) - { - Debug.Assert(_waitersHead is null); - _waitersTail = _waitersHead = w; - } - else - { - Debug.Assert(_waitersHead != null); - w.Prev = _waitersTail; - _waitersTail.Next = w; - _waitersTail = w; - } + Debug.Assert(_waitersTail.Next != null && _waitersTail.Prev != null); + w.Next = _waitersTail; + w.Prev = _waitersTail.Prev; + w.Prev.Next = w.Next.Prev = w; } + _waitersTail = w; } // At this point the waiter was added to the list of waiters, so we want to @@ -136,14 +138,11 @@ static void OnCancellation(object? state) lock (m.SyncObj) { - bool inList = w.Next != null || w.Prev != null || m._waitersHead == w; + bool inList = w.Next != null; if (inList) { - // The waiter was still in the list. - Debug.Assert( - m._waitersHead == w || - (m._waitersTail == w && w.Prev != null && w.Next is null) || - (w.Next != null && w.Prev != null)); + // The waiter is in the list. + Debug.Assert(w.Prev != null); // The gate counter was decremented when this waiter was added. We need // to undo that. Since the waiter is still in the list, the lock must @@ -156,33 +155,19 @@ static void OnCancellation(object? state) // release it, they will appropriately update state. Interlocked.Increment(ref m._gate); - // Remove it from the list. - if (m._waitersHead == w && m._waitersTail == w) - { - // It's the only node in the list. - m._waitersHead = m._waitersTail = null; - } - else if (m._waitersTail == w) - { - // It's the most recently queued item in the list. - m._waitersTail = w.Prev; - Debug.Assert(m._waitersTail != null); - m._waitersTail.Next = null; - } - else if (m._waitersHead == w) + if (w.Next == w) { - // It's the next item to be removed from the list. - m._waitersHead = w.Next; - Debug.Assert(m._waitersHead != null); - m._waitersHead.Prev = null; + Debug.Assert(m._waitersTail == w); + m._waitersTail = null; } else { - // It's in the middle of the list. - Debug.Assert(w.Next != null); - Debug.Assert(w.Prev != null); - w.Next.Prev = w.Prev; + w.Next!.Prev = w.Prev; w.Prev.Next = w.Next; + if (m._waitersTail == w) + { + m._waitersTail = w.Next; + } } // Remove it from the list. @@ -217,34 +202,37 @@ public void Exit() void Contended() { Waiter? w; - lock (SyncObj) { Debug.Assert(_lockedSemaphoreFull); - // Wake up the next waiter in the list. - w = _waitersHead; - if (w != null) + w = _waitersTail; + if (w is null) { - // Remove the waiter. - _waitersHead = w.Next; - if (w.Next != null) + _lockedSemaphoreFull = false; + } + else + { + Debug.Assert(w.Next != null && w.Prev != null); + Debug.Assert(w.Next != w || w.Prev == w); + Debug.Assert(w.Prev != w || w.Next == w); + + if (w.Next == w) { - w.Next.Prev = null; + _waitersTail = null; } else { - Debug.Assert(_waitersTail == w); - _waitersTail = null; + w = w.Prev; // get the head + Debug.Assert(w.Next != null && w.Prev != null); + Debug.Assert(w.Next != w && w.Prev != w); + + w.Next.Prev = w.Prev; + w.Prev.Next = w.Next; } + w.Next = w.Prev = null; } - else - { - // There wasn't a waiter. Mark that the async lock is no longer full. - Debug.Assert(_waitersTail is null); - _lockedSemaphoreFull = false; - } } // Either there wasn't a waiter, or we got one and successfully removed it from the list, diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs index a297e28766d3a..544f188bd5770 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs @@ -221,7 +221,10 @@ public async Task GetContentAsync_NullResponseContent_ReturnsDefaultValue() { Assert.Same(string.Empty, await client.GetStringAsync(CreateFakeUri())); Assert.Same(Array.Empty(), await client.GetByteArrayAsync(CreateFakeUri())); - Assert.Same(Stream.Null, await client.GetStreamAsync(CreateFakeUri())); + + Stream s = await client.GetStreamAsync(CreateFakeUri()); + Assert.NotNull(s); + Assert.Equal(-1, s.ReadByte()); } } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpResponseMessageTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpResponseMessageTest.cs index fdeeeb065ca23..7c7fafee8d348 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpResponseMessageTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpResponseMessageTest.cs @@ -2,10 +2,7 @@ // 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.IO; -using System.Net.Http.Headers; -using System.Threading; using System.Threading.Tasks; using Xunit; @@ -22,7 +19,7 @@ public void Ctor_Default_CorrectDefaults() Assert.Equal(HttpStatusCode.OK, rm.StatusCode); Assert.Equal("OK", rm.ReasonPhrase); Assert.Equal(new Version(1, 1), rm.Version); - Assert.Null(rm.Content); + Assert.NotNull(rm.Content); Assert.Null(rm.RequestMessage); } } @@ -35,7 +32,7 @@ public void Ctor_SpecifiedValues_CorrectValues() Assert.Equal(HttpStatusCode.Accepted, rm.StatusCode); Assert.Equal("Accepted", rm.ReasonPhrase); Assert.Equal(new Version(1, 1), rm.Version); - Assert.Null(rm.Content); + Assert.NotNull(rm.Content); Assert.Null(rm.RequestMessage); } } @@ -232,8 +229,15 @@ public void Content_SetToNull_Accepted() { using (var rm = new HttpResponseMessage()) { + HttpContent c1 = rm.Content; + Assert.Same(c1, rm.Content); + rm.Content = null; - Assert.Null(rm.Content); + + HttpContent c2 = rm.Content; + Assert.Same(c2, rm.Content); + + Assert.NotSame(c1, c2); } } @@ -249,6 +253,35 @@ public void StatusCode_InvalidStatusCodeRange_ThrowsArgumentOutOfRangeException( } } + [Fact] + public async Task DefaultContent_ReadableNotWritable_Success() + { + var resp = new HttpResponseMessage(); + + HttpContent c = resp.Content; + Assert.NotNull(c); + Assert.Same(c, resp.Content); + Assert.NotSame(resp.Content, new HttpResponseMessage().Content); + + Assert.Equal(0, c.Headers.ContentLength); + + Task t = c.ReadAsStreamAsync(); + Assert.Equal(TaskStatus.RanToCompletion, t.Status); + + Stream s = await t; + Assert.NotNull(s); + + Assert.Equal(-1, s.ReadByte()); + Assert.Equal(0, s.Read(new byte[1], 0, 1)); + Assert.Equal(0, await s.ReadAsync(new byte[1], 0, 1)); + Assert.Equal(0, await s.ReadAsync(new Memory(new byte[1]))); + + Assert.Throws(() => s.WriteByte(0)); + Assert.Throws(() => s.Write(new byte[1], 0, 1)); + await Assert.ThrowsAsync(() => s.WriteAsync(new byte[1], 0, 1)); + await Assert.ThrowsAsync(async () => await s.WriteAsync(new ReadOnlyMemory(new byte[1]))); + } + [Fact] public void ToString_DefaultAndNonDefaultInstance_DumpAllFields() { diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs index 2e148dd757e33..8342fed20b694 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs @@ -192,7 +192,7 @@ public static class ClientOperations using HttpResponseMessage m = await ctx.SendAsync(req); ValidateStatusCode(m); - ValidateServerContent(await m.Content!.ReadAsStringAsync(), expectedLength); + ValidateServerContent(await m.Content.ReadAsStringAsync(), expectedLength); }), ("GET Partial", @@ -204,7 +204,7 @@ public static class ClientOperations ValidateStatusCode(m); - using (Stream s = await m.Content!.ReadAsStreamAsync()) + using (Stream s = await m.Content.ReadAsStreamAsync()) { s.ReadByte(); // read single byte from response and throw the rest away } @@ -221,7 +221,7 @@ public static class ClientOperations ValidateStatusCode(res); - await res.Content!.ReadAsStringAsync(); + await res.Content.ReadAsStringAsync(); bool isValidChecksum = ValidateServerChecksum(res.Headers, expectedChecksum); string failureDetails = isValidChecksum ? "server checksum matches client checksum" : "server checksum mismatch"; @@ -273,7 +273,7 @@ public static class ClientOperations using HttpResponseMessage m = await ctx.SendAsync(req); ValidateStatusCode(m); - ValidateContent(expectedResponse, await m.Content!.ReadAsStringAsync(), $"Uri: {uri}"); + ValidateContent(expectedResponse, await m.Content.ReadAsStringAsync(), $"Uri: {uri}"); }), ("GET Aborted", @@ -332,7 +332,7 @@ public static class ClientOperations ValidateStatusCode(m); string checksumMessage = ValidateServerChecksum(m.Headers, checksum) ? "server checksum matches client checksum" : "server checksum mismatch"; - ValidateContent(content, await m.Content!.ReadAsStringAsync(), checksumMessage); + ValidateContent(content, await m.Content.ReadAsStringAsync(), checksumMessage); }), ("POST Multipart Data", @@ -346,7 +346,7 @@ public static class ClientOperations ValidateStatusCode(m); string checksumMessage = ValidateServerChecksum(m.Headers, checksum) ? "server checksum matches client checksum" : "server checksum mismatch"; - ValidateContent(formData.expected, await m.Content!.ReadAsStringAsync(), checksumMessage); + ValidateContent(formData.expected, await m.Content.ReadAsStringAsync(), checksumMessage); }), ("POST Duplex", @@ -359,7 +359,7 @@ public static class ClientOperations using HttpResponseMessage m = await ctx.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); ValidateStatusCode(m); - string response = await m.Content!.ReadAsStringAsync(); + string response = await m.Content.ReadAsStringAsync(); string checksumMessage = ValidateServerChecksum(m.TrailingHeaders, checksum, required: false) ? "server checksum matches client checksum" : "server checksum mismatch"; ValidateContent(content, await m.Content.ReadAsStringAsync(), checksumMessage); @@ -376,7 +376,7 @@ public static class ClientOperations using HttpResponseMessage m = await ctx.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); ValidateStatusCode(m); - string response = await m.Content!.ReadAsStringAsync(); + string response = await m.Content.ReadAsStringAsync(); // trailing headers not supported for all servers, so do not require checksums bool isValidChecksum = ValidateServerChecksum(m.TrailingHeaders, checksum, required: false); @@ -416,7 +416,7 @@ public static class ClientOperations ValidateStatusCode(m); string checksumMessage = ValidateServerChecksum(m.Headers, checksum) ? "server checksum matches client checksum" : "server checksum mismatch"; - ValidateContent(content, await m.Content!.ReadAsStringAsync(), checksumMessage); + ValidateContent(content, await m.Content.ReadAsStringAsync(), checksumMessage); }), ("HEAD", @@ -428,7 +428,7 @@ public static class ClientOperations ValidateStatusCode(m); - if (m.Content!.Headers.ContentLength != expectedLength) + if (m.Content.Headers.ContentLength != expectedLength) { throw new Exception($"Expected {expectedLength}, got {m.Content.Headers.ContentLength}"); } @@ -446,7 +446,7 @@ public static class ClientOperations ValidateStatusCode(m); - string r = await m.Content!.ReadAsStringAsync(); + string r = await m.Content.ReadAsStringAsync(); if (r != "") throw new Exception($"Got unexpected response: {r}"); }), @@ -460,7 +460,7 @@ public static class ClientOperations ValidateStatusCode(m); - string r = await m.Content!.ReadAsStringAsync(); + string r = await m.Content.ReadAsStringAsync(); if (r != "") throw new Exception($"Got unexpected response: {r}"); }), @@ -472,7 +472,7 @@ public static class ClientOperations using HttpResponseMessage m = await ctx.SendAsync(req); ValidateStatusCode(m); - ValidateServerContent(await m.Content!.ReadAsStringAsync(), expectedLength); + ValidateServerContent(await m.Content.ReadAsStringAsync(), expectedLength); }), }; diff --git a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj index c14ef4c1dd220..b4c31ba80fd7b 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj @@ -70,6 +70,8 @@ Link="ProductionCode\Common\System\Threading\Tasks\TaskToApm.cs" /> + + + - ("name", () => response.StatusDescription = statusDescription); + AssertExtensions.Throws("value", () => response.StatusDescription = statusDescription); Assert.Equal("OK", response.StatusDescription); } } diff --git a/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj b/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj index adc2595232090..9567cbde45048 100644 --- a/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj +++ b/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj @@ -103,8 +103,6 @@ Link="Common\System\Collections\Generic\BidirectionalDictionary.cs" /> - - \ No newline at end of file + diff --git a/src/libraries/System.Net.Mail/src/System/Net/BufferedReadStream.cs b/src/libraries/System.Net.Mail/src/System/Net/BufferedReadStream.cs index 95f851e240dc6..c9f5c51e5c346 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/BufferedReadStream.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/BufferedReadStream.cs @@ -97,7 +97,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel private async Task ReadMoreAsync(int bytesAlreadyRead, byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - int returnValue = await base.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); + int returnValue = await base.ReadAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); return bytesAlreadyRead + returnValue; } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs index 44e48f7fc9e3e..91ffd95551706 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs @@ -75,7 +75,7 @@ internal void SetContentFromFile(string fileName, ContentType? contentType) throw new ArgumentNullException(nameof(fileName)); } - if (fileName == string.Empty) + if (fileName.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(fileName)), nameof(fileName)); } @@ -91,7 +91,7 @@ internal void SetContentFromFile(string fileName, string? mediaType) throw new ArgumentNullException(nameof(fileName)); } - if (fileName == string.Empty) + if (fileName.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(fileName)), nameof(fileName)); } @@ -154,7 +154,7 @@ internal void SetContentFromString(string content, Encoding? encoding, string? m _part.Stream.Close(); } - if (mediaType == null || mediaType == string.Empty) + if (string.IsNullOrEmpty(mediaType)) { mediaType = MediaTypeNames.Text.Plain; } @@ -340,7 +340,7 @@ public Attachment(string fileName) : base(fileName) public Attachment(string fileName, ContentType contentType) : base(fileName, contentType) { - if (contentType.Name == null || contentType.Name == string.Empty) + if (string.IsNullOrEmpty(contentType.Name)) { Name = Path.GetFileName(fileName); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs index 9519b3f80d87c..76d97dd95f4e5 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs @@ -124,7 +124,7 @@ private static bool TryParse(string address, string? displayName, Encoding? disp { throw new ArgumentNullException(nameof(address)); } - if (address == string.Empty) + if (address.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(address)), nameof(address)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs index 5b1b687e30179..bc63f116fcea9 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs @@ -23,7 +23,7 @@ public void Add(string addresses) { throw new ArgumentNullException(nameof(addresses)); } - if (addresses == string.Empty) + if (addresses.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(addresses)), nameof(addresses)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs index 83eddcd9f755f..4bb5e9e8663d2 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs @@ -44,10 +44,10 @@ public MailMessage(string from, string to) if (to == null) throw new ArgumentNullException(nameof(to)); - if (from == string.Empty) + if (from.Length == 0) throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(from)), nameof(from)); - if (to == string.Empty) + if (to.Length == 0) throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(to)), nameof(to)); _message = new Message(from, to); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs index 6c912e3239c25..ee4618cdd83c3 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs @@ -51,10 +51,10 @@ internal Message(string from, string to) : this() if (to == null) throw new ArgumentNullException(nameof(to)); - if (from == string.Empty) + if (from.Length == 0) throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(from)), nameof(from)); - if (to == string.Empty) + if (to.Length == 0) throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(to)), nameof(to)); _from = new MailAddress(from); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs index 834b5ba0b8081..0def5723b3064 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs @@ -187,7 +187,7 @@ private void Initialize() throw new ArgumentNullException(nameof(value)); } - if (value == string.Empty) + if (value.Length == 0) { throw new ArgumentException(SR.net_emptystringset, nameof(value)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs index be078ae7edcdf..891d17ef06882 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs @@ -83,7 +83,7 @@ public string DispositionType { throw new ArgumentNullException(nameof(value)); } - if (value == string.Empty) + if (value.Length == 0) { throw new ArgumentException(SR.net_emptystringset, nameof(value)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs index d3a183fb3b31f..7394cfdd20c5e 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs @@ -50,7 +50,7 @@ public ContentType(string contentType) { throw new ArgumentNullException(nameof(contentType)); } - if (contentType == string.Empty) + if (contentType.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(contentType)), nameof(contentType)); } @@ -65,7 +65,7 @@ public ContentType(string contentType) get { return Parameters["boundary"]; } set { - if (value == null || value == string.Empty) + if (string.IsNullOrEmpty(value)) { Parameters.Remove("boundary"); } @@ -81,7 +81,7 @@ public ContentType(string contentType) get { return Parameters["charset"]; } set { - if (value == null || value == string.Empty) + if (string.IsNullOrEmpty(value)) { Parameters.Remove("charset"); } @@ -105,7 +105,7 @@ public string MediaType throw new ArgumentNullException(nameof(value)); } - if (value == string.Empty) + if (value.Length == 0) { throw new ArgumentException(SR.net_emptystringset, nameof(value)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs index 6c4b282717502..1b468f725477f 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs @@ -22,16 +22,16 @@ internal HeaderCollection() : base(StringComparer.OrdinalIgnoreCase) { } -#pragma warning disable CS8610 // Nullability of reference types in type of parameter doesn't match overridden member. +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Remove(string name) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (name == null) { throw new ArgumentNullException(nameof(name)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); } @@ -51,16 +51,16 @@ public override void Remove(string name) } -#pragma warning disable CS8610 // Nullability of reference types in type of parameter doesn't match overridden member. +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override string? Get(string name) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (name == null) { throw new ArgumentNullException(nameof(name)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); } @@ -78,16 +78,16 @@ public override void Remove(string name) return base.Get(name); } -#pragma warning disable CS8610 // Nullability of reference types in type of parameter doesn't match overridden member. +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override string[]? GetValues(string name) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (name == null) { throw new ArgumentNullException(nameof(name)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); } @@ -124,9 +124,9 @@ internal void InternalAdd(string name, string value) } } -#pragma warning disable CS8610 // Nullability of reference types in type of parameter doesn't match overridden member. +#pragma warning disable CS8765 // Nullability of parameters 'name' and 'value' don't match overridden member public override void Set(string name, string value) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (name == null) { @@ -138,12 +138,12 @@ public override void Set(string name, string value) throw new ArgumentNullException(nameof(value)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); } - if (value == string.Empty) + if (value.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(value)), nameof(value)); } @@ -175,9 +175,9 @@ public override void Set(string name, string value) } -#pragma warning disable CS8610 // Nullability of reference types in type of parameter doesn't match overridden member. +#pragma warning disable CS8765 // Nullability of parameters 'name' and 'value' don't match overridden member public override void Add(string name, string value) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (name == null) { @@ -187,11 +187,11 @@ public override void Add(string name, string value) { throw new ArgumentNullException(nameof(value)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); } - if (value == string.Empty) + if (value.Length == 0) { throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(value)), nameof(value)); } diff --git a/src/libraries/System.Net.Mail/tests/Functional/AlternateViewCollectionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/AlternateViewCollectionTest.cs index 6540a168b5b92..ed20522d401c0 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/AlternateViewCollectionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/AlternateViewCollectionTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// AlternateViewCollectionTest.cs - NUnit Test Cases for System.Net.MailAddress.AlternateViewCollection +// AlternateViewCollectionTest.cs - Unit Test Cases for System.Net.MailAddress.AlternateViewCollection // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/AlternateViewTest.cs b/src/libraries/System.Net.Mail/tests/Functional/AlternateViewTest.cs index 302dd3e156b82..59320cbb1d54e 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/AlternateViewTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/AlternateViewTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// AlternateViewTest.cs - NUnit Test Cases for System.Net.MailAddress.AlternateView +// AlternateViewTest.cs - Unit Test Cases for System.Net.MailAddress.AlternateView // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/AttachmentCollectionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/AttachmentCollectionTest.cs index 2237a9838d30c..68e4c1ef78f1c 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/AttachmentCollectionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/AttachmentCollectionTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// AttachmentCollectionTest.cs - NUnit Test Cases for System.Net.MailAddress.AttachmentCollection +// AttachmentCollectionTest.cs - Unit Test Cases for System.Net.MailAddress.AttachmentCollection // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/AttachmentTest.cs b/src/libraries/System.Net.Mail/tests/Functional/AttachmentTest.cs index a3264ea162a2d..9a0b9f41e966a 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/AttachmentTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/AttachmentTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// AttachmentTest.cs - NUnit Test Cases for System.Net.MailAddress.Attachment +// AttachmentTest.cs - Unit Test Cases for System.Net.MailAddress.Attachment // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceCollectionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceCollectionTest.cs index 8bed530fbbc9d..68ef77002980e 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceCollectionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceCollectionTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// LinkedResourceCollectionTest.cs - NUnit Test Cases for System.Net.MailAddress.LinkedResourceCollection +// LinkedResourceCollectionTest.cs - Unit Test Cases for System.Net.MailAddress.LinkedResourceCollection // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceTest.cs b/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceTest.cs index c64a92ed08efd..00b6a62f64d0b 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/LinkedResourceTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// LinkedResourceTest.cs - NUnit Test Cases for System.Net.MailAddress.LinkedResource +// LinkedResourceTest.cs - Unit Test Cases for System.Net.MailAddress.LinkedResource // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/MailAddressCollectionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/MailAddressCollectionTest.cs index 8d1a2156b7ac4..5aa41b4a26b73 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/MailAddressCollectionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/MailAddressCollectionTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// MailAddressCollectionTest.cs - NUnit Test Cases for System.Net.MailAddress.MailAddressCollection +// MailAddressCollectionTest.cs - Unit Test Cases for System.Net.MailAddress.MailAddressCollection // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/MailMessageTest.cs b/src/libraries/System.Net.Mail/tests/Functional/MailMessageTest.cs index f8be941b6c750..bdd41aa31cb60 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/MailMessageTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/MailMessageTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// MailMessageTest.cs - NUnit Test Cases for System.Net.MailAddress.MailMessage +// MailMessageTest.cs - Unit Test Cases for System.Net.MailAddress.MailMessage // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs index 7e1c86d2fadef..ddcb811b8b5c6 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// SmtpClientTest.cs - NUnit Test Cases for System.Net.Mail.SmtpClient +// SmtpClientTest.cs - Unit Test Cases for System.Net.Mail.SmtpClient // // Authors: // John Luke (john.luke@gmail.com) diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs index 2846746446e71..443a32ebd4d66 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. // -// SmtpExceptionTest.cs - NUnit Test Cases for System.Net.Mail.SmtpException +// SmtpExceptionTest.cs - Unit Test Cases for System.Net.Mail.SmtpException // // Authors: // Gert Driesen (drieseng@users.sourceforge.net) diff --git a/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj b/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj index 5a721973b144b..d4da9df33459e 100644 --- a/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj +++ b/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj @@ -142,8 +142,6 @@ Link="Common\System\Collections\Generic\BidirectionalDictionary.cs" /> - - \ No newline at end of file + diff --git a/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj b/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj index 7d5e1cc07d29c..498f4e8fce267 100644 --- a/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj +++ b/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj @@ -10,8 +10,6 @@ - - GetUnicastAddressesAsync() { // Wait for the address table to stabilize. - var tcs = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(s => ((TaskCompletionSource)s).TrySetResult(true), tcs)) { await tcs.Task.ConfigureAwait(false); diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs index 0d7af8cf3703f..9b5c56ed8ba69 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs @@ -278,7 +278,7 @@ private async Task SendIcmpEchoRequestOverRawSocketAsync(IPAddress ad } } - private Process GetPingProcess(IPAddress address, byte[] buffer, PingOptions? options) + private Process GetPingProcess(IPAddress address, byte[] buffer, int timeout, PingOptions? options) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string? pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; @@ -293,7 +293,7 @@ private Process GetPingProcess(IPAddress address, byte[] buffer, PingOptions? op fragmentOption = options.DontFragment ? UnixCommandLinePing.PingFragmentOptions.Do : UnixCommandLinePing.PingFragmentOptions.Dont; } - string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, address.ToString(), isIpv4, options?.Ttl ?? 0, fragmentOption); + string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, timeout, address.ToString(), isIpv4, options?.Ttl ?? 0, fragmentOption); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; @@ -303,7 +303,7 @@ private Process GetPingProcess(IPAddress address, byte[] buffer, PingOptions? op private PingReply SendWithPingUtility(IPAddress address, byte[] buffer, int timeout, PingOptions? options) { - using (Process p = GetPingProcess(address, buffer, options)) + using (Process p = GetPingProcess(address, buffer, timeout, options)) { p.Start(); if (!p.WaitForExit(timeout) || p.ExitCode == 1 || p.ExitCode == 2) @@ -326,7 +326,7 @@ private PingReply SendWithPingUtility(IPAddress address, byte[] buffer, int time private async Task SendWithPingUtilityAsync(IPAddress address, byte[] buffer, int timeout, PingOptions? options) { - using (Process p = GetPingProcess(address, buffer, options)) + using (Process p = GetPingProcess(address, buffer, timeout, options)) { var processCompletion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); p.EnableRaisingEvents = true; diff --git a/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs b/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs index 7711aff9cb87c..899a2eaa17945 100644 --- a/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs +++ b/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs @@ -19,6 +19,28 @@ public class UnixPingUtilityTests { private const int IcmpHeaderLengthInBytes = 8; + [Theory] + [InlineData(0)] + [InlineData(100)] + [InlineData(1000)] + [InlineData(1500)] + [PlatformSpecific(TestPlatforms.AnyUnix)] + public static void TimeoutIsRespected(int timeout) + { + Process p = ConstructPingProcess(IPAddress.Parse(TestSettings.UnreachableAddress), 50, timeout); + //suppress Ping output to console/terminal stdout during test execution + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; + + Stopwatch stopWatch = Stopwatch.StartNew(); + + p.Start(); + p.WaitForExit(); + + //ensure that the process takes longer than or equal to 'timeout' + Assert.True(stopWatch.ElapsedMilliseconds >= timeout); + } + [Theory] [InlineData(0)] [InlineData(1)] @@ -27,36 +49,28 @@ public class UnixPingUtilityTests [PlatformSpecific(TestPlatforms.AnyUnix)] // Tests un-priviledged Ping support on Unix public static async Task PacketSizeIsRespected(int payloadSize) { - IPAddress localAddress = await TestSettings.GetLocalIPAddressAsync(); - bool ipv4 = localAddress.AddressFamily == AddressFamily.InterNetwork; - string arguments = UnixCommandLinePing.ConstructCommandLine(payloadSize, localAddress.ToString(), ipv4); - string utilityPath = (localAddress.AddressFamily == AddressFamily.InterNetwork) - ? UnixCommandLinePing.Ping4UtilityPath - : UnixCommandLinePing.Ping6UtilityPath; - - var p = new Process(); - p.StartInfo.FileName = utilityPath; - p.StartInfo.Arguments = arguments; - p.StartInfo.UseShellExecute = false; + var stdOutLines = new List(); + var stdErrLines = new List(); + Process p = ConstructPingProcess(await TestSettings.GetLocalIPAddressAsync(), payloadSize, 1000); p.StartInfo.RedirectStandardOutput = true; - var stdOutLines = new List(); - p.OutputDataReceived += new DataReceivedEventHandler( - delegate (object sendingProcess, DataReceivedEventArgs outputLine) { stdOutLines.Add(outputLine.Data); }); + p.OutputDataReceived += delegate (object sendingProcess, DataReceivedEventArgs outputLine) + { + stdOutLines.Add(outputLine.Data); + }; p.StartInfo.RedirectStandardError = true; - var stdErrLines = new List(); - p.ErrorDataReceived += new DataReceivedEventHandler( - delegate (object sendingProcess, DataReceivedEventArgs errorLine) { stdErrLines.Add(errorLine.Data); }); + p.ErrorDataReceived += delegate (object sendingProcess, DataReceivedEventArgs errorLine) + { + stdErrLines.Add(errorLine.Data); + }; p.Start(); p.BeginOutputReadLine(); p.BeginErrorReadLine(); // There are multiple issues with ping6 in macOS 10.12 (Sierra), see https://github.com/dotnet/runtime/issues/24682. - bool isPing6OnMacSierra = utilityPath.Equals(UnixCommandLinePing.Ping6UtilityPath) && - RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && - !PlatformDetection.IsMacOsHighSierraOrHigher; + bool isPing6OnMacSierra = IsPing6OnMacSierra(p.StartInfo); string pingOutput; if (!p.WaitForExit(TestSettings.PingTimeout)) @@ -68,7 +82,7 @@ public static async Task PacketSizeIsRespected(int payloadSize) pingOutput = string.Join("\n", stdOutLines); string stdErr = string.Join("\n", stdErrLines); throw new Exception( - $"[{utilityPath} {arguments}] process did not exit in {TestSettings.PingTimeout} ms.\nStdOut:[{pingOutput}]\nStdErr:[{stdErr}]"); + $"[{p.StartInfo.FileName} {p.StartInfo.Arguments}] process did not exit in {TestSettings.PingTimeout} ms.\nStdOut:[{pingOutput}]\nStdErr:[{stdErr}]"); } // Ensure standard output and error are flushed @@ -84,7 +98,7 @@ public static async Task PacketSizeIsRespected(int payloadSize) string stdErr = string.Join("\n", stdErrLines); throw new Exception( - $"[{utilityPath} {arguments}] process exit code is {exitCode}.\nStdOut:[{pingOutput}]\nStdErr:[{stdErr}]"); + $"[{p.StartInfo.FileName} {p.StartInfo.Arguments}] process exit code is {exitCode}.\nStdOut:[{pingOutput}]\nStdErr:[{stdErr}]"); } try @@ -106,10 +120,33 @@ public static async Task PacketSizeIsRespected(int payloadSize) { string stdErr = string.Join("\n", stdErrLines); throw new Exception( - $"Parse error for [{utilityPath} {arguments}] process exit code is {exitCode}.\nStdOut:[{pingOutput}]\nStdErr:[{stdErr}]", e); + $"Parse error for [{p.StartInfo.FileName} {p.StartInfo.Arguments}] process exit code is {exitCode}.\nStdOut:[{pingOutput}]\nStdErr:[{stdErr}]", e); } } + private static bool IsPing6OnMacSierra(ProcessStartInfo startInfo) + { + return startInfo.FileName.Equals(UnixCommandLinePing.Ping6UtilityPath) && + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && + !PlatformDetection.IsMacOsHighSierraOrHigher; + } + + private static Process ConstructPingProcess(IPAddress localAddress, int payloadSize, int timeout) + { + bool ipv4 = localAddress.AddressFamily == AddressFamily.InterNetwork; + string arguments = UnixCommandLinePing.ConstructCommandLine(payloadSize, timeout, localAddress.ToString(), ipv4); + string utilityPath = (localAddress.AddressFamily == AddressFamily.InterNetwork) + ? UnixCommandLinePing.Ping4UtilityPath + : UnixCommandLinePing.Ping6UtilityPath; + + var p = new Process(); + p.StartInfo.FileName = utilityPath; + p.StartInfo.Arguments = arguments; + p.StartInfo.UseShellExecute = false; + + return p; + } + private static int ParseReturnedPacketSize(string pingOutput) { int indexOfBytesFrom = pingOutput.IndexOf("bytes from"); diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs b/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs index 75f68bb98086e..af1f75ebc9d49 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs @@ -118,7 +118,7 @@ public CookieContainer(int capacity) { if (capacity <= 0) { - throw new ArgumentException(SR.net_toosmall, "Capacity"); + throw new ArgumentException(SR.net_toosmall, nameof(capacity)); } m_maxCookies = capacity; } @@ -132,7 +132,7 @@ public CookieContainer(int capacity, int perDomainCapacity, int maxCookieSize) : m_maxCookiesPerDomain = perDomainCapacity; if (maxCookieSize <= 0) { - throw new ArgumentException(SR.net_toosmall, "MaxCookieSize"); + throw new ArgumentException(SR.net_toosmall, nameof(maxCookieSize)); } m_maxCookieSize = maxCookieSize; } @@ -230,7 +230,7 @@ public void Add(Cookie cookie) { throw new ArgumentException( SR.Format(SR.net_emptystringcall, nameof(cookie) + "." + nameof(cookie.Domain)), - nameof(cookie) + "." + nameof(cookie.Domain)); + nameof(cookie)); } Uri? uri; diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs index d3ce1f523d0ec..7bd84309abf0c 100644 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs +++ b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs @@ -486,7 +486,7 @@ public void Ctor_Capacity_Success() [Fact] public void Ctor_Capacity_Invalid() { - AssertExtensions.Throws("Capacity", () => new CookieContainer(0)); // Capacity <= 0 + AssertExtensions.Throws("capacity", () => new CookieContainer(0)); // Capacity <= 0 } [Fact] @@ -595,7 +595,7 @@ public void Add_Cookie_Invalid() { CookieContainer cc = new CookieContainer(); Assert.Throws(() => cc.Add((Cookie)null)); // Null cookie - AssertExtensions.Throws("cookie.Domain", () => cc.Add(new Cookie("name", "value", "", ""))); // Empty domain + AssertExtensions.Throws("cookie", () => cc.Add(new Cookie("name", "value", "", ""))); // Empty domain cc.MaxCookieSize = 1; Assert.Throws(() => cc.Add(new Cookie("name", "long-text", "", "contoso.com"))); // Value.Length > MaxCookieSize @@ -625,11 +625,11 @@ public void Capacity_ShrinkNoneExpired_RemovesAll() [Fact] public void Ctor_CapacityPerDomainCapacityMaxCookieSize_Invalid() { - AssertExtensions.Throws("Capacity", () => new CookieContainer(0, 10, 5)); // Capacity <= 0 + AssertExtensions.Throws("capacity", () => new CookieContainer(0, 10, 5)); // Capacity <= 0 Assert.Throws(() => new CookieContainer(5, 0, 5)); // Per domain capacity <= 0 Assert.Throws(() => new CookieContainer(5, 10, 5)); // Per domain capacity > Capacity - AssertExtensions.Throws("MaxCookieSize", () => new CookieContainer(15, 10, 0)); // Max cookie size <= 0 + AssertExtensions.Throws("maxCookieSize", () => new CookieContainer(15, 10, 0)); // Max cookie size <= 0 } [Fact] diff --git a/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj b/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj index 0b81d0749fb41..8b748818b3a0e 100644 --- a/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj +++ b/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj @@ -49,8 +49,6 @@ Link="Common\System\Net\InternalException.cs" /> - 0) { - // Copy all the new queues to the real queues. Since only this thread modifies the real queues, it doesn't have to lock it. - if (s_newQueues.Count > 0) + lock (s_newQueues) { - lock (s_newQueues) + for (LinkedListNode? node = s_newQueues.First; node != null; node = s_newQueues.First) { - for (LinkedListNode? node = s_newQueues.First; node != null; node = s_newQueues.First) - { - s_newQueues.Remove(node); - s_queues.AddLast(node); - } + s_newQueues.Remove(node); + s_queues.AddLast(node); } } + } - int now = Environment.TickCount; - int nextTick = 0; - bool haveNextTick = false; - for (LinkedListNode? node = s_queues.First; node != null; /* node = node.Next must be done in the body */) + int now = Environment.TickCount; + int nextTick = 0; + bool haveNextTick = false; + for (LinkedListNode? node = s_queues.First; node != null; /* node = node.Next must be done in the body */) + { + TimerQueue? queue = (TimerQueue?)node.Value.Target; + if (queue == null) { - TimerQueue? queue = (TimerQueue?)node.Value.Target; - if (queue == null) - { - LinkedListNode? next = node.Next; - s_queues.Remove(node); - node = next; - continue; - } - - // Fire() will always return values that should be interpreted as later than 'now' (that is, even if 'now' is - // returned, it is 0x100000000 milliseconds in the future). There's also a chance that Fire() will return a value - // intended as > 0x100000000 milliseconds from 'now'. Either case will just cause an extra scan through the timers. - int nextTickInstance; - if (queue.Fire(out nextTickInstance) && (!haveNextTick || IsTickBetween(now, nextTick, nextTickInstance))) - { - nextTick = nextTickInstance; - haveNextTick = true; - } + LinkedListNode? next = node.Next; + s_queues.Remove(node); + node = next; + continue; + } - node = node.Next; + // Fire() will always return values that should be interpreted as later than 'now' (that is, even if 'now' is + // returned, it is 0x100000000 milliseconds in the future). There's also a chance that Fire() will return a value + // intended as > 0x100000000 milliseconds from 'now'. Either case will just cause an extra scan through the timers. + int nextTickInstance; + if (queue.Fire(out nextTickInstance) && (!haveNextTick || IsTickBetween(now, nextTick, nextTickInstance))) + { + nextTick = nextTickInstance; + haveNextTick = true; } - // Figure out how long to wait, taking into account how long the loop took. - // Add 15 ms to compensate for poor TickCount resolution (want to guarantee a firing). - int newNow = Environment.TickCount; - int waitDuration = haveNextTick ? - (int)(IsTickBetween(now, nextTick, newNow) ? - Math.Min(unchecked((uint)(nextTick - newNow)), (uint)(int.MaxValue - TickCountResolution)) + TickCountResolution : - 0) : - ThreadIdleTimeoutMilliseconds; + node = node.Next; + } - if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Waiting for {waitDuration}ms"); + // Figure out how long to wait, taking into account how long the loop took. + // Add 15 ms to compensate for poor TickCount resolution (want to guarantee a firing). + int newNow = Environment.TickCount; + int waitDuration = haveNextTick ? + (int)(IsTickBetween(now, nextTick, newNow) ? + Math.Min(unchecked((uint)(nextTick - newNow)), (uint)(int.MaxValue - TickCountResolution)) + TickCountResolution : + 0) : + ThreadIdleTimeoutMilliseconds; - int waitResult = WaitHandle.WaitAny(s_threadEvents, waitDuration, false); + if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Waiting for {waitDuration}ms"); - // 0 is s_ThreadShutdownEvent - die. - if (waitResult == 0) - { - if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Awoke, cause: Shutdown"); - running = false; - break; - } + int waitResult = WaitHandle.WaitAny(s_threadEvents, waitDuration, false); + + // 0 is s_ThreadShutdownEvent - die. + if (waitResult == 0) + { + if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Awoke, cause: Shutdown"); + running = false; + break; + } - if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Awoke, cause {(waitResult == WaitHandle.WaitTimeout ? "Timeout" : "Prod")}"); + if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Awoke, cause {(waitResult == WaitHandle.WaitTimeout ? "Timeout" : "Prod")}"); - // If we timed out with nothing to do, shut down. - if (waitResult == WaitHandle.WaitTimeout && !haveNextTick) + // If we timed out with nothing to do, shut down. + if (waitResult == WaitHandle.WaitTimeout && !haveNextTick) + { + Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Idle, (int)TimerThreadState.Running); + // There could have been one more prod between the wait and the exchange. Check, and abort if necessary. + if (s_threadReadyEvent.WaitOne(0, false)) { - Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Idle, (int)TimerThreadState.Running); - // There could have been one more prod between the wait and the exchange. Check, and abort if necessary. - if (s_threadReadyEvent.WaitOne(0, false)) + if (Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Running, (int)TimerThreadState.Idle) == + (int)TimerThreadState.Idle) { - if (Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Running, (int)TimerThreadState.Idle) == - (int)TimerThreadState.Idle) - { - continue; - } + continue; } - - running = false; - break; } + + running = false; + break; } } - catch (Exception exception) - { - if (ExceptionCheck.IsFatal(exception)) - throw; + } + catch (Exception exception) + { + if (ExceptionCheck.IsFatal(exception)) + throw; - if (NetEventSource.IsEnabled) NetEventSource.Error(null, exception); + if (NetEventSource.IsEnabled) NetEventSource.Error(null, exception); - // The only options are to continue processing and likely enter an error-loop, - // shut down timers for this AppDomain, or shut down the AppDomain. Go with shutting - // down the AppDomain in debug, and going into a loop in retail, but try to make the - // loop somewhat slow. Note that in retail, this can only be triggered by OutOfMemory or StackOverflow, - // or an exception thrown within TimerThread - the rest are caught in Fire(). + // The only options are to continue processing and likely enter an error-loop, + // shut down timers for this AppDomain, or shut down the AppDomain. Go with shutting + // down the AppDomain in debug, and going into a loop in retail, but try to make the + // loop somewhat slow. Note that in retail, this can only be triggered by OutOfMemory or StackOverflow, + // or an exception thrown within TimerThread - the rest are caught in Fire(). #if !DEBUG - Thread.Sleep(1000); + Thread.Sleep(1000); #else - throw; + throw; #endif - } } } - - if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Stop"); -#if DEBUG } -#endif + + if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Stop"); } /// diff --git a/src/libraries/System.Net.Security/ref/System.Net.Security.cs b/src/libraries/System.Net.Security/ref/System.Net.Security.cs index c022960def9c7..d657bb1fd59d7 100644 --- a/src/libraries/System.Net.Security/ref/System.Net.Security.cs +++ b/src/libraries/System.Net.Security/ref/System.Net.Security.cs @@ -91,9 +91,13 @@ public partial class NegotiateStream : System.Net.Security.AuthenticatedStream public override void Flush() { } public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; } public override int Read(byte[] buffer, int offset, int count) { throw null; } + public override System.Threading.Tasks.Task ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; } + public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default) { throw null; } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; } public override void SetLength(long value) { } public override void Write(byte[] buffer, int offset, int count) { } + public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; } + public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default) { throw null; } } public enum ProtectionLevel { @@ -182,6 +186,7 @@ public partial class SslStream : System.Net.Security.AuthenticatedStream public virtual System.Security.Authentication.SslProtocols SslProtocol { get { throw null; } } public System.Net.TransportContext TransportContext { get { throw null; } } public override int WriteTimeout { get { throw null; } set { } } + public void AuthenticateAsClient(System.Net.Security.SslClientAuthenticationOptions sslClientAuthenticationOptions) { } public virtual void AuthenticateAsClient(string targetHost) { } public virtual void AuthenticateAsClient(string targetHost, System.Security.Cryptography.X509Certificates.X509CertificateCollection? clientCertificates, bool checkCertificateRevocation) { } public virtual void AuthenticateAsClient(string targetHost, System.Security.Cryptography.X509Certificates.X509CertificateCollection? clientCertificates, System.Security.Authentication.SslProtocols enabledSslProtocols, bool checkCertificateRevocation) { } @@ -189,6 +194,7 @@ public partial class SslStream : System.Net.Security.AuthenticatedStream public virtual System.Threading.Tasks.Task AuthenticateAsClientAsync(string targetHost) { throw null; } public virtual System.Threading.Tasks.Task AuthenticateAsClientAsync(string targetHost, System.Security.Cryptography.X509Certificates.X509CertificateCollection? clientCertificates, bool checkCertificateRevocation) { throw null; } public virtual System.Threading.Tasks.Task AuthenticateAsClientAsync(string targetHost, System.Security.Cryptography.X509Certificates.X509CertificateCollection? clientCertificates, System.Security.Authentication.SslProtocols enabledSslProtocols, bool checkCertificateRevocation) { throw null; } + public void AuthenticateAsServer(System.Net.Security.SslServerAuthenticationOptions sslServerAuthenticationOptions) { } public virtual void AuthenticateAsServer(System.Security.Cryptography.X509Certificates.X509Certificate serverCertificate) { } public virtual void AuthenticateAsServer(System.Security.Cryptography.X509Certificates.X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation) { } public virtual void AuthenticateAsServer(System.Security.Cryptography.X509Certificates.X509Certificate serverCertificate, bool clientCertificateRequired, System.Security.Authentication.SslProtocols enabledSslProtocols, bool checkCertificateRevocation) { } @@ -210,6 +216,7 @@ public partial class SslStream : System.Net.Security.AuthenticatedStream public virtual void EndAuthenticateAsServer(System.IAsyncResult asyncResult) { } public override int EndRead(System.IAsyncResult asyncResult) { throw null; } public override void EndWrite(System.IAsyncResult asyncResult) { } + ~SslStream() { } public override void Flush() { } public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; } public override int Read(byte[] buffer, int offset, int count) { throw null; } diff --git a/src/libraries/System.Net.Security/src/Resources/Strings.resx b/src/libraries/System.Net.Security/src/Resources/Strings.resx index 7270ea80faefd..8af05ebe134c8 100644 --- a/src/libraries/System.Net.Security/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Security/src/Resources/Strings.resx @@ -212,6 +212,9 @@ Authentication failed because the remote party has closed the transport stream. + + Authentication failed because the remote party sent a TLS alert: '{0}'. + Authentication failed on the remote side (the stream might still be available for additional authentication attempts). diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 868faddb5727a..73d613dfa729d 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -12,43 +12,37 @@ - - + + + + + + + - - - - - - - + - - - - - - /// The class is a simple wrapper on top of a read stream. It will read the exact number of bytes requested. - /// It will throw if EOF is reached before the expected number of bytes is returned. - /// - internal static class FixedSizeReader - { - /// - /// Returns 0 on legitimate EOF or if 0 bytes were requested, otherwise reads as directed or throws. - /// Returns count on success. - /// - public static int ReadPacket(Stream transport, byte[] buffer, int offset, int count) - { - int remainingCount = count; - do - { - int bytes = transport.Read(buffer, offset, remainingCount); - if (bytes == 0) - { - if (remainingCount != count) - { - throw new IOException(SR.net_io_eof); - } - - return 0; - } - - remainingCount -= bytes; - offset += bytes; - } while (remainingCount > 0); - - Debug.Assert(remainingCount == 0); - return count; - } - - /// - /// Completes "request" with 0 if 0 bytes was requested or legitimate EOF received. - /// Otherwise, reads as directed or completes "request" with an Exception. - /// - public static async Task ReadPacketAsync(Stream transport, AsyncProtocolRequest request) - { - try - { - int remainingCount = request.Count, offset = request.Offset; - do - { - int bytes = await transport.ReadAsync(new Memory(request.Buffer, offset, remainingCount), request.CancellationToken).ConfigureAwait(false); - if (bytes == 0) - { - if (remainingCount != request.Count) - { - throw new IOException(SR.net_io_eof); - } - request.CompleteRequest(0); - return; - } - - offset += bytes; - remainingCount -= bytes; - } while (remainingCount > 0); - - Debug.Assert(remainingCount == 0); - request.CompleteRequest(request.Count); - } - catch (Exception e) - { - request.CompleteUserWithError(e); - } - } - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/NTAuthentication.cs b/src/libraries/System.Net.Security/src/System/Net/NTAuthentication.cs index af931677016e7..0f4f7afef338d 100644 --- a/src/libraries/System.Net.Security/src/System/Net/NTAuthentication.cs +++ b/src/libraries/System.Net.Security/src/System/Net/NTAuthentication.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Net.Security; using System.Security.Authentication.ExtendedProtection; @@ -114,13 +115,11 @@ private static void InitializeCallback(object state) context.ThisPtr.Initialize(context.IsServer, context.Package, context.Credential, context.Spn, context.RequestedContextFlags, context.ChannelBinding); } - internal int Encrypt(byte[] buffer, int offset, int count, ref byte[]? output, uint sequenceNumber) + internal int Encrypt(ReadOnlySpan buffer, [NotNull] ref byte[]? output, uint sequenceNumber) { return NegotiateStreamPal.Encrypt( _securityContext!, buffer, - offset, - count, IsConfidentialityFlag, IsNTLM, ref output, diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/AuthenticatedStream.cs b/src/libraries/System.Net.Security/src/System/Net/Security/AuthenticatedStream.cs index c8c79449d04ec..9c8eac2d1969d 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/AuthenticatedStream.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/AuthenticatedStream.cs @@ -47,31 +47,24 @@ protected Stream InnerStream protected override void Dispose(bool disposing) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) + try { -#endif - try + if (disposing) { - if (disposing) + if (_leaveStreamOpen) { - if (_leaveStreamOpen) - { - _innerStream.Flush(); - } - else - { - _innerStream.Dispose(); - } + _innerStream.Flush(); + } + else + { + _innerStream.Dispose(); } } - finally - { - base.Dispose(disposing); - } -#if DEBUG } -#endif + finally + { + base.Dispose(disposing); + } } public override ValueTask DisposeAsync() diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs b/src/libraries/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs deleted file mode 100644 index 4c748bd307c29..0000000000000 --- a/src/libraries/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs +++ /dev/null @@ -1,446 +0,0 @@ -// 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.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Security -{ - // - // This is a wrapping stream that does data encryption/decryption based on a successfully authenticated SSPI context. - // This file contains the private implementation. - // - public partial class NegotiateStream : AuthenticatedStream - { - private static readonly AsyncCallback s_writeCallback = new AsyncCallback(WriteCallback); - private static readonly AsyncProtocolCallback s_readCallback = new AsyncProtocolCallback(ReadCallback); - - private int _NestedWrite; - private int _NestedRead; - private byte[] _ReadHeader = null!; // will be initialized by ctor helper - - // Never updated directly, special properties are used. - private byte[]? _InternalBuffer; - private int _InternalOffset; - private int _InternalBufferCount; - - private void InitializeStreamPart() - { - _ReadHeader = new byte[4]; - } - - private byte[]? InternalBuffer - { - get - { - return _InternalBuffer; - } - } - - private int InternalOffset - { - get - { - return _InternalOffset; - } - } - - private int InternalBufferCount - { - get - { - return _InternalBufferCount; - } - } - - private void DecrementInternalBufferCount(int decrCount) - { - _InternalOffset += decrCount; - _InternalBufferCount -= decrCount; - } - - private void EnsureInternalBufferSize(int bytes) - { - _InternalBufferCount = bytes; - _InternalOffset = 0; - if (InternalBuffer == null || InternalBuffer.Length < bytes) - { - _InternalBuffer = new byte[bytes]; - } - } - - private void AdjustInternalBufferOffsetSize(int bytes, int offset) - { - _InternalBufferCount = bytes; - _InternalOffset = offset; - } - - // - // Validates user parameters for all Read/Write methods. - // - private void ValidateParameters(byte[] buffer, int offset, int count) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (offset < 0) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count)); - } - - if (count > buffer.Length - offset) - { - throw new ArgumentOutOfRangeException(nameof(count), SR.net_offset_plus_count); - } - } - - // - // Combined sync/async write method. For sync request asyncRequest==null. - // - private void ProcessWrite(byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - ValidateParameters(buffer, offset, count); - - if (Interlocked.Exchange(ref _NestedWrite, 1) == 1) - { - throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginWrite" : "Write"), "write")); - } - - bool failed = false; - try - { - StartWriting(buffer, offset, count, asyncRequest); - } - catch (Exception e) - { - failed = true; - if (e is IOException) - { - throw; - } - - throw new IOException(SR.net_io_write, e); - } - finally - { - if (asyncRequest == null || failed) - { - _NestedWrite = 0; - } - } - } - - private void StartWriting(byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - // We loop to this method from the callback. - // If the last chunk was just completed from async callback (count < 0), we complete user request. - if (count >= 0) - { - byte[]? outBuffer = null; - do - { - int chunkBytes = Math.Min(count, NegoState.MaxWriteDataSize); - int encryptedBytes; - - try - { - encryptedBytes = _negoState.EncryptData(buffer, offset, chunkBytes, ref outBuffer); - } - catch (Exception e) - { - throw new IOException(SR.net_io_encrypt, e); - } - - if (asyncRequest != null) - { - // prepare for the next request - asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, null); - Task t = InnerStream.WriteAsync(outBuffer!, 0, encryptedBytes); - if (t.IsCompleted) - { - t.GetAwaiter().GetResult(); - } - else - { - IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest); - if (!ar.CompletedSynchronously) - { - return; - } - TaskToApm.End(ar); - } - } - else - { - InnerStream.Write(outBuffer!, 0, encryptedBytes); - } - - offset += chunkBytes; - count -= chunkBytes; - } while (count != 0); - } - - if (asyncRequest != null) - { - asyncRequest.CompleteUser(); - } - } - - // - // Combined sync/async read method. For sync request asyncRequest==null. - // There is a little overhead because we need to pass buffer/offset/count used only in sync. - // Still the benefit is that we have a common sync/async code path. - // - private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - ValidateParameters(buffer, offset, count); - - if (Interlocked.Exchange(ref _NestedRead, 1) == 1) - { - throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginRead" : "Read"), "read")); - } - - bool failed = false; - try - { - if (InternalBufferCount != 0) - { - int copyBytes = InternalBufferCount > count ? count : InternalBufferCount; - if (copyBytes != 0) - { - Buffer.BlockCopy(InternalBuffer!, InternalOffset, buffer, offset, copyBytes); - DecrementInternalBufferCount(copyBytes); - } - asyncRequest?.CompleteUser(copyBytes); - return copyBytes; - } - - // Performing actual I/O. - return StartReading(buffer, offset, count, asyncRequest); - } - catch (Exception e) - { - failed = true; - if (e is IOException) - { - throw; - } - throw new IOException(SR.net_io_read, e); - } - finally - { - if (asyncRequest == null || failed) - { - _NestedRead = 0; - } - } - } - - // - // To avoid recursion when 0 bytes have been decrypted, loop until decryption results in at least 1 byte. - // - private int StartReading(byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - int result; - // When we read -1 bytes means we have decrypted 0 bytes, need looping. - while ((result = StartFrameHeader(buffer, offset, count, asyncRequest)) == -1); - - return result; - } - - private int StartFrameHeader(byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - int readBytes = 0; - if (asyncRequest != null) - { - asyncRequest.SetNextRequest(_ReadHeader, 0, _ReadHeader.Length, s_readCallback); - _ = FixedSizeReader.ReadPacketAsync(InnerStream, asyncRequest); - if (!asyncRequest.MustCompleteSynchronously) - { - return 0; - } - - readBytes = asyncRequest.Result; - } - else - { - readBytes = FixedSizeReader.ReadPacket(InnerStream, _ReadHeader, 0, _ReadHeader.Length); - } - - return StartFrameBody(readBytes, buffer, offset, count, asyncRequest); - } - - private int StartFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - if (readBytes == 0) - { - //EOF - asyncRequest?.CompleteUser(0); - return 0; - } - - if (!(readBytes == _ReadHeader.Length)) - { - NetEventSource.Fail(this, $"Frame size must be 4 but received {readBytes} bytes."); - } - - // Replace readBytes with the body size recovered from the header content. - readBytes = _ReadHeader[3]; - readBytes = (readBytes << 8) | _ReadHeader[2]; - readBytes = (readBytes << 8) | _ReadHeader[1]; - readBytes = (readBytes << 8) | _ReadHeader[0]; - - // - // The body carries 4 bytes for trailer size slot plus trailer, hence <=4 frame size is always an error. - // Additionally we'd like to restrict the read frame size to 64k. - // - if (readBytes <= 4 || readBytes > NegoState.MaxReadFrameSize) - { - throw new IOException(SR.net_frame_read_size); - } - - // - // Always pass InternalBuffer for SSPI "in place" decryption. - // A user buffer can be shared by many threads in that case decryption/integrity check may fail cause of data corruption. - // - EnsureInternalBufferSize(readBytes); - if (asyncRequest != null) - { - asyncRequest.SetNextRequest(InternalBuffer, 0, readBytes, s_readCallback); - - _ = FixedSizeReader.ReadPacketAsync(InnerStream, asyncRequest); - - if (!asyncRequest.MustCompleteSynchronously) - { - return 0; - } - - readBytes = asyncRequest.Result; - } - else //Sync - { - readBytes = FixedSizeReader.ReadPacket(InnerStream, InternalBuffer!, 0, readBytes); - } - - return ProcessFrameBody(readBytes, buffer, offset, count, asyncRequest); - } - - private int ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, AsyncProtocolRequest? asyncRequest) - { - if (readBytes == 0) - { - // We already checked that the frame body is bigger than 0 bytes - // Hence, this is an EOF ... fire. - throw new IOException(SR.net_io_eof); - } - - // Decrypt into internal buffer, change "readBytes" to count now _Decrypted Bytes_ - int internalOffset; - readBytes = _negoState.DecryptData(InternalBuffer!, 0, readBytes, out internalOffset); - - // Decrypted data start from zero offset, the size can be shrunk after decryption. - AdjustInternalBufferOffsetSize(readBytes, internalOffset); - - if (readBytes == 0 && count != 0) - { - // Read again. - return -1; - } - - if (readBytes > count) - { - readBytes = count; - } - - Buffer.BlockCopy(InternalBuffer!, InternalOffset, buffer, offset, readBytes); - - // This will adjust both the remaining internal buffer count and the offset. - DecrementInternalBufferCount(readBytes); - - asyncRequest?.CompleteUser(readBytes); - - return readBytes; - } - - private static void WriteCallback(IAsyncResult transportResult) - { - if (transportResult.CompletedSynchronously) - { - return; - } - - if (!(transportResult.AsyncState is AsyncProtocolRequest)) - { - NetEventSource.Fail(transportResult, "State type is wrong, expected AsyncProtocolRequest."); - } - - AsyncProtocolRequest asyncRequest = (AsyncProtocolRequest)transportResult.AsyncState!; - - try - { - NegotiateStream negoStream = (NegotiateStream)asyncRequest.AsyncObject!; - TaskToApm.End(transportResult); - if (asyncRequest.Count == 0) - { - // This was the last chunk. - asyncRequest.Count = -1; - } - - negoStream.StartWriting(asyncRequest.Buffer!, asyncRequest.Offset, asyncRequest.Count, asyncRequest); - } - catch (Exception e) - { - if (asyncRequest.IsUserCompleted) - { - // This will throw on a worker thread. - throw; - } - - asyncRequest.CompleteUserWithError(e); - } - } - - private static void ReadCallback(AsyncProtocolRequest asyncRequest) - { - // Async ONLY completion. - try - { - NegotiateStream negoStream = (NegotiateStream)asyncRequest.AsyncObject!; - BufferAsyncResult bufferResult = (BufferAsyncResult)asyncRequest.UserAsyncResult; - - // This is an optimization to avoid an additional callback. - if ((object?)asyncRequest.Buffer == (object?)negoStream._ReadHeader) - { - negoStream.StartFrameBody(asyncRequest.Result, bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest); - } - else - { - if (-1 == negoStream.ProcessFrameBody(asyncRequest.Result, bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest)) - { - // In case we decrypted 0 bytes, start another reading. - negoStream.StartReading(bufferResult.Buffer, bufferResult.Offset, bufferResult.Count, asyncRequest); - } - } - } - catch (Exception e) - { - if (asyncRequest.IsUserCompleted) - { - // This will throw on a worker thread. - throw; - } - - asyncRequest.CompleteUserWithError(e); - } - } - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NegoState.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NegoState.cs deleted file mode 100644 index b59ffb97692ca..0000000000000 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NegoState.cs +++ /dev/null @@ -1,840 +0,0 @@ -// 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.Diagnostics; -using System.IO; -using System.Security.Principal; -using System.Threading; -using System.ComponentModel; -using System.Runtime.ExceptionServices; -using System.Security.Authentication; -using System.Security.Authentication.ExtendedProtection; - -namespace System.Net.Security -{ - // - // The class maintains the state of the authentication process and the security context. - // It encapsulates security context and does the real work in authentication and - // user data encryption - // - internal class NegoState - { -#pragma warning disable CA1825 // used in reference comparison, requires unique object identity - private static readonly byte[] s_emptyMessage = new byte[0]; -#pragma warning restore CA1825 - private static readonly AsyncCallback s_readCallback = new AsyncCallback(ReadCallback); - private static readonly AsyncCallback s_writeCallback = new AsyncCallback(WriteCallback); - - private readonly Stream _innerStream; - - private Exception? _exception; - - private StreamFramer? _framer; - private NTAuthentication? _context; - - private int _nestedAuth; - - internal const int ERROR_TRUST_FAILURE = 1790; // Used to serialize protectionLevel or impersonationLevel mismatch error to the remote side. - internal const int MaxReadFrameSize = 64 * 1024; - internal const int MaxWriteDataSize = 63 * 1024; // 1k for the framing and trailer that is always less as per SSPI. - - private bool _canRetryAuthentication; - private ProtectionLevel _expectedProtectionLevel; - private TokenImpersonationLevel _expectedImpersonationLevel; - private uint _writeSequenceNumber; - private uint _readSequenceNumber; - - private ExtendedProtectionPolicy? _extendedProtectionPolicy; - - // SSPI does not send a server ack on successful auth. - // This is a state variable used to gracefully handle auth confirmation. - private bool _remoteOk = false; - - internal NegoState(Stream innerStream) - { - Debug.Assert(innerStream != null); - - _innerStream = innerStream; - } - - internal static string DefaultPackage - { - get - { - return NegotiationInfoClass.Negotiate; - } - } - - internal IIdentity GetIdentity() - { - CheckThrow(true); - return NegotiateStreamPal.GetIdentity(_context!); - } - - internal void ValidateCreateContext( - string package, - NetworkCredential credential, - string servicePrincipalName, - ExtendedProtectionPolicy? policy, - ProtectionLevel protectionLevel, - TokenImpersonationLevel impersonationLevel) - { - if (policy != null) - { - // One of these must be set if EP is turned on - if (policy.CustomChannelBinding == null && policy.CustomServiceNames == null) - { - throw new ArgumentException(SR.net_auth_must_specify_extended_protection_scheme, nameof(policy)); - } - - _extendedProtectionPolicy = policy; - } - else - { - _extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never); - } - - ValidateCreateContext(package, true, credential, servicePrincipalName, _extendedProtectionPolicy!.CustomChannelBinding, protectionLevel, impersonationLevel); - } - - internal void ValidateCreateContext( - string package, - bool isServer, - NetworkCredential credential, - string? servicePrincipalName, - ChannelBinding? channelBinding, - ProtectionLevel protectionLevel, - TokenImpersonationLevel impersonationLevel) - { - if (_exception != null && !_canRetryAuthentication) - { - ExceptionDispatchInfo.Throw(_exception); - } - - if (_context != null && _context.IsValidContext) - { - throw new InvalidOperationException(SR.net_auth_reauth); - } - - if (credential == null) - { - throw new ArgumentNullException(nameof(credential)); - } - - if (servicePrincipalName == null) - { - throw new ArgumentNullException(nameof(servicePrincipalName)); - } - - NegotiateStreamPal.ValidateImpersonationLevel(impersonationLevel); - if (_context != null && IsServer != isServer) - { - throw new InvalidOperationException(SR.net_auth_client_server); - } - - _exception = null; - _remoteOk = false; - _framer = new StreamFramer(_innerStream); - _framer.WriteHeader.MessageId = FrameHeader.HandshakeId; - - _expectedProtectionLevel = protectionLevel; - _expectedImpersonationLevel = isServer ? impersonationLevel : TokenImpersonationLevel.None; - _writeSequenceNumber = 0; - _readSequenceNumber = 0; - - ContextFlagsPal flags = ContextFlagsPal.Connection; - - // A workaround for the client when talking to Win9x on the server side. - if (protectionLevel == ProtectionLevel.None && !isServer) - { - package = NegotiationInfoClass.NTLM; - } - else if (protectionLevel == ProtectionLevel.EncryptAndSign) - { - flags |= ContextFlagsPal.Confidentiality; - } - else if (protectionLevel == ProtectionLevel.Sign) - { - // Assuming user expects NT4 SP4 and above. - flags |= (ContextFlagsPal.ReplayDetect | ContextFlagsPal.SequenceDetect | ContextFlagsPal.InitIntegrity); - } - - if (isServer) - { - if (_extendedProtectionPolicy!.PolicyEnforcement == PolicyEnforcement.WhenSupported) - { - flags |= ContextFlagsPal.AllowMissingBindings; - } - - if (_extendedProtectionPolicy.PolicyEnforcement != PolicyEnforcement.Never && - _extendedProtectionPolicy.ProtectionScenario == ProtectionScenario.TrustedProxy) - { - flags |= ContextFlagsPal.ProxyBindings; - } - } - else - { - // Server side should not request any of these flags. - if (protectionLevel != ProtectionLevel.None) - { - flags |= ContextFlagsPal.MutualAuth; - } - - if (impersonationLevel == TokenImpersonationLevel.Identification) - { - flags |= ContextFlagsPal.InitIdentify; - } - - if (impersonationLevel == TokenImpersonationLevel.Delegation) - { - flags |= ContextFlagsPal.Delegate; - } - } - - _canRetryAuthentication = false; - - try - { - _context = new NTAuthentication(isServer, package, credential, servicePrincipalName, flags, channelBinding!); - } - catch (Win32Exception e) - { - throw new AuthenticationException(SR.net_auth_SSPI, e); - } - } - - private Exception SetException(Exception e) - { - if (_exception == null || !(_exception is ObjectDisposedException)) - { - _exception = e; - } - - if (_exception != null && _context != null) - { - _context.CloseContext(); - } - - return _exception!; - } - - internal bool IsAuthenticated - { - get - { - return _context != null && HandshakeComplete && _exception == null && _remoteOk; - } - } - - internal bool IsMutuallyAuthenticated - { - get - { - if (!IsAuthenticated) - { - return false; - } - - // Suppressing for NTLM since SSPI does not return correct value in the context flags. - if (_context!.IsNTLM) - { - return false; - } - - return _context.IsMutualAuthFlag; - } - } - - internal bool IsEncrypted - { - get - { - return IsAuthenticated && _context!.IsConfidentialityFlag; - } - } - - internal bool IsSigned - { - get - { - return IsAuthenticated && (_context!.IsIntegrityFlag || _context.IsConfidentialityFlag); - } - } - - internal bool IsServer - { - get - { - return _context != null && _context.IsServer; - } - } - - internal bool CanGetSecureStream - { - get - { - return (_context!.IsConfidentialityFlag || _context.IsIntegrityFlag); - } - } - - internal TokenImpersonationLevel AllowedImpersonation - { - get - { - CheckThrow(true); - return PrivateImpersonationLevel; - } - } - - private TokenImpersonationLevel PrivateImpersonationLevel - { - get - { - // We should suppress the delegate flag in NTLM case. - return (_context!.IsDelegationFlag && _context.ProtocolName != NegotiationInfoClass.NTLM) ? TokenImpersonationLevel.Delegation - : _context.IsIdentifyFlag ? TokenImpersonationLevel.Identification - : TokenImpersonationLevel.Impersonation; - } - } - - private bool HandshakeComplete - { - get - { - return _context!.IsCompleted && _context.IsValidContext; - } - } - - internal void CheckThrow(bool authSucessCheck) - { - if (_exception != null) - { - ExceptionDispatchInfo.Throw(_exception); - } - - if (authSucessCheck && !IsAuthenticated) - { - throw new InvalidOperationException(SR.net_auth_noauth); - } - } - - // - // This is to not depend on GC&SafeHandle class if the context is not needed anymore. - // - internal void Close() - { - // Mark this instance as disposed. - _exception = new ObjectDisposedException("NegotiateStream"); - if (_context != null) - { - _context.CloseContext(); - } - } - - internal void ProcessAuthentication(LazyAsyncResult? lazyResult) - { - CheckThrow(false); - if (Interlocked.Exchange(ref _nestedAuth, 1) == 1) - { - throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, lazyResult == null ? "BeginAuthenticate" : "Authenticate", "authenticate")); - } - - try - { - if (_context!.IsServer) - { - // Listen for a client blob. - StartReceiveBlob(lazyResult); - } - else - { - // Start with the first blob. - StartSendBlob(null, lazyResult); - } - } - catch (Exception e) - { - // Round-trip it through SetException(). - e = SetException(e); - throw; - } - finally - { - if (lazyResult == null || _exception != null) - { - _nestedAuth = 0; - } - } - } - - internal void EndProcessAuthentication(IAsyncResult result) - { - if (result == null) - { - throw new ArgumentNullException("asyncResult"); - } - - LazyAsyncResult? lazyResult = result as LazyAsyncResult; - if (lazyResult == null) - { - throw new ArgumentException(SR.Format(SR.net_io_async_result, result.GetType().FullName), "asyncResult"); - } - - if (Interlocked.Exchange(ref _nestedAuth, 0) == 0) - { - throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndAuthenticate")); - } - - // No "artificial" timeouts implemented so far, InnerStream controls that. - lazyResult.InternalWaitForCompletion(); - - Exception? e = lazyResult.Result as Exception; - - if (e != null) - { - // Round-trip it through the SetException(). - e = SetException(e); - ExceptionDispatchInfo.Throw(e); - } - } - - private bool CheckSpn() - { - if (_context!.IsKerberos) - { - return true; - } - - if (_extendedProtectionPolicy!.PolicyEnforcement == PolicyEnforcement.Never || - _extendedProtectionPolicy.CustomServiceNames == null) - { - return true; - } - - string? clientSpn = _context.ClientSpecifiedSpn; - - if (string.IsNullOrEmpty(clientSpn)) - { - if (_extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.WhenSupported) - { - return true; - } - } - else - { - return _extendedProtectionPolicy.CustomServiceNames.Contains(clientSpn); - } - - return false; - } - - // - // Client side starts here, but server also loops through this method. - // - private void StartSendBlob(byte[]? message, LazyAsyncResult? lazyResult) - { - Exception? exception = null; - if (message != s_emptyMessage) - { - message = GetOutgoingBlob(message, ref exception); - } - - if (exception != null) - { - // Signal remote side on a failed attempt. - StartSendAuthResetSignal(lazyResult, message!, exception); - return; - } - - if (HandshakeComplete) - { - if (_context!.IsServer && !CheckSpn()) - { - exception = new AuthenticationException(SR.net_auth_bad_client_creds_or_target_mismatch); - int statusCode = ERROR_TRUST_FAILURE; - message = new byte[8]; //sizeof(long) - - for (int i = message.Length - 1; i >= 0; --i) - { - message[i] = (byte)(statusCode & 0xFF); - statusCode = (int)((uint)statusCode >> 8); - } - - StartSendAuthResetSignal(lazyResult, message, exception); - return; - } - - if (PrivateImpersonationLevel < _expectedImpersonationLevel) - { - exception = new AuthenticationException(SR.Format(SR.net_auth_context_expectation, _expectedImpersonationLevel.ToString(), PrivateImpersonationLevel.ToString())); - int statusCode = ERROR_TRUST_FAILURE; - message = new byte[8]; //sizeof(long) - - for (int i = message.Length - 1; i >= 0; --i) - { - message[i] = (byte)(statusCode & 0xFF); - statusCode = (int)((uint)statusCode >> 8); - } - - StartSendAuthResetSignal(lazyResult, message, exception); - return; - } - - ProtectionLevel result = _context.IsConfidentialityFlag ? ProtectionLevel.EncryptAndSign : _context.IsIntegrityFlag ? ProtectionLevel.Sign : ProtectionLevel.None; - - if (result < _expectedProtectionLevel) - { - exception = new AuthenticationException(SR.Format(SR.net_auth_context_expectation, result.ToString(), _expectedProtectionLevel.ToString())); - int statusCode = ERROR_TRUST_FAILURE; - message = new byte[8]; //sizeof(long) - - for (int i = message.Length - 1; i >= 0; --i) - { - message[i] = (byte)(statusCode & 0xFF); - statusCode = (int)((uint)statusCode >> 8); - } - - StartSendAuthResetSignal(lazyResult, message, exception); - return; - } - - // Signal remote party that we are done - _framer!.WriteHeader.MessageId = FrameHeader.HandshakeDoneId; - if (_context.IsServer) - { - // Server may complete now because client SSPI would not complain at this point. - _remoteOk = true; - - // However the client will wait for server to send this ACK - //Force signaling server OK to the client - if (message == null) - { - message = s_emptyMessage; - } - } - } - else if (message == null || message == s_emptyMessage) - { - throw new InternalException(); - } - - if (message != null) - { - //even if we are completed, there could be a blob for sending. - if (lazyResult == null) - { - _framer!.WriteMessage(message); - } - else - { - IAsyncResult ar = _framer!.BeginWriteMessage(message, s_writeCallback, lazyResult); - if (!ar.CompletedSynchronously) - { - return; - } - _framer.EndWriteMessage(ar); - } - } - CheckCompletionBeforeNextReceive(lazyResult); - } - - // - // This will check and logically complete the auth handshake. - // - private void CheckCompletionBeforeNextReceive(LazyAsyncResult? lazyResult) - { - if (HandshakeComplete && _remoteOk) - { - // We are done with success. - if (lazyResult != null) - { - lazyResult.InvokeCallback(); - } - - return; - } - - StartReceiveBlob(lazyResult); - } - - // - // Server side starts here, but client also loops through this method. - // - private void StartReceiveBlob(LazyAsyncResult? lazyResult) - { - Debug.Assert(_framer != null); - - byte[]? message; - if (lazyResult == null) - { - message = _framer.ReadMessage(); - } - else - { - IAsyncResult ar = _framer.BeginReadMessage(s_readCallback, lazyResult); - if (!ar.CompletedSynchronously) - { - return; - } - - message = _framer.EndReadMessage(ar); - } - - ProcessReceivedBlob(message, lazyResult); - } - - private void ProcessReceivedBlob(byte[]? message, LazyAsyncResult? lazyResult) - { - // This is an EOF otherwise we would get at least *empty* message but not a null one. - if (message == null) - { - throw new AuthenticationException(SR.net_auth_eof, null); - } - - // Process Header information. - if (_framer!.ReadHeader.MessageId == FrameHeader.HandshakeErrId) - { - if (message.Length >= 8) // sizeof(long) - { - // Try to recover remote win32 Exception. - long error = 0; - for (int i = 0; i < 8; ++i) - { - error = (error << 8) + message[i]; - } - - ThrowCredentialException(error); - } - - throw new AuthenticationException(SR.net_auth_alert, null); - } - - if (_framer.ReadHeader.MessageId == FrameHeader.HandshakeDoneId) - { - _remoteOk = true; - } - else if (_framer.ReadHeader.MessageId != FrameHeader.HandshakeId) - { - throw new AuthenticationException(SR.Format(SR.net_io_header_id, "MessageId", _framer.ReadHeader.MessageId, FrameHeader.HandshakeId), null); - } - - CheckCompletionBeforeNextSend(message, lazyResult); - } - - // - // This will check and logically complete the auth handshake. - // - private void CheckCompletionBeforeNextSend(byte[] message, LazyAsyncResult? lazyResult) - { - //If we are done don't go into send. - if (HandshakeComplete) - { - if (!_remoteOk) - { - throw new AuthenticationException(SR.Format(SR.net_io_header_id, "MessageId", _framer!.ReadHeader.MessageId, FrameHeader.HandshakeDoneId), null); - } - if (lazyResult != null) - { - lazyResult.InvokeCallback(); - } - - return; - } - - // Not yet done, get a new blob and send it if any. - StartSendBlob(message, lazyResult); - } - - // - // This is to reset auth state on the remote side. - // If this write succeeds we will allow auth retrying. - // - private void StartSendAuthResetSignal(LazyAsyncResult? lazyResult, byte[] message, Exception exception) - { - _framer!.WriteHeader.MessageId = FrameHeader.HandshakeErrId; - - if (IsLogonDeniedException(exception)) - { - if (IsServer) - { - exception = new InvalidCredentialException(SR.net_auth_bad_client_creds, exception); - } - else - { - exception = new InvalidCredentialException(SR.net_auth_bad_client_creds_or_target_mismatch, exception); - } - } - - if (!(exception is AuthenticationException)) - { - exception = new AuthenticationException(SR.net_auth_SSPI, exception); - } - - if (lazyResult == null) - { - _framer.WriteMessage(message); - } - else - { - lazyResult.Result = exception; - IAsyncResult ar = _framer.BeginWriteMessage(message, s_writeCallback, lazyResult); - if (!ar.CompletedSynchronously) - { - return; - } - - _framer.EndWriteMessage(ar); - } - - _canRetryAuthentication = true; - ExceptionDispatchInfo.Throw(exception); - } - - private static void WriteCallback(IAsyncResult transportResult) - { - if (!(transportResult.AsyncState is LazyAsyncResult)) - { - NetEventSource.Fail(transportResult, "State type is wrong, expected LazyAsyncResult."); - } - - if (transportResult.CompletedSynchronously) - { - return; - } - - LazyAsyncResult lazyResult = (LazyAsyncResult)transportResult.AsyncState!; - - // Async completion. - try - { - NegoState authState = (NegoState)lazyResult.AsyncObject!; - authState._framer!.EndWriteMessage(transportResult); - - // Special case for an error notification. - if (lazyResult.Result is Exception e) - { - authState._canRetryAuthentication = true; - ExceptionDispatchInfo.Throw(e); - } - - authState.CheckCompletionBeforeNextReceive(lazyResult); - } - catch (Exception e) - { - if (lazyResult.InternalPeekCompleted) - { - // This will throw on a worker thread. - throw; - } - - lazyResult.InvokeCallback(e); - } - } - - private static void ReadCallback(IAsyncResult transportResult) - { - if (!(transportResult.AsyncState is LazyAsyncResult)) - { - NetEventSource.Fail(transportResult, "State type is wrong, expected LazyAsyncResult."); - } - - if (transportResult.CompletedSynchronously) - { - return; - } - - LazyAsyncResult lazyResult = (LazyAsyncResult)transportResult.AsyncState!; - - // Async completion. - try - { - NegoState authState = (NegoState)lazyResult.AsyncObject!; - byte[]? message = authState._framer!.EndReadMessage(transportResult); - authState.ProcessReceivedBlob(message, lazyResult); - } - catch (Exception e) - { - if (lazyResult.InternalPeekCompleted) - { - // This will throw on a worker thread. - throw; - } - - lazyResult.InvokeCallback(e); - } - } - - internal static bool IsError(SecurityStatusPal status) - { - return ((int)status.ErrorCode >= (int)SecurityStatusPalErrorCode.OutOfMemory); - } - - private unsafe byte[]? GetOutgoingBlob(byte[]? incomingBlob, ref Exception? e) - { - byte[]? message = _context!.GetOutgoingBlob(incomingBlob, false, out SecurityStatusPal statusCode); - - if (IsError(statusCode)) - { - e = NegotiateStreamPal.CreateExceptionFromError(statusCode); - uint error = (uint)e.HResult; - - message = new byte[sizeof(long)]; - for (int i = message.Length - 1; i >= 0; --i) - { - message[i] = (byte)(error & 0xFF); - error = (error >> 8); - } - } - - if (message != null && message.Length == 0) - { - message = s_emptyMessage; - } - - return message; - } - - internal int EncryptData(byte[] buffer, int offset, int count, ref byte[]? outBuffer) - { - CheckThrow(true); - - // SSPI seems to ignore this sequence number. - ++_writeSequenceNumber; - return _context!.Encrypt(buffer, offset, count, ref outBuffer, _writeSequenceNumber); - } - - internal int DecryptData(byte[] buffer, int offset, int count, out int newOffset) - { - CheckThrow(true); - - // SSPI seems to ignore this sequence number. - ++_readSequenceNumber; - return _context!.Decrypt(buffer, offset, count, out newOffset, _readSequenceNumber); - } - - internal static void ThrowCredentialException(long error) - { - Win32Exception e = new Win32Exception((int)error); - - if (e.NativeErrorCode == (int)SecurityStatusPalErrorCode.LogonDenied) - { - throw new InvalidCredentialException(SR.net_auth_bad_client_creds, e); - } - - if (e.NativeErrorCode == NegoState.ERROR_TRUST_FAILURE) - { - throw new AuthenticationException(SR.net_auth_context_expectation_remote, e); - } - - throw new AuthenticationException(SR.net_auth_alert, e); - } - - internal static bool IsLogonDeniedException(Exception exception) - { - Win32Exception? win32exception = exception as Win32Exception; - - return (win32exception != null) && (win32exception.NativeErrorCode == (int)SecurityStatusPalErrorCode.LogonDenied); - } - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStream.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStream.cs index 7fdf5ab50f3d8..8a420ed6a4baf 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStream.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStream.cs @@ -2,34 +2,59 @@ // 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.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Threading; -using System.Threading.Tasks; +using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; +using System.Security.Authentication; using System.Security.Authentication.ExtendedProtection; using System.Security.Principal; +using System.Threading; +using System.Threading.Tasks; namespace System.Net.Security { - /* - An authenticated stream based on NEGO SSP. - - The class that can be used by client and server side applications - - to transfer Identities across the stream - - to encrypt data based on NEGO SSP package - - In most cases the innerStream will be of type NetworkStream. - On Win9x data encryption is not available and both sides have - to explicitly drop SecurityLevel and MuatualAuth requirements. - - This is a simple wrapper class. - All real work is done by internal NegoState class and the other partial implementation files. - */ + /// + /// Provides a stream that uses the Negotiate security protocol to authenticate the client, and optionally the server, in client-server communication. + /// public partial class NegotiateStream : AuthenticatedStream { - private readonly NegoState _negoState; - private readonly string _package; + private const int ERROR_TRUST_FAILURE = 1790; // Used to serialize protectionLevel or impersonationLevel mismatch error to the remote side. + private const int MaxReadFrameSize = 64 * 1024; + private const int MaxWriteDataSize = 63 * 1024; // 1k for the framing and trailer that is always less as per SSPI. + private const string DefaultPackage = NegotiationInfoClass.Negotiate; + +#pragma warning disable CA1825 // used in reference comparison, requires unique object identity + private static readonly byte[] s_emptyMessage = new byte[0]; +#pragma warning restore CA1825 + + private readonly byte[] _readHeader; private IIdentity? _remoteIdentity; + private byte[] _buffer; + private int _bufferOffset; + private int _bufferCount; + + private volatile int _writeInProgress; + private volatile int _readInProgress; + private volatile int _authInProgress; + + private Exception? _exception; + private StreamFramer? _framer; + private NTAuthentication? _context; + private bool _canRetryAuthentication; + private ProtectionLevel _expectedProtectionLevel; + private TokenImpersonationLevel _expectedImpersonationLevel; + private uint _writeSequenceNumber; + private uint _readSequenceNumber; + private ExtendedProtectionPolicy? _extendedProtectionPolicy; + + /// + /// SSPI does not send a server ack on successful auth. + /// This is a state variable used to gracefully handle auth confirmation. + /// + private bool _remoteOk = false; public NegotiateStream(Stream innerStream) : this(innerStream, false) { @@ -37,687 +62,920 @@ public NegotiateStream(Stream innerStream) : this(innerStream, false) public NegotiateStream(Stream innerStream, bool leaveInnerStreamOpen) : base(innerStream, leaveInnerStreamOpen) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) - { -#endif - _negoState = new NegoState(innerStream); - _package = NegoState.DefaultPackage; - InitializeStreamPart(); -#if DEBUG - } -#endif + _readHeader = new byte[4]; + _buffer = Array.Empty(); } - public virtual IAsyncResult BeginAuthenticateAsClient(AsyncCallback? asyncCallback, object? asyncState) + protected override void Dispose(bool disposing) { - return BeginAuthenticateAsClient((NetworkCredential)CredentialCache.DefaultCredentials, null, string.Empty, - ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, - asyncCallback, asyncState); + try + { + _exception = new ObjectDisposedException(nameof(NegotiateStream)); + _context?.CloseContext(); + } + finally + { + base.Dispose(disposing); + } } - public virtual IAsyncResult BeginAuthenticateAsClient(NetworkCredential credential, string targetName, AsyncCallback? asyncCallback, object? asyncState) + public override async ValueTask DisposeAsync() { - return BeginAuthenticateAsClient(credential, null, targetName, - ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, - asyncCallback, asyncState); + try + { + _exception = new ObjectDisposedException(nameof(NegotiateStream)); + _context?.CloseContext(); + } + finally + { + await base.DisposeAsync().ConfigureAwait(false); + } } - public virtual IAsyncResult BeginAuthenticateAsClient(NetworkCredential credential, ChannelBinding? binding, string targetName, AsyncCallback? asyncCallback, object? asyncState) - { - return BeginAuthenticateAsClient(credential, binding, targetName, - ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, - asyncCallback, asyncState); - } + public virtual IAsyncResult BeginAuthenticateAsClient(AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsClient((NetworkCredential)CredentialCache.DefaultCredentials, binding: null, string.Empty, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, + asyncCallback, asyncState); - public virtual IAsyncResult BeginAuthenticateAsClient( - NetworkCredential credential, - string targetName, - ProtectionLevel requiredProtectionLevel, - TokenImpersonationLevel allowedImpersonationLevel, - AsyncCallback? asyncCallback, - object? asyncState) - { - return BeginAuthenticateAsClient(credential, null, targetName, - requiredProtectionLevel, allowedImpersonationLevel, - asyncCallback, asyncState); - } + public virtual IAsyncResult BeginAuthenticateAsClient(NetworkCredential credential, string targetName, AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsClient(credential, binding: null, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, + asyncCallback, asyncState); - public virtual IAsyncResult BeginAuthenticateAsClient( - NetworkCredential credential, - ChannelBinding? binding, - string targetName, - ProtectionLevel requiredProtectionLevel, - TokenImpersonationLevel allowedImpersonationLevel, - AsyncCallback? asyncCallback, - object? asyncState) - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - _negoState.ValidateCreateContext(_package, false, credential, targetName, binding, requiredProtectionLevel, allowedImpersonationLevel); + public virtual IAsyncResult BeginAuthenticateAsClient(NetworkCredential credential, ChannelBinding? binding, string targetName, AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsClient(credential, binding, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, + asyncCallback, asyncState); - LazyAsyncResult result = new LazyAsyncResult(_negoState, asyncState, asyncCallback); - _negoState.ProcessAuthentication(result); + public virtual IAsyncResult BeginAuthenticateAsClient( + NetworkCredential credential, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel, + AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsClient(credential, binding: null, targetName, requiredProtectionLevel, allowedImpersonationLevel, + asyncCallback, asyncState); - return result; -#if DEBUG - } -#endif - } + public virtual IAsyncResult BeginAuthenticateAsClient( + NetworkCredential credential, ChannelBinding? binding, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel, + AsyncCallback? asyncCallback, object? asyncState) => + TaskToApm.Begin(AuthenticateAsClientAsync(credential, binding, targetName, requiredProtectionLevel, allowedImpersonationLevel), asyncCallback, asyncState); - public virtual void EndAuthenticateAsClient(IAsyncResult asyncResult) - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) - { -#endif - _negoState.EndProcessAuthentication(asyncResult); -#if DEBUG - } -#endif - } + public virtual void EndAuthenticateAsClient(IAsyncResult asyncResult) => TaskToApm.End(asyncResult); - public virtual void AuthenticateAsServer() - { - AuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, null, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - } + public virtual void AuthenticateAsServer() => + AuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, policy: null, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - public virtual void AuthenticateAsServer(ExtendedProtectionPolicy? policy) - { + public virtual void AuthenticateAsServer(ExtendedProtectionPolicy? policy) => AuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, policy, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - } - public virtual void AuthenticateAsServer(NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) - { - AuthenticateAsServer(credential, null, requiredProtectionLevel, requiredImpersonationLevel); - } + public virtual void AuthenticateAsServer(NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) => + AuthenticateAsServer(credential, policy: null, requiredProtectionLevel, requiredImpersonationLevel); public virtual void AuthenticateAsServer(NetworkCredential credential, ExtendedProtectionPolicy? policy, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) - { -#endif - _negoState.ValidateCreateContext(_package, credential, string.Empty, policy, requiredProtectionLevel, requiredImpersonationLevel); - _negoState.ProcessAuthentication(null); -#if DEBUG - } -#endif + ValidateCreateContext(DefaultPackage, credential, string.Empty, policy, requiredProtectionLevel, requiredImpersonationLevel); + AuthenticateAsync(new SyncReadWriteAdapter(InnerStream)).GetAwaiter().GetResult(); } - public virtual IAsyncResult BeginAuthenticateAsServer(AsyncCallback? asyncCallback, object? asyncState) - { - return BeginAuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, null, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, asyncCallback, asyncState); - } + public virtual IAsyncResult BeginAuthenticateAsServer(AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, policy: null, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, asyncCallback, asyncState); - public virtual IAsyncResult BeginAuthenticateAsServer(ExtendedProtectionPolicy? policy, AsyncCallback? asyncCallback, object? asyncState) - { - return BeginAuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, policy, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, asyncCallback, asyncState); - } + public virtual IAsyncResult BeginAuthenticateAsServer(ExtendedProtectionPolicy? policy, AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, policy, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, asyncCallback, asyncState); public virtual IAsyncResult BeginAuthenticateAsServer( - NetworkCredential credential, - ProtectionLevel requiredProtectionLevel, - TokenImpersonationLevel requiredImpersonationLevel, - AsyncCallback? asyncCallback, - object? asyncState) - { - return BeginAuthenticateAsServer(credential, null, requiredProtectionLevel, requiredImpersonationLevel, asyncCallback, asyncState); - } + NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel, + AsyncCallback? asyncCallback, object? asyncState) => + BeginAuthenticateAsServer(credential, policy: null, requiredProtectionLevel, requiredImpersonationLevel, asyncCallback, asyncState); public virtual IAsyncResult BeginAuthenticateAsServer( - NetworkCredential credential, - ExtendedProtectionPolicy? policy, - ProtectionLevel requiredProtectionLevel, - TokenImpersonationLevel requiredImpersonationLevel, - AsyncCallback? asyncCallback, - object? asyncState) - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - _negoState.ValidateCreateContext(_package, credential, string.Empty, policy, requiredProtectionLevel, requiredImpersonationLevel); + NetworkCredential credential, ExtendedProtectionPolicy? policy, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel, + AsyncCallback? asyncCallback, object? asyncState) => + TaskToApm.Begin(AuthenticateAsServerAsync(credential, policy, requiredProtectionLevel, requiredImpersonationLevel), asyncCallback, asyncState); - LazyAsyncResult result = new LazyAsyncResult(_negoState, asyncState, asyncCallback); - _negoState.ProcessAuthentication(result); + public virtual void EndAuthenticateAsServer(IAsyncResult asyncResult) => TaskToApm.End(asyncResult); - return result; -#if DEBUG - } -#endif - } - // - public virtual void EndAuthenticateAsServer(IAsyncResult asyncResult) - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) - { -#endif - _negoState.EndProcessAuthentication(asyncResult); -#if DEBUG - } -#endif - } + public virtual void AuthenticateAsClient() => + AuthenticateAsClient((NetworkCredential)CredentialCache.DefaultCredentials, binding: null, string.Empty, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - public virtual void AuthenticateAsClient() - { - AuthenticateAsClient((NetworkCredential)CredentialCache.DefaultCredentials, null, string.Empty, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - } - - public virtual void AuthenticateAsClient(NetworkCredential credential, string targetName) - { - AuthenticateAsClient(credential, null, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - } + public virtual void AuthenticateAsClient(NetworkCredential credential, string targetName) => + AuthenticateAsClient(credential, binding: null, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - public virtual void AuthenticateAsClient(NetworkCredential credential, ChannelBinding? binding, string targetName) - { + public virtual void AuthenticateAsClient(NetworkCredential credential, ChannelBinding? binding, string targetName) => AuthenticateAsClient(credential, binding, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - } public virtual void AuthenticateAsClient( - NetworkCredential credential, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) - { - AuthenticateAsClient(credential, null, targetName, requiredProtectionLevel, allowedImpersonationLevel); - } + NetworkCredential credential, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) => + AuthenticateAsClient(credential, binding: null, targetName, requiredProtectionLevel, allowedImpersonationLevel); public virtual void AuthenticateAsClient( NetworkCredential credential, ChannelBinding? binding, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) - { -#endif - _negoState.ValidateCreateContext(_package, false, credential, targetName, binding, requiredProtectionLevel, allowedImpersonationLevel); - _negoState.ProcessAuthentication(null); -#if DEBUG - } -#endif + ValidateCreateContext(DefaultPackage, isServer: false, credential, targetName, binding, requiredProtectionLevel, allowedImpersonationLevel); + AuthenticateAsync(new SyncReadWriteAdapter(InnerStream)).GetAwaiter().GetResult(); } - public virtual Task AuthenticateAsClientAsync() - { - return Task.Factory.FromAsync(BeginAuthenticateAsClient, EndAuthenticateAsClient, null); - } + public virtual Task AuthenticateAsClientAsync() => + AuthenticateAsClientAsync((NetworkCredential)CredentialCache.DefaultCredentials, binding: null, string.Empty, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - public virtual Task AuthenticateAsClientAsync(NetworkCredential credential, string targetName) - { - return Task.Factory.FromAsync(BeginAuthenticateAsClient, EndAuthenticateAsClient, credential, targetName, null); - } + public virtual Task AuthenticateAsClientAsync(NetworkCredential credential, string targetName) => + AuthenticateAsClientAsync(credential, binding: null, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); public virtual Task AuthenticateAsClientAsync( NetworkCredential credential, string targetName, ProtectionLevel requiredProtectionLevel, - TokenImpersonationLevel allowedImpersonationLevel) - { - return Task.Factory.FromAsync((callback, state) => BeginAuthenticateAsClient(credential, targetName, requiredProtectionLevel, allowedImpersonationLevel, callback, state), EndAuthenticateAsClient, null); - } + TokenImpersonationLevel allowedImpersonationLevel) => + AuthenticateAsClientAsync(credential, binding: null, targetName, requiredProtectionLevel, allowedImpersonationLevel); - public virtual Task AuthenticateAsClientAsync(NetworkCredential credential, ChannelBinding? binding, string targetName) - { - return Task.Factory.FromAsync(BeginAuthenticateAsClient, EndAuthenticateAsClient, credential, binding, targetName, null); - } + public virtual Task AuthenticateAsClientAsync(NetworkCredential credential, ChannelBinding? binding, string targetName) => + AuthenticateAsClientAsync(credential, binding, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); public virtual Task AuthenticateAsClientAsync( - NetworkCredential credential, ChannelBinding? binding, - string targetName, ProtectionLevel requiredProtectionLevel, + NetworkCredential credential, ChannelBinding? binding, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) { - return Task.Factory.FromAsync((callback, state) => BeginAuthenticateAsClient(credential, binding, targetName, requiredProtectionLevel, allowedImpersonationLevel, callback, state), EndAuthenticateAsClient, null); + ValidateCreateContext(DefaultPackage, isServer: false, credential, targetName, binding, requiredProtectionLevel, allowedImpersonationLevel); + return AuthenticateAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken: default)); } - public virtual Task AuthenticateAsServerAsync() - { - return Task.Factory.FromAsync(BeginAuthenticateAsServer, EndAuthenticateAsServer, null); - } + public virtual Task AuthenticateAsServerAsync() => + AuthenticateAsServerAsync((NetworkCredential)CredentialCache.DefaultCredentials, policy: null, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - public virtual Task AuthenticateAsServerAsync(ExtendedProtectionPolicy? policy) - { - return Task.Factory.FromAsync(BeginAuthenticateAsServer, EndAuthenticateAsServer, policy, null); - } + public virtual Task AuthenticateAsServerAsync(ExtendedProtectionPolicy? policy) => + AuthenticateAsServerAsync((NetworkCredential)CredentialCache.DefaultCredentials, policy, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); - public virtual Task AuthenticateAsServerAsync(NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) - { - return Task.Factory.FromAsync(BeginAuthenticateAsServer, EndAuthenticateAsServer, credential, requiredProtectionLevel, requiredImpersonationLevel, null); - } + public virtual Task AuthenticateAsServerAsync(NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) => + AuthenticateAsServerAsync(credential, policy: null, requiredProtectionLevel, requiredImpersonationLevel); public virtual Task AuthenticateAsServerAsync( - NetworkCredential credential, ExtendedProtectionPolicy? policy, - ProtectionLevel requiredProtectionLevel, - TokenImpersonationLevel requiredImpersonationLevel) + NetworkCredential credential, ExtendedProtectionPolicy? policy, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) { - return Task.Factory.FromAsync((callback, state) => BeginAuthenticateAsServer(credential, policy, requiredProtectionLevel, requiredImpersonationLevel, callback, state), EndAuthenticateAsClient, null); + ValidateCreateContext(DefaultPackage, credential, string.Empty, policy, requiredProtectionLevel, requiredImpersonationLevel); + return AuthenticateAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken: default)); } - public override bool IsAuthenticated + public override bool IsAuthenticated => IsAuthenticatedCore; + + [MemberNotNullWhen(true, nameof(_context))] + private bool IsAuthenticatedCore => _context != null && HandshakeComplete && _exception == null && _remoteOk; + + public override bool IsMutuallyAuthenticated => + IsAuthenticatedCore && + !_context.IsNTLM && // suppressing for NTLM since SSPI does not return correct value in the context flags. + _context.IsMutualAuthFlag; + + public override bool IsEncrypted => IsAuthenticatedCore && _context.IsConfidentialityFlag; + + public override bool IsSigned => IsAuthenticatedCore && (_context.IsIntegrityFlag || _context.IsConfidentialityFlag); + + public override bool IsServer => _context != null && _context.IsServer; + + public virtual TokenImpersonationLevel ImpersonationLevel { get { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - return _negoState.IsAuthenticated; -#if DEBUG - } -#endif + ThrowIfFailed(authSuccessCheck: true); + return PrivateImpersonationLevel; } } - public override bool IsMutuallyAuthenticated + private TokenImpersonationLevel PrivateImpersonationLevel => + _context!.IsDelegationFlag && _context.ProtocolName != NegotiationInfoClass.NTLM ? TokenImpersonationLevel.Delegation : // We should suppress the delegate flag in NTLM case. + _context.IsIdentifyFlag ? TokenImpersonationLevel.Identification : + TokenImpersonationLevel.Impersonation; + + private bool HandshakeComplete => _context!.IsCompleted && _context.IsValidContext; + + private bool CanGetSecureStream => _context!.IsConfidentialityFlag || _context.IsIntegrityFlag; + + public virtual IIdentity RemoteIdentity { get { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + IIdentity? identity = _remoteIdentity; + if (identity is null) { -#endif - return _negoState.IsMutuallyAuthenticated; -#if DEBUG + ThrowIfFailed(authSuccessCheck: true); + _remoteIdentity = identity = NegotiateStreamPal.GetIdentity(_context!); } -#endif + return identity; } } - public override bool IsEncrypted + public override bool CanSeek => false; + + public override bool CanRead => IsAuthenticated && InnerStream.CanRead; + + public override bool CanTimeout => InnerStream.CanTimeout; + + public override bool CanWrite => IsAuthenticated && InnerStream.CanWrite; + + public override int ReadTimeout { - get - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - return _negoState.IsEncrypted; -#if DEBUG - } -#endif - } + get => InnerStream.ReadTimeout; + set => InnerStream.ReadTimeout = value; } - public override bool IsSigned + public override int WriteTimeout { - get + get => InnerStream.WriteTimeout; + set => InnerStream.WriteTimeout = value; + } + + public override long Length => InnerStream.Length; + + public override long Position + { + get => InnerStream.Position; + set => throw new NotSupportedException(SR.net_noseek); + } + + public override void SetLength(long value) => + InnerStream.SetLength(value); + + public override long Seek(long offset, SeekOrigin origin) => + throw new NotSupportedException(SR.net_noseek); + + public override void Flush() => + InnerStream.Flush(); + + public override Task FlushAsync(CancellationToken cancellationToken) => + InnerStream.FlushAsync(cancellationToken); + + public override int Read(byte[] buffer, int offset, int count) + { + ValidateParameters(buffer, offset, count); + + ThrowIfFailed(authSuccessCheck: true); + if (!CanGetSecureStream) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - return _negoState.IsSigned; -#if DEBUG - } -#endif + return InnerStream.Read(buffer, offset, count); } + + ValueTask vt = ReadAsync(new SyncReadWriteAdapter(InnerStream), new Memory(buffer, offset, count)); + Debug.Assert(vt.IsCompleted, "Should have completed synchroously with sync adapter"); + return vt.GetAwaiter().GetResult(); } - public override bool IsServer + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - get + ValidateParameters(buffer, offset, count); + + ThrowIfFailed(authSuccessCheck: true); + if (!CanGetSecureStream) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - return _negoState.IsServer; -#if DEBUG - } -#endif + return InnerStream.ReadAsync(buffer, offset, count, cancellationToken); } + + return ReadAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken), new Memory(buffer, offset, count)).AsTask(); } - public virtual TokenImpersonationLevel ImpersonationLevel + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { - get + ThrowIfFailed(authSuccessCheck: true); + if (!CanGetSecureStream) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - return _negoState.AllowedImpersonation; -#if DEBUG - } -#endif + return InnerStream.ReadAsync(buffer, cancellationToken); } + + return ReadAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken), buffer); } - public virtual IIdentity RemoteIdentity + private async ValueTask ReadAsync(TAdapter adapter, Memory buffer, [CallerMemberName] string? callerName = null) where TAdapter : IReadWriteAdapter { - get + if (Interlocked.Exchange(ref _readInProgress, 1) == 1) + { + throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, callerName, "read")); + } + + try { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + if (_bufferCount != 0) + { + int copyBytes = Math.Min(_bufferCount, buffer.Length); + if (copyBytes != 0) + { + _buffer.AsMemory(_bufferOffset, copyBytes).CopyTo(buffer); + _bufferOffset += copyBytes; + _bufferCount -= copyBytes; + } + return copyBytes; + } + + while (true) { -#endif + int readBytes = await adapter.ReadAllAsync(_readHeader).ConfigureAwait(false); + if (readBytes == 0) + { + return 0; + } + + // Replace readBytes with the body size recovered from the header content. + readBytes = BitConverter.ToInt32(_readHeader, 0); + + // The body carries 4 bytes for trailer size slot plus trailer, hence <= 4 frame size is always an error. + // Additionally we'd like to restrict the read frame size to 64k. + if (readBytes <= 4 || readBytes > MaxReadFrameSize) + { + throw new IOException(SR.net_frame_read_size); + } - if (_remoteIdentity == null) + // Always pass InternalBuffer for SSPI "in place" decryption. + // A user buffer can be shared by many threads in that case decryption/integrity check may fail cause of data corruption. + _bufferCount = readBytes; + _bufferOffset = 0; + if (_buffer.Length < readBytes) { - _remoteIdentity = _negoState.GetIdentity(); + _buffer = new byte[readBytes]; } + readBytes = await adapter.ReadAllAsync(new Memory(_buffer, 0, readBytes)).ConfigureAwait(false); + if (readBytes == 0) + { + // We already checked that the frame body is bigger than 0 bytes. Hence, this is an EOF. + throw new IOException(SR.net_io_eof); + } + + // Decrypt into internal buffer, change "readBytes" to count now _Decrypted Bytes_ + // Decrypted data start from zero offset, the size can be shrunk after decryption. + _bufferCount = readBytes = DecryptData(_buffer!, 0, readBytes, out _bufferOffset); + if (readBytes == 0 && buffer.Length != 0) + { + // Read again. + continue; + } + + if (readBytes > buffer.Length) + { + readBytes = buffer.Length; + } + + _buffer.AsMemory(_bufferOffset, readBytes).CopyTo(buffer); + _bufferOffset += readBytes; + _bufferCount -= readBytes; - return _remoteIdentity; -#if DEBUG + return readBytes; } -#endif + } + catch (Exception e) when (!(e is IOException || e is OperationCanceledException)) + { + throw new IOException(SR.net_io_read, e); + } + finally + { + _readInProgress = 0; } } - // - // Stream contract implementation - // - public override bool CanSeek + public override void Write(byte[] buffer, int offset, int count) { - get + ValidateParameters(buffer, offset, count); + + ThrowIfFailed(authSuccessCheck: true); + if (!CanGetSecureStream) { - return false; + InnerStream.Write(buffer, offset, count); + return; } + + WriteAsync(new SyncReadWriteAdapter(InnerStream), new ReadOnlyMemory(buffer, offset, count)).GetAwaiter().GetResult(); } - public override bool CanRead + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - get + ValidateParameters(buffer, offset, count); + + ThrowIfFailed(authSuccessCheck: true); + if (!CanGetSecureStream) { - return IsAuthenticated && InnerStream.CanRead; + return InnerStream.WriteAsync(buffer, offset, count, cancellationToken); } + + return WriteAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken), new ReadOnlyMemory(buffer, offset, count)); } - public override bool CanTimeout + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { - get + ThrowIfFailed(authSuccessCheck: true); + if (!CanGetSecureStream) { - return InnerStream.CanTimeout; + return InnerStream.WriteAsync(buffer, cancellationToken); } + + return new ValueTask(WriteAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken), buffer)); } - public override bool CanWrite + private async Task WriteAsync(TAdapter adapter, ReadOnlyMemory buffer) where TAdapter : IReadWriteAdapter { - get + if (Interlocked.Exchange(ref _writeInProgress, 1) == 1) { - return IsAuthenticated && InnerStream.CanWrite; + throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(Write), "write")); } - } - public override int ReadTimeout - { - get + try { - return InnerStream.ReadTimeout; + byte[]? outBuffer = null; + while (!buffer.IsEmpty) + { + int chunkBytes = Math.Min(buffer.Length, MaxWriteDataSize); + int encryptedBytes; + try + { + encryptedBytes = EncryptData(buffer.Slice(0, chunkBytes).Span, ref outBuffer); + } + catch (Exception e) + { + throw new IOException(SR.net_io_encrypt, e); + } + + await adapter.WriteAsync(outBuffer, 0, encryptedBytes).ConfigureAwait(false); + buffer = buffer.Slice(chunkBytes); + } } - set + catch (Exception e) when (!(e is IOException || e is OperationCanceledException)) { - InnerStream.ReadTimeout = value; + throw new IOException(SR.net_io_write, e); + } + finally + { + _writeInProgress = 0; } } - public override int WriteTimeout + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => + TaskToApm.Begin(ReadAsync(buffer, offset, count), asyncCallback, asyncState); + + public override int EndRead(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => + TaskToApm.Begin(WriteAsync(buffer, offset, count), asyncCallback, asyncState); + + public override void EndWrite(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + /// Validates user parameters for all Read/Write methods. + private static void ValidateParameters(byte[] buffer, int offset, int count) { - get + if (buffer == null) { - return InnerStream.WriteTimeout; + throw new ArgumentNullException(nameof(buffer)); } - set + + if (offset < 0) { - InnerStream.WriteTimeout = value; + throw new ArgumentOutOfRangeException(nameof(offset)); } - } - public override long Length - { - get + if (count < 0) { - return InnerStream.Length; + throw new ArgumentOutOfRangeException(nameof(count)); + } + + if (count > buffer.Length - offset) + { + throw new ArgumentOutOfRangeException(nameof(count), SR.net_offset_plus_count); } } - public override long Position + private void ValidateCreateContext( + string package, + NetworkCredential credential, + string servicePrincipalName, + ExtendedProtectionPolicy? policy, + ProtectionLevel protectionLevel, + TokenImpersonationLevel impersonationLevel) { - get + if (policy != null) { - return InnerStream.Position; + // One of these must be set if EP is turned on + if (policy.CustomChannelBinding == null && policy.CustomServiceNames == null) + { + throw new ArgumentException(SR.net_auth_must_specify_extended_protection_scheme, nameof(policy)); + } + + _extendedProtectionPolicy = policy; } - set + else { - throw new NotSupportedException(SR.net_noseek); + _extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never); } - } - public override void SetLength(long value) - { - InnerStream.SetLength(value); + ValidateCreateContext(package, isServer: true, credential, servicePrincipalName, _extendedProtectionPolicy.CustomChannelBinding, protectionLevel, impersonationLevel); } - public override long Seek(long offset, SeekOrigin origin) + private void ValidateCreateContext( + string package, + bool isServer, + NetworkCredential credential, + string? servicePrincipalName, + ChannelBinding? channelBinding, + ProtectionLevel protectionLevel, + TokenImpersonationLevel impersonationLevel) { - throw new NotSupportedException(SR.net_noseek); - } + if (_exception != null && !_canRetryAuthentication) + { + ExceptionDispatchInfo.Throw(_exception); + } - public override void Flush() - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) + if (_context != null && _context.IsValidContext) { -#endif - InnerStream.Flush(); -#if DEBUG + throw new InvalidOperationException(SR.net_auth_reauth); } -#endif - } - public override Task FlushAsync(CancellationToken cancellationToken) - { - return InnerStream.FlushAsync(cancellationToken); - } + if (credential == null) + { + throw new ArgumentNullException(nameof(credential)); + } - protected override void Dispose(bool disposing) - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) + if (servicePrincipalName == null) + { + throw new ArgumentNullException(nameof(servicePrincipalName)); + } + + NegotiateStreamPal.ValidateImpersonationLevel(impersonationLevel); + if (_context != null && IsServer != isServer) + { + throw new InvalidOperationException(SR.net_auth_client_server); + } + + _exception = null; + _remoteOk = false; + _framer = new StreamFramer(); + _framer.WriteHeader.MessageId = FrameHeader.HandshakeId; + + _expectedProtectionLevel = protectionLevel; + _expectedImpersonationLevel = isServer ? impersonationLevel : TokenImpersonationLevel.None; + _writeSequenceNumber = 0; + _readSequenceNumber = 0; + + ContextFlagsPal flags = ContextFlagsPal.Connection; + + // A workaround for the client when talking to Win9x on the server side. + if (protectionLevel == ProtectionLevel.None && !isServer) + { + package = NegotiationInfoClass.NTLM; + } + else if (protectionLevel == ProtectionLevel.EncryptAndSign) + { + flags |= ContextFlagsPal.Confidentiality; + } + else if (protectionLevel == ProtectionLevel.Sign) + { + // Assuming user expects NT4 SP4 and above. + flags |= ContextFlagsPal.ReplayDetect | ContextFlagsPal.SequenceDetect | ContextFlagsPal.InitIntegrity; + } + + if (isServer) { -#endif - try + if (_extendedProtectionPolicy!.PolicyEnforcement == PolicyEnforcement.WhenSupported) { - _negoState.Close(); + flags |= ContextFlagsPal.AllowMissingBindings; } - finally + + if (_extendedProtectionPolicy.PolicyEnforcement != PolicyEnforcement.Never && + _extendedProtectionPolicy.ProtectionScenario == ProtectionScenario.TrustedProxy) { - base.Dispose(disposing); + flags |= ContextFlagsPal.ProxyBindings; } -#if DEBUG } -#endif - } + else + { + // Server side should not request any of these flags. + if (protectionLevel != ProtectionLevel.None) + { + flags |= ContextFlagsPal.MutualAuth; + } + + if (impersonationLevel == TokenImpersonationLevel.Identification) + { + flags |= ContextFlagsPal.InitIdentify; + } + + if (impersonationLevel == TokenImpersonationLevel.Delegation) + { + flags |= ContextFlagsPal.Delegate; + } + } + + _canRetryAuthentication = false; - public override async ValueTask DisposeAsync() - { try { - _negoState.Close(); + _context = new NTAuthentication(isServer, package, credential, servicePrincipalName, flags, channelBinding!); } - finally + catch (Win32Exception e) { - await base.DisposeAsync().ConfigureAwait(false); + throw new AuthenticationException(SR.net_auth_SSPI, e); } } - public override int Read(byte[] buffer, int offset, int count) + private void SetFailed(Exception e) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) + if (!(_exception is ObjectDisposedException)) { -#endif - _negoState.CheckThrow(true); + _exception = e; + } - if (!_negoState.CanGetSecureStream) - { - return InnerStream.Read(buffer, offset, count); - } + _context?.CloseContext(); + } + + private void ThrowIfFailed(bool authSuccessCheck) + { + if (_exception != null) + { + ExceptionDispatchInfo.Throw(_exception); + } - return ProcessRead(buffer, offset, count, null); -#if DEBUG + if (authSuccessCheck && !IsAuthenticatedCore) + { + throw new InvalidOperationException(SR.net_auth_noauth); } -#endif } - public override void Write(byte[] buffer, int offset, int count) + private async Task AuthenticateAsync(TAdapter adapter, [CallerMemberName] string? callerName = null) where TAdapter : IReadWriteAdapter { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) - { -#endif - _negoState.CheckThrow(true); + Debug.Assert(_context != null); - if (!_negoState.CanGetSecureStream) - { - InnerStream.Write(buffer, offset, count); - return; - } + ThrowIfFailed(authSuccessCheck: false); + if (Interlocked.Exchange(ref _authInProgress, 1) == 1) + { + throw new InvalidOperationException(SR.Format(SR.net_io_invalidnestedcall, callerName, "authenticate")); + } - ProcessWrite(buffer, offset, count, null); -#if DEBUG + try + { + await (_context.IsServer ? + ReceiveBlobAsync(adapter) : // server should listen for a client blob + SendBlobAsync(adapter, message: null)).ConfigureAwait(false); // client should send the first blob + } + catch (Exception e) + { + SetFailed(e); + throw; + } + finally + { + _authInProgress = 0; } -#endif } - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) + private bool CheckSpn() { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + Debug.Assert(_context != null); + + if (_context.IsKerberos || + _extendedProtectionPolicy!.PolicyEnforcement == PolicyEnforcement.Never || + _extendedProtectionPolicy.CustomServiceNames == null) { -#endif - _negoState.CheckThrow(true); + return true; + } - if (!_negoState.CanGetSecureStream) - { - return TaskToApm.Begin(InnerStream.ReadAsync(buffer, offset, count), asyncCallback, asyncState); - } + string? clientSpn = _context.ClientSpecifiedSpn; - BufferAsyncResult bufferResult = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback); - AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferResult); - ProcessRead(buffer, offset, count, asyncRequest); - return bufferResult; -#if DEBUG + if (string.IsNullOrEmpty(clientSpn)) + { + return _extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.WhenSupported; } -#endif + + return _extendedProtectionPolicy.CustomServiceNames.Contains(clientSpn); } - public override int EndRead(IAsyncResult asyncResult) + // Client authentication starts here, but server also loops through this method. + private async Task SendBlobAsync(TAdapter adapter, byte[]? message) where TAdapter : IReadWriteAdapter { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) + Debug.Assert(_context != null); + + Exception? exception = null; + if (message != s_emptyMessage) + { + message = GetOutgoingBlob(message, ref exception); + } + + if (exception != null) { -#endif - _negoState.CheckThrow(true); + // Signal remote side on a failed attempt. + await SendAuthResetSignalAndThrowAsync(adapter, message!, exception).ConfigureAwait(false); + Debug.Fail("Unreachable"); + } - if (!_negoState.CanGetSecureStream) + if (HandshakeComplete) + { + if (_context.IsServer && !CheckSpn()) { - return TaskToApm.End(asyncResult); - } + exception = new AuthenticationException(SR.net_auth_bad_client_creds_or_target_mismatch); + int statusCode = ERROR_TRUST_FAILURE; + message = new byte[sizeof(long)]; + for (int i = message.Length - 1; i >= 0; --i) + { + message[i] = (byte)(statusCode & 0xFF); + statusCode = (int)((uint)statusCode >> 8); + } - if (asyncResult == null) + await SendAuthResetSignalAndThrowAsync(adapter, message, exception).ConfigureAwait(false); + Debug.Fail("Unreachable"); + } + + if (PrivateImpersonationLevel < _expectedImpersonationLevel) { - throw new ArgumentNullException(nameof(asyncResult)); + exception = new AuthenticationException(SR.Format(SR.net_auth_context_expectation, _expectedImpersonationLevel.ToString(), PrivateImpersonationLevel.ToString())); + int statusCode = ERROR_TRUST_FAILURE; + message = new byte[sizeof(long)]; + + for (int i = message.Length - 1; i >= 0; --i) + { + message[i] = (byte)(statusCode & 0xFF); + statusCode = (int)((uint)statusCode >> 8); + } + + await SendAuthResetSignalAndThrowAsync(adapter, message, exception).ConfigureAwait(false); + Debug.Fail("Unreachable"); } - BufferAsyncResult? bufferResult = asyncResult as BufferAsyncResult; - if (bufferResult == null) + ProtectionLevel result = _context.IsConfidentialityFlag ? ProtectionLevel.EncryptAndSign : _context.IsIntegrityFlag ? ProtectionLevel.Sign : ProtectionLevel.None; + + if (result < _expectedProtectionLevel) { - throw new ArgumentException(SR.Format(SR.net_io_async_result, asyncResult.GetType().FullName), nameof(asyncResult)); + exception = new AuthenticationException(SR.Format(SR.net_auth_context_expectation, result.ToString(), _expectedProtectionLevel.ToString())); + int statusCode = ERROR_TRUST_FAILURE; + message = new byte[sizeof(long)]; + + for (int i = message.Length - 1; i >= 0; --i) + { + message[i] = (byte)(statusCode & 0xFF); + statusCode = (int)((uint)statusCode >> 8); + } + + await SendAuthResetSignalAndThrowAsync(adapter, message, exception).ConfigureAwait(false); + Debug.Fail("Unreachable"); } - if (Interlocked.Exchange(ref _NestedRead, 0) == 0) + // Signal remote party that we are done + _framer!.WriteHeader.MessageId = FrameHeader.HandshakeDoneId; + if (_context.IsServer) { - throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndRead")); + // Server may complete now because client SSPI would not complain at this point. + _remoteOk = true; + + // However the client will wait for server to send this ACK + // Force signaling server OK to the client + message ??= s_emptyMessage; } + } + else if (message == null || message == s_emptyMessage) + { + throw new InternalException(); + } + + if (message != null) + { + //even if we are completed, there could be a blob for sending. + await _framer!.WriteMessageAsync(adapter, message).ConfigureAwait(false); + } - // No "artificial" timeouts implemented so far, InnerStream controls timeout. - bufferResult.InternalWaitForCompletion(); + if (HandshakeComplete && _remoteOk) + { + // We are done with success. + return; + } + + await ReceiveBlobAsync(adapter).ConfigureAwait(false); + } + + // Server authentication starts here, but client also loops through this method. + private async Task ReceiveBlobAsync(TAdapter adapter) where TAdapter : IReadWriteAdapter + { + Debug.Assert(_framer != null); - if (bufferResult.Result is Exception e) + byte[]? message = await _framer.ReadMessageAsync(adapter).ConfigureAwait(false); + if (message == null) + { + // This is an EOF otherwise we would get at least *empty* message but not a null one. + throw new AuthenticationException(SR.net_auth_eof); + } + + // Process Header information. + if (_framer.ReadHeader.MessageId == FrameHeader.HandshakeErrId) + { + if (message.Length >= sizeof(long)) { - if (e is IOException) + // Try to recover remote win32 Exception. + long error = 0; + for (int i = 0; i < 8; ++i) { - ExceptionDispatchInfo.Throw(e); + error = (error << 8) + message[i]; } - throw new IOException(SR.net_io_read, e); + ThrowCredentialException(error); } - return bufferResult.Int32Result; -#if DEBUG + throw new AuthenticationException(SR.net_auth_alert); } -#endif - } - // - // - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) - { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + + if (_framer.ReadHeader.MessageId == FrameHeader.HandshakeDoneId) + { + _remoteOk = true; + } + else if (_framer.ReadHeader.MessageId != FrameHeader.HandshakeId) { -#endif - _negoState.CheckThrow(true); + throw new AuthenticationException(SR.Format(SR.net_io_header_id, nameof(FrameHeader.MessageId), _framer.ReadHeader.MessageId, FrameHeader.HandshakeId)); + } - if (!_negoState.CanGetSecureStream) + // If we are done don't go into send. + if (HandshakeComplete) + { + if (!_remoteOk) { - return TaskToApm.Begin(InnerStream.WriteAsync(buffer, offset, count), asyncCallback, asyncState); + throw new AuthenticationException(SR.Format(SR.net_io_header_id, nameof(FrameHeader.MessageId), _framer.ReadHeader.MessageId, FrameHeader.HandshakeDoneId)); } - BufferAsyncResult bufferResult = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback); - AsyncProtocolRequest asyncRequest = new AsyncProtocolRequest(bufferResult); + return; + } + + // Not yet done, get a new blob and send it if any. + await SendBlobAsync(adapter, message).ConfigureAwait(false); + } + + // This is to reset auth state on the remote side. + // If this write succeeds we will allow auth retrying. + private async Task SendAuthResetSignalAndThrowAsync(TAdapter adapter, byte[] message, Exception exception) where TAdapter : IReadWriteAdapter + { + _framer!.WriteHeader.MessageId = FrameHeader.HandshakeErrId; + + if (IsLogonDeniedException(exception)) + { + exception = new InvalidCredentialException(IsServer ? SR.net_auth_bad_client_creds : SR.net_auth_bad_client_creds_or_target_mismatch, exception); + } - ProcessWrite(buffer, offset, count, asyncRequest); - return bufferResult; -#if DEBUG + if (!(exception is AuthenticationException)) + { + exception = new AuthenticationException(SR.net_auth_SSPI, exception); } -#endif + + await _framer.WriteMessageAsync(adapter, message).ConfigureAwait(false); + + _canRetryAuthentication = true; + ExceptionDispatchInfo.Throw(exception); } - public override void EndWrite(IAsyncResult asyncResult) + private static bool IsError(SecurityStatusPal status) => + (int)status.ErrorCode >= (int)SecurityStatusPalErrorCode.OutOfMemory; + + private unsafe byte[]? GetOutgoingBlob(byte[]? incomingBlob, ref Exception? e) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) + Debug.Assert(_context != null); + + byte[]? message = _context.GetOutgoingBlob(incomingBlob, false, out SecurityStatusPal statusCode); + + if (IsError(statusCode)) { -#endif - _negoState.CheckThrow(true); + e = NegotiateStreamPal.CreateExceptionFromError(statusCode); + uint error = (uint)e.HResult; - if (!_negoState.CanGetSecureStream) + message = new byte[sizeof(long)]; + for (int i = message.Length - 1; i >= 0; --i) { - TaskToApm.End(asyncResult); - return; + message[i] = (byte)(error & 0xFF); + error >>= 8; } + } - if (asyncResult == null) - { - throw new ArgumentNullException(nameof(asyncResult)); - } + if (message != null && message.Length == 0) + { + message = s_emptyMessage; + } - BufferAsyncResult? bufferResult = asyncResult as BufferAsyncResult; - if (bufferResult == null) - { - throw new ArgumentException(SR.Format(SR.net_io_async_result, asyncResult.GetType().FullName), nameof(asyncResult)); - } + return message; + } - if (Interlocked.Exchange(ref _NestedWrite, 0) == 0) - { - throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndWrite")); - } + private int EncryptData(ReadOnlySpan buffer, [NotNull] ref byte[]? outBuffer) + { + Debug.Assert(_context != null); + ThrowIfFailed(authSuccessCheck: true); - // No "artificial" timeouts implemented so far, InnerStream controls timeout. - bufferResult.InternalWaitForCompletion(); + // SSPI seems to ignore this sequence number. + ++_writeSequenceNumber; + return _context.Encrypt(buffer, ref outBuffer, _writeSequenceNumber); + } - if (bufferResult.Result is Exception e) - { - if (e is IOException) - { - ExceptionDispatchInfo.Throw(e); - } + private int DecryptData(byte[] buffer, int offset, int count, out int newOffset) + { + Debug.Assert(_context != null); + ThrowIfFailed(authSuccessCheck: true); - throw new IOException(SR.net_io_write, e); - } -#if DEBUG - } -#endif + // SSPI seems to ignore this sequence number. + ++_readSequenceNumber; + return _context.Decrypt(buffer, offset, count, out newOffset, _readSequenceNumber); + } + + private static void ThrowCredentialException(long error) + { + var e = new Win32Exception((int)error); + throw e.NativeErrorCode switch + { + (int)SecurityStatusPalErrorCode.LogonDenied => new InvalidCredentialException(SR.net_auth_bad_client_creds, e), + ERROR_TRUST_FAILURE => new AuthenticationException(SR.net_auth_context_expectation_remote, e), + _ => new AuthenticationException(SR.net_auth_alert, e) + }; } + + private static bool IsLogonDeniedException(Exception exception) => + exception is Win32Exception win32exception && + win32exception.NativeErrorCode == (int)SecurityStatusPalErrorCode.LogonDenied; } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs index a03fe69151f6e..51d69634b36e5 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; @@ -85,12 +86,10 @@ internal static void ValidateImpersonationLevel(TokenImpersonationLevel imperson internal static int Encrypt( SafeDeleteContext securityContext, - byte[] buffer, - int offset, - int count, + ReadOnlySpan buffer, bool isConfidential, bool isNtlm, - ref byte[]? output, + [NotNull] ref byte[]? output, uint sequenceNumber) { SecPkgContext_Sizes sizes = default; @@ -101,9 +100,9 @@ internal static void ValidateImpersonationLevel(TokenImpersonationLevel imperson { int maxCount = checked(int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer); - if (count > maxCount || count < 0) + if (buffer.Length > maxCount) { - throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount)); + throw new ArgumentOutOfRangeException(nameof(buffer.Length), SR.Format(SR.net_io_out_range, maxCount)); } } catch (Exception e) when (!ExceptionCheck.IsFatal(e)) @@ -112,21 +111,21 @@ internal static void ValidateImpersonationLevel(TokenImpersonationLevel imperson throw; } - int resultSize = count + sizes.cbSecurityTrailer + sizes.cbBlockSize; + int resultSize = buffer.Length + sizes.cbSecurityTrailer + sizes.cbBlockSize; if (output == null || output.Length < resultSize + 4) { output = new byte[resultSize + 4]; } // Make a copy of user data for in-place encryption. - Buffer.BlockCopy(buffer, offset, output, 4 + sizes.cbSecurityTrailer, count); + buffer.CopyTo(output.AsSpan(4 + sizes.cbSecurityTrailer)); // Prepare buffers TOKEN(signature), DATA and Padding. ThreeSecurityBuffers buffers = default; var securityBuffer = MemoryMarshal.CreateSpan(ref buffers._item0, 3); securityBuffer[0] = new SecurityBuffer(output, 4, sizes.cbSecurityTrailer, SecurityBufferType.SECBUFFER_TOKEN); - securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, count, SecurityBufferType.SECBUFFER_DATA); - securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + count, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING); + securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, buffer.Length, SecurityBufferType.SECBUFFER_DATA); + securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + buffer.Length, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING); int errorCode; if (isConfidential) @@ -160,7 +159,7 @@ internal static void ValidateImpersonationLevel(TokenImpersonationLevel imperson } resultSize += securityBuffer[1].size; - if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.cbSecurityTrailer))) + if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (buffer.Length + sizes.cbSecurityTrailer))) { Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/ReadWriteAdapter.cs b/src/libraries/System.Net.Security/src/System/Net/Security/ReadWriteAdapter.cs new file mode 100644 index 0000000000000..497baeb4ccf6e --- /dev/null +++ b/src/libraries/System.Net.Security/src/System/Net/Security/ReadWriteAdapter.cs @@ -0,0 +1,89 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Security +{ + internal interface IReadWriteAdapter + { + ValueTask ReadAsync(Memory buffer); + + ValueTask WriteAsync(byte[] buffer, int offset, int count); + + Task WaitAsync(TaskCompletionSource waiter); + + CancellationToken CancellationToken { get; } + + public async ValueTask ReadAllAsync(Memory buffer) + { + int length = buffer.Length; + + do + { + int bytes = await ReadAsync(buffer).ConfigureAwait(false); + if (bytes == 0) + { + if (!buffer.IsEmpty) + { + throw new IOException(SR.net_io_eof); + } + break; + } + + buffer = buffer.Slice(bytes); + } + while (!buffer.IsEmpty); + + return length; + } + } + + internal readonly struct AsyncReadWriteAdapter : IReadWriteAdapter + { + private readonly Stream _stream; + + public AsyncReadWriteAdapter(Stream stream, CancellationToken cancellationToken) + { + _stream = stream; + CancellationToken = cancellationToken; + } + + public ValueTask ReadAsync(Memory buffer) => + _stream.ReadAsync(buffer, CancellationToken); + + public ValueTask WriteAsync(byte[] buffer, int offset, int count) => + _stream.WriteAsync(new ReadOnlyMemory(buffer, offset, count), CancellationToken); + + public Task WaitAsync(TaskCompletionSource waiter) => waiter.Task; + + public CancellationToken CancellationToken { get; } + } + + internal readonly struct SyncReadWriteAdapter : IReadWriteAdapter + { + private readonly Stream _stream; + + public SyncReadWriteAdapter(Stream stream) => _stream = stream; + + public ValueTask ReadAsync(Memory buffer) => + new ValueTask(_stream.Read(buffer.Span)); + + public ValueTask WriteAsync(byte[] buffer, int offset, int count) + { + _stream.Write(buffer, offset, count); + return default; + } + + public Task WaitAsync(TaskCompletionSource waiter) + { + waiter.Task.GetAwaiter().GetResult(); + return Task.CompletedTask; + } + + public CancellationToken CancellationToken => default; + } +} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs index 82aab9fe95196..b770ef26fb78a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs @@ -625,7 +625,7 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) // // Acquire Server Side Certificate information and set it on the class. // - private bool AcquireServerCredentials(ref byte[]? thumbPrint, ReadOnlySpan clientHello) + private bool AcquireServerCredentials(ref byte[]? thumbPrint) { if (NetEventSource.IsEnabled) NetEventSource.Enter(this); @@ -639,13 +639,13 @@ private bool AcquireServerCredentials(ref byte[]? thumbPrint, ReadOnlySpan // with .NET Framework), and if neither is set we fall back to using ServerCertificate. if (_sslAuthenticationOptions.ServerCertSelectionDelegate != null) { - string? serverIdentity = SniHelper.GetServerName(clientHello); - localCertificate = _sslAuthenticationOptions.ServerCertSelectionDelegate(serverIdentity); - + localCertificate = _sslAuthenticationOptions.ServerCertSelectionDelegate(_sslAuthenticationOptions.TargetHost); if (localCertificate == null) { throw new AuthenticationException(SR.net_ssl_io_no_server_cert); } + if (NetEventSource.IsEnabled) + NetEventSource.Info(this, "Use delegate selected Cert"); } else if (_sslAuthenticationOptions.CertSelectionDelegate != null) { @@ -784,7 +784,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte if (_refreshCredentialNeeded) { cachedCreds = _sslAuthenticationOptions.IsServer - ? AcquireServerCredentials(ref thumbPrint, inputBuffer) + ? AcquireServerCredentials(ref thumbPrint) : AcquireClientCredentials(ref thumbPrint); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs index ffbf730e7d971..db682188997e1 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs @@ -26,13 +26,13 @@ internal class SniHelper // opaque fragment[SSLPlaintext.length]; // } SSLPlaintext; const int ContentTypeOffset = 0; - const int ProtocolVersionOffset = ContentTypeOffset + sizeof(ContentType); + const int ProtocolVersionOffset = ContentTypeOffset + sizeof(TlsContentType); const int LengthOffset = ProtocolVersionOffset + ProtocolVersionSize; const int HandshakeOffset = LengthOffset + sizeof(ushort); // SSL v2's ContentType has 0x80 bit set. // We do not care about SSL v2 here because it does not support client hello extensions - if (sslPlainText.Length < HandshakeOffset || (ContentType)sslPlainText[ContentTypeOffset] != ContentType.Handshake) + if (sslPlainText.Length < HandshakeOffset || (TlsContentType)sslPlainText[ContentTypeOffset] != TlsContentType.Handshake) { return null; } @@ -62,10 +62,10 @@ internal class SniHelper // } body; // } Handshake; const int HandshakeTypeOffset = 0; - const int ClientHelloLengthOffset = HandshakeTypeOffset + sizeof(HandshakeType); + const int ClientHelloLengthOffset = HandshakeTypeOffset + sizeof(TlsHandshakeType); const int ClientHelloOffset = ClientHelloLengthOffset + UInt24Size; - if (sslHandshake.Length < ClientHelloOffset || (HandshakeType)sslHandshake[HandshakeTypeOffset] != HandshakeType.ClientHello) + if (sslHandshake.Length < ClientHelloOffset || (TlsHandshakeType)sslHandshake[HandshakeTypeOffset] != TlsHandshakeType.ClientHello) { return null; } @@ -363,16 +363,6 @@ private static Encoding CreateEncoding() return Encoding.GetEncoding("utf-8", new EncoderExceptionFallback(), new DecoderExceptionFallback()); } - private enum ContentType : byte - { - Handshake = 0x16 - } - - private enum HandshakeType : byte - { - ClientHello = 0x01 - } - private enum ExtensionType : ushort { ServerName = 0x00 diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.Adapters.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.Adapters.cs deleted file mode 100644 index 4995f3fd09bf0..0000000000000 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.Adapters.cs +++ /dev/null @@ -1,63 +0,0 @@ -// 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.Threading; -using System.Threading.Tasks; - -namespace System.Net.Security -{ - // This contains adapters to allow a single code path for sync/async logic - public partial class SslStream - { - private interface ISslIOAdapter - { - ValueTask ReadAsync(Memory buffer); - ValueTask WriteAsync(byte[] buffer, int offset, int count); - Task WaitAsync(TaskCompletionSource waiter); - CancellationToken CancellationToken { get; } - } - - private readonly struct AsyncSslIOAdapter : ISslIOAdapter - { - private readonly SslStream _sslStream; - private readonly CancellationToken _cancellationToken; - - public AsyncSslIOAdapter(SslStream sslStream, CancellationToken cancellationToken) - { - _cancellationToken = cancellationToken; - _sslStream = sslStream; - } - - public ValueTask ReadAsync(Memory buffer) => _sslStream.InnerStream.ReadAsync(buffer, _cancellationToken); - - public ValueTask WriteAsync(byte[] buffer, int offset, int count) => _sslStream.InnerStream.WriteAsync(new ReadOnlyMemory(buffer, offset, count), _cancellationToken); - - public Task WaitAsync(TaskCompletionSource waiter) => waiter.Task; - - public CancellationToken CancellationToken => _cancellationToken; - } - - private readonly struct SyncSslIOAdapter : ISslIOAdapter - { - private readonly SslStream _sslStream; - - public SyncSslIOAdapter(SslStream sslStream) => _sslStream = sslStream; - - public ValueTask ReadAsync(Memory buffer) => new ValueTask(_sslStream.InnerStream.Read(buffer.Span)); - - public ValueTask WriteAsync(byte[] buffer, int offset, int count) - { - _sslStream.InnerStream.Write(buffer, offset, count); - return default; - } - - public Task WaitAsync(TaskCompletionSource waiter) - { - waiter.Task.Wait(); - return Task.CompletedTask; - } - - public CancellationToken CancellationToken => default; - } - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs index 600163be36290..7b9dd62870c4e 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs @@ -24,24 +24,18 @@ public partial class SslStream private enum Framing { - Unknown = 0, - BeforeSSL3, - SinceSSL3, - Unified, - Invalid + Unknown = 0, // Initial before any frame is processd. + BeforeSSL3, // SSlv2 + SinceSSL3, // SSlv3 & TLS + Unified, // Intermediate on first frame until response is processes. + Invalid // Somthing is wrong. } // This is set on the first packet to figure out the framing style. private Framing _framing = Framing.Unknown; - // SSL3/TLS protocol frames definitions. - private enum FrameType : byte - { - ChangeCipherSpec = 20, - Alert = 21, - Handshake = 22, - AppData = 23 - } + private TlsAlertDescription _lastAlertDescription; + private TlsFrameHandshakeInfo _lastFrame; private readonly object _handshakeLock = new object(); private volatile TaskCompletionSource? _handshakeWaiter; @@ -202,11 +196,11 @@ private SecurityStatusPal PrivateDecryptData(byte[]? buffer, ref int offset, ref if (isAsync) { - result = ForceAuthenticationAsync(new AsyncSslIOAdapter(this, cancellationToken), _context!.IsServer, null, isApm); + result = ForceAuthenticationAsync(new AsyncReadWriteAdapter(InnerStream, cancellationToken), _context!.IsServer, null, isApm); } else { - ForceAuthenticationAsync(new SyncSslIOAdapter(this), _context!.IsServer, null).GetAwaiter().GetResult(); + ForceAuthenticationAsync(new SyncReadWriteAdapter(InnerStream), _context!.IsServer, null).GetAwaiter().GetResult(); result = null; } @@ -217,7 +211,7 @@ private SecurityStatusPal PrivateDecryptData(byte[]? buffer, ref int offset, ref // This is used to reply on re-handshake when received SEC_I_RENEGOTIATE on Read(). // private async Task ReplyOnReAuthenticationAsync(TIOAdapter adapter, byte[]? buffer) - where TIOAdapter : ISslIOAdapter + where TIOAdapter : IReadWriteAdapter { try { @@ -232,7 +226,7 @@ private async Task ReplyOnReAuthenticationAsync(TIOAdapter adapter, // reAuthenticationData is only used on Windows in case of renegotiation. private async Task ForceAuthenticationAsync(TIOAdapter adapter, bool receiveFirst, byte[]? reAuthenticationData, bool isApm = false) - where TIOAdapter : ISslIOAdapter + where TIOAdapter : IReadWriteAdapter { ProtocolToken message; bool handshakeCompleted = false; @@ -274,7 +268,6 @@ private async Task ForceAuthenticationAsync(TIOAdapter adapter, bool { // get ready to receive first frame _handshakeBuffer = new ArrayBuffer(InitialHandshakeBufferSize); - _framing = Framing.Unknown; } while (!handshakeCompleted) @@ -288,6 +281,19 @@ private async Task ForceAuthenticationAsync(TIOAdapter adapter, bool if (message.Failed) { + if (_lastFrame.Header.Type == TlsContentType.Handshake && message.Size == 0) + { + // If we failed without OS sending out alert, inject one here to be consistent across platforms. + byte[] alert = TlsFrameHelper.CreateAlertFrame(_lastFrame.Header.Version, TlsAlertDescription.ProtocolVersion); + await adapter.WriteAsync(alert, 0, alert.Length).ConfigureAwait(false); + } + else if (_lastFrame.Header.Type == TlsContentType.Alert && _lastAlertDescription != TlsAlertDescription.CloseNotify && + message.Status.ErrorCode == SecurityStatusPalErrorCode.IllegalMessage) + { + // Improve generic message and show details if we failed because of TLS Alert. + throw new AuthenticationException(SR.Format(SR.net_auth_tls_alert, _lastAlertDescription.ToString()), message.GetException()); + } + throw new AuthenticationException(SR.net_auth_SSPI, message.GetException()); } else if (message.Status.ErrorCode == SecurityStatusPalErrorCode.OK) @@ -333,7 +339,7 @@ private async Task ForceAuthenticationAsync(TIOAdapter adapter, bool } private async ValueTask ReceiveBlobAsync(TIOAdapter adapter) - where TIOAdapter : ISslIOAdapter + where TIOAdapter : IReadWriteAdapter { int readBytes = await FillHandshakeBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false); if (readBytes == 0) @@ -346,17 +352,49 @@ private async ValueTask ReceiveBlobAsync(TIOAdapter a _framing = DetectFraming(_handshakeBuffer.ActiveReadOnlySpan); } - int frameSize = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan); - if (frameSize < 0) + if (_framing != Framing.SinceSSL3) + { +#pragma warning disable 0618 + _lastFrame.Header.Version = SslProtocols.Ssl2; +#pragma warning restore 0618 + _lastFrame.Header.Length = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan) - TlsFrameHelper.HeaderSize; + } + else + { + TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame.Header); + } + + if (_lastFrame.Header.Length < 0) { throw new IOException(SR.net_frame_read_size); } + // Header length is content only so we must add header size as well. + int frameSize = _lastFrame.Header.Length + TlsFrameHelper.HeaderSize; if (_handshakeBuffer.ActiveLength < frameSize) { await FillHandshakeBufferAsync(adapter, frameSize).ConfigureAwait(false); } + // At this point, we have at least one TLS frame. + if (_lastFrame.Header.Type == TlsContentType.Alert) + { + TlsAlertLevel level = 0; + if (TlsFrameHelper.TryGetAlertInfo(_handshakeBuffer.ActiveReadOnlySpan, ref level, ref _lastAlertDescription)) + { + if (NetEventSource.IsEnabled && _lastAlertDescription != TlsAlertDescription.CloseNotify) NetEventSource.Fail(this, $"Received TLS alert {_lastAlertDescription}"); + } + } + else if (_lastFrame.Header.Type == TlsContentType.Handshake) + { + if (_handshakeBuffer.ActiveReadOnlySpan[TlsFrameHelper.HeaderSize] == (byte)TlsHandshakeType.ClientHello && + _sslAuthenticationOptions!.ServerCertSelectionDelegate != null) + { + // Process SNI from Client Hello message + TlsFrameHelper.TryGetHandshakeInfo(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame); + _sslAuthenticationOptions.TargetHost = _lastFrame.TargetName; + } + } return ProcessBlob(frameSize); } @@ -371,24 +409,28 @@ private ProtocolToken ProcessBlob(int frameSize) // ActiveSpan will exclude the "discarded" data. _handshakeBuffer.Discard(frameSize); - // Often more TLS messages fit into same packet. Get as many complete frames as we can. - while (_handshakeBuffer.ActiveLength > SecureChannel.ReadHeaderSize) + if (_framing == Framing.SinceSSL3) { - ReadOnlySpan remainingData = _handshakeBuffer.ActiveReadOnlySpan; - if (remainingData[0] >= (int)FrameType.AppData) + // Often more TLS messages fit into same packet. Get as many complete frames as we can. + while (_handshakeBuffer.ActiveLength > TlsFrameHelper.HeaderSize) { - break; - } + TlsFrameHeader nextHeader = default; + + if (!TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref nextHeader)) + { + break; + } + + frameSize = nextHeader.Length + TlsFrameHelper.HeaderSize; + if (nextHeader.Type == TlsContentType.AppData || frameSize > _handshakeBuffer.ActiveLength) + { + // We don't have full frame left or we already have app data which needs to be processed by decrypt. + break; + } - frameSize = GetFrameSize(remainingData); - if (_handshakeBuffer.ActiveLength >= frameSize) - { chunkSize += frameSize; _handshakeBuffer.Discard(frameSize); - continue; } - - break; } return _context!.NextMessage(availableData.Slice(0, chunkSize)); @@ -447,7 +489,7 @@ private bool CompleteHandshake(ref ProtocolToken? alertToken) } private async ValueTask WriteAsyncChunked(TIOAdapter writeAdapter, ReadOnlyMemory buffer) - where TIOAdapter : struct, ISslIOAdapter + where TIOAdapter : struct, IReadWriteAdapter { do { @@ -458,7 +500,7 @@ private async ValueTask WriteAsyncChunked(TIOAdapter writeAdapter, R } private ValueTask WriteSingleChunk(TIOAdapter writeAdapter, ReadOnlyMemory buffer) - where TIOAdapter : struct, ISslIOAdapter + where TIOAdapter : struct, IReadWriteAdapter { byte[] rentedBuffer = ArrayPool.Shared.Rent(buffer.Length + FrameOverhead); byte[] outBuffer = rentedBuffer; @@ -604,7 +646,7 @@ private void ReturnReadBufferIfEmpty() } private async ValueTask ReadAsyncInternal(TIOAdapter adapter, Memory buffer) - where TIOAdapter : ISslIOAdapter + where TIOAdapter : IReadWriteAdapter { if (Interlocked.Exchange(ref _nestedRead, 1) == 1) { @@ -751,7 +793,7 @@ private async ValueTask ReadAsyncInternal(TIOAdapter adapter, M // If we have enough data, it returns synchronously. If not, it will try to read // remaining bytes from given stream. private ValueTask FillHandshakeBufferAsync(TIOAdapter adapter, int minSize) - where TIOAdapter : ISslIOAdapter + where TIOAdapter : IReadWriteAdapter { if (_handshakeBuffer.ActiveLength >= minSize) { @@ -801,7 +843,7 @@ async ValueTask InternalFillHandshakeBufferAsync(TIOAdapter adap, ValueTas } private async ValueTask FillBufferAsync(TIOAdapter adapter, int numBytesRequired) - where TIOAdapter : ISslIOAdapter + where TIOAdapter : IReadWriteAdapter { Debug.Assert(_internalBufferCount > 0); Debug.Assert(_internalBufferCount < numBytesRequired); @@ -819,7 +861,7 @@ private async ValueTask FillBufferAsync(TIOAdapter adapter, int numB } private async ValueTask WriteAsyncInternal(TIOAdapter writeAdapter, ReadOnlyMemory buffer) - where TIOAdapter : struct, ISslIOAdapter + where TIOAdapter : struct, IReadWriteAdapter { ThrowIfExceptionalOrNotAuthenticatedOrShutdown(); @@ -913,6 +955,7 @@ private static byte[] EnsureBufferSize(byte[] buffer, int copyCount, int size) Buffer.BlockCopy(saved, 0, buffer, 0, copyCount); } } + return buffer; } @@ -1003,8 +1046,8 @@ private Framing DetectFraming(ReadOnlySpan bytes) } // If the first byte is SSL3 HandShake, then check if we have a SSLv3 Type3 client hello. - if (bytes[0] == (byte)FrameType.Handshake || bytes[0] == (byte)FrameType.AppData - || bytes[0] == (byte)FrameType.Alert) + if (bytes[0] == (byte)TlsContentType.Handshake || bytes[0] == (byte)TlsContentType.AppData + || bytes[0] == (byte)TlsContentType.Alert) { if (bytes.Length < 3) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs index 73f4417dacc21..f3638799d7732 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs @@ -304,8 +304,13 @@ public virtual void AuthenticateAsClient(string targetHost, X509CertificateColle AuthenticateAsClient(options); } - private void AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions) + public void AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions) { + if (sslClientAuthenticationOptions == null) + { + throw new ArgumentNullException(nameof(sslClientAuthenticationOptions)); + } + SetAndVerifyValidationCallback(sslClientAuthenticationOptions.RemoteCertificateValidationCallback); SetAndVerifySelectionCallback(sslClientAuthenticationOptions.LocalCertificateSelectionCallback); @@ -337,8 +342,13 @@ public virtual void AuthenticateAsServer(X509Certificate serverCertificate, bool AuthenticateAsServer(options); } - private void AuthenticateAsServer(SslServerAuthenticationOptions sslServerAuthenticationOptions) + public void AuthenticateAsServer(SslServerAuthenticationOptions sslServerAuthenticationOptions) { + if (sslServerAuthenticationOptions == null) + { + throw new ArgumentNullException(nameof(sslServerAuthenticationOptions)); + } + SetAndVerifyValidationCallback(sslServerAuthenticationOptions.RemoteCertificateValidationCallback); ValidateCreateContext(CreateAuthenticationOptions(sslServerAuthenticationOptions)); @@ -367,6 +377,11 @@ public virtual Task AuthenticateAsClientAsync(string targetHost, X509Certificate public Task AuthenticateAsClientAsync(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken = default) { + if (sslClientAuthenticationOptions == null) + { + throw new ArgumentNullException(nameof(sslClientAuthenticationOptions)); + } + SetAndVerifyValidationCallback(sslClientAuthenticationOptions.RemoteCertificateValidationCallback); SetAndVerifySelectionCallback(sslClientAuthenticationOptions.LocalCertificateSelectionCallback); @@ -417,6 +432,11 @@ public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate, public Task AuthenticateAsServerAsync(SslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken = default) { + if (sslServerAuthenticationOptions == null) + { + throw new ArgumentNullException(nameof(sslServerAuthenticationOptions)); + } + SetAndVerifyValidationCallback(sslServerAuthenticationOptions.RemoteCertificateValidationCallback); ValidateCreateContext(CreateAuthenticationOptions(sslServerAuthenticationOptions)); @@ -742,8 +762,7 @@ public override int Read(byte[] buffer, int offset, int count) { ThrowIfExceptionalOrNotAuthenticated(); ValidateParameters(buffer, offset, count); - SyncSslIOAdapter reader = new SyncSslIOAdapter(this); - ValueTask vt = ReadAsyncInternal(reader, new Memory(buffer, offset, count)); + ValueTask vt = ReadAsyncInternal(new SyncReadWriteAdapter(InnerStream), new Memory(buffer, offset, count)); Debug.Assert(vt.IsCompleted, "Sync operation must have completed synchronously"); return vt.GetAwaiter().GetResult(); } @@ -755,8 +774,7 @@ public override void Write(byte[] buffer, int offset, int count) ThrowIfExceptionalOrNotAuthenticated(); ValidateParameters(buffer, offset, count); - SyncSslIOAdapter writeAdapter = new SyncSslIOAdapter(this); - ValueTask vt = WriteAsyncInternal(writeAdapter, new ReadOnlyMemory(buffer, offset, count)); + ValueTask vt = WriteAsyncInternal(new SyncReadWriteAdapter(InnerStream), new ReadOnlyMemory(buffer, offset, count)); Debug.Assert(vt.IsCompleted, "Sync operation must have completed synchronously"); vt.GetAwaiter().GetResult(); } @@ -792,26 +810,23 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); } - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { ThrowIfExceptionalOrNotAuthenticated(); - AsyncSslIOAdapter writeAdapter = new AsyncSslIOAdapter(this, cancellationToken); - return WriteAsyncInternal(writeAdapter, buffer); + return WriteAsyncInternal(new AsyncReadWriteAdapter(InnerStream, cancellationToken), buffer); } public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { ThrowIfExceptionalOrNotAuthenticated(); ValidateParameters(buffer, offset, count); - AsyncSslIOAdapter read = new AsyncSslIOAdapter(this, cancellationToken); - return ReadAsyncInternal(read, new Memory(buffer, offset, count)).AsTask(); + return ReadAsyncInternal(new AsyncReadWriteAdapter(InnerStream, cancellationToken), new Memory(buffer, offset, count)).AsTask(); } public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { ThrowIfExceptionalOrNotAuthenticated(); - AsyncSslIOAdapter read = new AsyncSslIOAdapter(this, cancellationToken); - return ReadAsyncInternal(read, buffer); + return ReadAsyncInternal(new AsyncReadWriteAdapter(InnerStream, cancellationToken), buffer); } private void ThrowIfExceptional() diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs index b72e549355fdc..3cf26e783a9d0 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs @@ -237,9 +237,8 @@ public static void VerifyPackageInfo() sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials)!, sslAuthenticationOptions); context = sslContext; - if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost)) + if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer) { - Debug.Assert(!sslAuthenticationOptions.IsServer, "targetName should not be set for server-side handshakes"); Interop.AppleCrypto.SslSetTargetName(sslContext.SslContext, sslAuthenticationOptions.TargetHost); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/TlsFrameHelper.cs b/src/libraries/System.Net.Security/src/System/Net/Security/TlsFrameHelper.cs new file mode 100644 index 0000000000000..58906a3dda740 --- /dev/null +++ b/src/libraries/System.Net.Security/src/System/Net/Security/TlsFrameHelper.cs @@ -0,0 +1,239 @@ +// 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.Diagnostics; +using System.Security.Authentication; + +namespace System.Net.Security +{ + // SSL3/TLS protocol frames definitions. + internal enum TlsContentType : byte + { + ChangeCipherSpec = 20, + Alert = 21, + Handshake = 22, + AppData = 23 + } + + internal enum TlsHandshakeType : byte + { + HelloRequest = 0, + ClientHello = 1, + ServerHello = 2, + NewSessionTicket = 4, + EndOfEarlyData = 5, + EncryptedExtensions = 8, + Certificate = 11, + ServerKeyExchange = 12, + CertificateRequest = 13, + ServerHelloDone = 14, + CertificateVerify = 15, + ClientKeyExchange = 16, + Finished = 20, + KeyEpdate = 24, + MessageHash = 254 + } + + internal enum TlsAlertLevel : byte + { + Warning = 1, + Fatal = 2, + } + + internal enum TlsAlertDescription : byte + { + CloseNotify = 0, // warning + UnexpectedMessage = 10, // error + BadRecordMac = 20, // error + DecryptionFailed = 21, // reserved + RecordOverflow = 22, // error + DecompressionFail = 30, // error + HandshakeFailure = 40, // error + BadCertificate = 42, // warning or error + UnsupportedCert = 43, // warning or error + CertificateRevoked = 44, // warning or error + CertificateExpired = 45, // warning or error + CertificateUnknown = 46, // warning or error + IllegalParameter = 47, // error + UnknownCA = 48, // error + AccessDenied = 49, // error + DecodeError = 50, // error + DecryptError = 51, // error + ExportRestriction = 60, // reserved + ProtocolVersion = 70, // error + InsuffientSecurity = 71, // error + InternalError = 80, // error + UserCanceled = 90, // warning or error + NoRenegotiation = 100, // warning + UnsupportedExt = 110, // error + } + + internal struct TlsFrameHeader + { + public TlsContentType Type; + public SslProtocols Version; + public int Length; + } + + internal struct TlsFrameHandshakeInfo + { + public TlsFrameHeader Header; + public TlsHandshakeType HandshakeType; + public SslProtocols SupportedVersions; + public string? TargetName; + } + + internal class TlsFrameHelper + { + public const int HeaderSize = 5; + + private static byte[] s_protocolMismatch13 = new byte[] { (byte)TlsContentType.Alert, 3, 4, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch12 = new byte[] { (byte)TlsContentType.Alert, 3, 3, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch11 = new byte[] { (byte)TlsContentType.Alert, 3, 2, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch10 = new byte[] { (byte)TlsContentType.Alert, 3, 1, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch30 = new byte[] { (byte)TlsContentType.Alert, 3, 0, 0, 2, 2, 40 }; + + public static bool TryGetFrameHeader(ReadOnlySpan frame, ref TlsFrameHeader header) + { + bool result = frame.Length > 4; + + if (frame.Length >= 1) + { + header.Type = (TlsContentType)frame[0]; + + if (frame.Length >= 3) + { + // SSLv3, TLS or later + if (frame[1] == 3) + { + if (frame.Length > 4) + { + header.Length = ((frame[3] << 8) | frame[4]); + } + + switch (frame[2]) + { + case 4: + header.Version = SslProtocols.Tls13; + break; + case 3: + header.Version = SslProtocols.Tls12; + break; + case 2: + header.Version = SslProtocols.Tls11; + break; + case 1: + header.Version = SslProtocols.Tls; + break; + case 0: +#pragma warning disable 0618 + header.Version = SslProtocols.Ssl3; +#pragma warning restore 0618 + break; + default: + header.Version = SslProtocols.None; + break; + } + } + else + { + header.Length = -1; + header.Version = SslProtocols.None; + } + } + } + + return result; + } + + // Returns frame size e.g. header + content + public static int GetFrameSize(ReadOnlySpan frame) + { + if (frame.Length < 5 || frame[1] < 3) + { + return - 1; + } + + return ((frame[3] << 8) | frame[4]) + HeaderSize; + } + + public static bool TryGetHandshakeInfo(ReadOnlySpan frame, ref TlsFrameHandshakeInfo info) + { + if (frame.Length < 6 || frame[0] != (byte)TlsContentType.Handshake) + { + return false; + } + + // This will not fail since we have enough data. + bool gotHeader = TryGetFrameHeader(frame, ref info.Header); + Debug.Assert(gotHeader); + + info.SupportedVersions = info.Header.Version; + + info.HandshakeType = (TlsHandshakeType)frame[5]; + + if (info.HandshakeType == TlsHandshakeType.ClientHello) + { + info.TargetName = SniHelper.GetServerName(frame); + } + + return true; + } + + public static bool TryGetAlertInfo(ReadOnlySpan frame, ref TlsAlertLevel level, ref TlsAlertDescription description) + { + if (frame.Length < 7 || frame[0] != (byte)TlsContentType.Alert) + { + return false; + } + + level = (TlsAlertLevel)frame[5]; + description = (TlsAlertDescription)frame[6]; + + return true; + } + + private static byte[] CreateProtocolVersionAlert(SslProtocols version) => + version switch + { + SslProtocols.Tls13 => s_protocolMismatch13, + SslProtocols.Tls12 => s_protocolMismatch12, + SslProtocols.Tls11 => s_protocolMismatch11, + SslProtocols.Tls => s_protocolMismatch10, +#pragma warning disable 0618 + SslProtocols.Ssl3 => s_protocolMismatch30, +#pragma warning restore 0618 + _ => Array.Empty(), + }; + + public static byte[] CreateAlertFrame(SslProtocols version, TlsAlertDescription reason) + { + if (reason == TlsAlertDescription.ProtocolVersion) + { + return CreateProtocolVersionAlert(version); + } + else if ((int)version > (int)SslProtocols.Tls) + { + // Create TLS1.2 alert + byte[] buffer = new byte[] { (byte)TlsContentType.Alert, 3, 3, 0, 2, 2, (byte)reason }; + switch (version) + { + case SslProtocols.Tls13: + buffer[2] = 4; + break; + case SslProtocols.Tls11: + buffer[2] = 2; + break; + case SslProtocols.Tls: + buffer[2] = 1; + break; + } + + return buffer; + } + + return Array.Empty(); + } + } +} diff --git a/src/libraries/System.Net.Security/src/System/Net/SslStreamContext.cs b/src/libraries/System.Net.Security/src/System/Net/SslStreamContext.cs index eda52c9d784ef..338e3c84434b5 100644 --- a/src/libraries/System.Net.Security/src/System/Net/SslStreamContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/SslStreamContext.cs @@ -2,28 +2,23 @@ // 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.Diagnostics; using System.Net.Security; using System.Security.Authentication.ExtendedProtection; namespace System.Net { - internal class SslStreamContext : TransportContext + internal sealed class SslStreamContext : TransportContext { + private readonly SslStream _sslStream; + internal SslStreamContext(SslStream sslStream) { - if (sslStream == null) - { - NetEventSource.Fail(this, "Not expecting a null sslStream!"); - } - + Debug.Assert(sslStream != null); _sslStream = sslStream!; } - public override ChannelBinding? GetChannelBinding(ChannelBindingKind kind) - { - return _sslStream.GetChannelBinding(kind); - } - - private readonly SslStream _sslStream; + public override ChannelBinding? GetChannelBinding(ChannelBindingKind kind) => + _sslStream.GetChannelBinding(kind); } } diff --git a/src/libraries/System.Net.Security/src/System/Net/StreamFramer.cs b/src/libraries/System.Net.Security/src/System/Net/StreamFramer.cs index dc494ca17e1b0..264fb4d6accfd 100644 --- a/src/libraries/System.Net.Security/src/System/Net/StreamFramer.cs +++ b/src/libraries/System.Net.Security/src/System/Net/StreamFramer.cs @@ -4,83 +4,37 @@ using System.IO; using System.Globalization; -using System.Runtime.ExceptionServices; +using System.Net.Security; using System.Threading.Tasks; namespace System.Net { - internal class StreamFramer + internal sealed class StreamFramer { - private readonly Stream _transport; - - private bool _eof; - private readonly FrameHeader _writeHeader = new FrameHeader(); private readonly FrameHeader _curReadHeader = new FrameHeader(); - private readonly FrameHeader _readVerifier = new FrameHeader( - FrameHeader.IgnoreValue, - FrameHeader.IgnoreValue, - FrameHeader.IgnoreValue); - - private readonly byte[] _readHeaderBuffer; - private readonly byte[] _writeHeaderBuffer; - private readonly AsyncCallback _readFrameCallback; - private readonly AsyncCallback _beginWriteCallback; - - public StreamFramer(Stream Transport) - { - if (Transport == null || Transport == Stream.Null) - { - throw new ArgumentNullException(nameof(Transport)); - } - - _transport = Transport; - _readHeaderBuffer = new byte[_curReadHeader.Size]; - _writeHeaderBuffer = new byte[_writeHeader.Size]; - - _readFrameCallback = new AsyncCallback(ReadFrameCallback); - _beginWriteCallback = new AsyncCallback(BeginWriteCallback); - } - - public FrameHeader ReadHeader - { - get - { - return _curReadHeader; - } - } - - public FrameHeader WriteHeader - { - get - { - return _writeHeader; - } - } + private readonly byte[] _readHeaderBuffer = new byte[FrameHeader.Size]; + private readonly byte[] _writeHeaderBuffer = new byte[FrameHeader.Size]; + private bool _eof; - public Stream Transport - { - get - { - return _transport; - } - } + public FrameHeader ReadHeader => _curReadHeader; + public FrameHeader WriteHeader => _writeHeader; - public byte[]? ReadMessage() + public async ValueTask ReadMessageAsync(TAdapter adapter) where TAdapter : IReadWriteAdapter { if (_eof) { return null; } - int offset = 0; byte[] buffer = _readHeaderBuffer; int bytesRead; + int offset = 0; while (offset < buffer.Length) { - bytesRead = Transport.Read(buffer, offset, buffer.Length - offset); + bytesRead = await adapter.ReadAsync(buffer.AsMemory(offset)).ConfigureAwait(false); if (bytesRead == 0) { if (offset == 0) @@ -89,20 +43,18 @@ public Stream Transport _eof = true; return null; } - else - { - throw new IOException(SR.Format(SR.net_io_readfailure, SR.net_io_connectionclosed)); - } + + throw new IOException(SR.Format(SR.net_io_readfailure, SR.net_io_connectionclosed)); } offset += bytesRead; } - _curReadHeader.CopyFrom(buffer, 0, _readVerifier); - if (_curReadHeader.PayloadSize > _curReadHeader.MaxMessageSize) + _curReadHeader.CopyFrom(buffer, 0); + if (_curReadHeader.PayloadSize > FrameHeader.MaxMessageSize) { throw new InvalidOperationException(SR.Format(SR.net_frame_size, - _curReadHeader.MaxMessageSize.ToString(NumberFormatInfo.InvariantInfo), + FrameHeader.MaxMessageSize, _curReadHeader.PayloadSize.ToString(NumberFormatInfo.InvariantInfo))); } @@ -111,7 +63,7 @@ public Stream Transport offset = 0; while (offset < buffer.Length) { - bytesRead = Transport.Read(buffer, offset, buffer.Length - offset); + bytesRead = await adapter.ReadAsync(buffer.AsMemory(offset)).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(SR.Format(SR.net_io_readfailure, SR.net_io_connectionclosed)); @@ -122,226 +74,7 @@ public Stream Transport return buffer; } - public IAsyncResult BeginReadMessage(AsyncCallback asyncCallback, object stateObject) - { - WorkerAsyncResult workerResult; - - if (_eof) - { - workerResult = new WorkerAsyncResult(this, stateObject, asyncCallback, null, 0, 0); - workerResult.InvokeCallback(-1); - return workerResult; - } - - workerResult = new WorkerAsyncResult(this, stateObject, asyncCallback, - _readHeaderBuffer, 0, - _readHeaderBuffer.Length); - - IAsyncResult result = TaskToApm.Begin(_transport.ReadAsync(_readHeaderBuffer, 0, _readHeaderBuffer.Length), - _readFrameCallback, workerResult); - - if (result.CompletedSynchronously) - { - ReadFrameComplete(result); - } - - return workerResult; - } - - private void ReadFrameCallback(IAsyncResult transportResult) - { - if (!(transportResult.AsyncState is WorkerAsyncResult)) - { - NetEventSource.Fail(this, $"The state expected to be WorkerAsyncResult, received {transportResult}."); - } - - if (transportResult.CompletedSynchronously) - { - return; - } - - WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState!; - - try - { - ReadFrameComplete(transportResult); - } - catch (Exception e) - { - if (e is OutOfMemoryException) - { - throw; - } - - if (!(e is IOException)) - { - e = new System.IO.IOException(SR.Format(SR.net_io_readfailure, e.Message), e); - } - - workerResult.InvokeCallback(e); - } - } - - // IO COMPLETION CALLBACK - // - // This callback is responsible for getting the complete protocol frame. - // 1. it reads the header. - // 2. it determines the frame size. - // 3. loops while not all frame received or an error. - // - private void ReadFrameComplete(IAsyncResult transportResult) - { - do - { - if (!(transportResult.AsyncState is WorkerAsyncResult)) - { - NetEventSource.Fail(this, $"The state expected to be WorkerAsyncResult, received {transportResult}."); - } - - WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState!; - - int bytesRead = TaskToApm.End(transportResult); - workerResult.Offset += bytesRead; - - if (!(workerResult.Offset <= workerResult.End)) - { - NetEventSource.Fail(this, $"WRONG: offset - end = {workerResult.Offset - workerResult.End}"); - } - - if (bytesRead <= 0) - { - // (by design) This indicates the stream has receives EOF - // If we are in the middle of a Frame - fail, otherwise - produce EOF - object? result = null; - if (!workerResult.HeaderDone && workerResult.Offset == 0) - { - result = (object)-1; - } - else - { - result = new System.IO.IOException(SR.net_frame_read_io); - } - - workerResult.InvokeCallback(result); - return; - } - - if (workerResult.Offset >= workerResult.End) - { - if (!workerResult.HeaderDone) - { - workerResult.HeaderDone = true; - // This indicates the header has been read successfully - _curReadHeader.CopyFrom(workerResult.Buffer!, 0, _readVerifier); - int payloadSize = _curReadHeader.PayloadSize; - if (payloadSize < 0) - { - // Let's call user callback and they call us back and we will throw - workerResult.InvokeCallback(new System.IO.IOException(SR.net_frame_read_size)); - } - - if (payloadSize == 0) - { - // report empty frame (NOT eof!) to the caller, he might be interested in - workerResult.InvokeCallback(0); - return; - } - - if (payloadSize > _curReadHeader.MaxMessageSize) - { - throw new InvalidOperationException(SR.Format(SR.net_frame_size, - _curReadHeader.MaxMessageSize.ToString(NumberFormatInfo.InvariantInfo), - payloadSize.ToString(NumberFormatInfo.InvariantInfo))); - } - - // Start reading the remaining frame data (note header does not count). - byte[] frame = new byte[payloadSize]; - // Save the ref of the data block - workerResult.Buffer = frame; - workerResult.End = frame.Length; - workerResult.Offset = 0; - - // Transport.ReadAsync below will pickup those changes. - } - else - { - workerResult.HeaderDone = false; // Reset for optional object reuse. - workerResult.InvokeCallback(workerResult.End); - return; - } - } - - // This means we need more data to complete the data block. - transportResult = TaskToApm.Begin(_transport.ReadAsync(workerResult.Buffer!, workerResult.Offset, workerResult.End - workerResult.Offset), - _readFrameCallback, workerResult); - } while (transportResult.CompletedSynchronously); - } - - // - // User code will call this when workerResult gets signaled. - // - // On BeginRead, the user always gets back our WorkerAsyncResult. - // The Result property represents either a number of bytes read or an - // exception put by our async state machine. - // - public byte[]? EndReadMessage(IAsyncResult asyncResult) - { - if (asyncResult == null) - { - throw new ArgumentNullException(nameof(asyncResult)); - } - WorkerAsyncResult? workerResult = asyncResult as WorkerAsyncResult; - - if (workerResult == null) - { - throw new ArgumentException(SR.Format(SR.net_io_async_result, typeof(WorkerAsyncResult).FullName), nameof(asyncResult)); - } - - if (!workerResult.InternalPeekCompleted) - { - workerResult.InternalWaitForCompletion(); - } - - if (workerResult.Result is Exception e) - { - ExceptionDispatchInfo.Throw(e); - } - - int size = (int)workerResult.Result!; - if (size == -1) - { - _eof = true; - return null; - } - else if (size == 0) - { - // Empty frame. - return Array.Empty(); - } - - return workerResult.Buffer; - } - - public void WriteMessage(byte[] message) - { - if (message == null) - { - throw new ArgumentNullException(nameof(message)); - } - - _writeHeader.PayloadSize = message.Length; - _writeHeader.CopyTo(_writeHeaderBuffer, 0); - - Transport.Write(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length); - if (message.Length == 0) - { - return; - } - - Transport.Write(message, 0, message.Length); - } - - public IAsyncResult BeginWriteMessage(byte[] message, AsyncCallback asyncCallback, object stateObject) + public async Task WriteMessageAsync(TAdapter adapter, byte[] message) where TAdapter : IReadWriteAdapter { if (message == null) { @@ -351,141 +84,16 @@ public IAsyncResult BeginWriteMessage(byte[] message, AsyncCallback asyncCallbac _writeHeader.PayloadSize = message.Length; _writeHeader.CopyTo(_writeHeaderBuffer, 0); - if (message.Length == 0) - { - return TaskToApm.Begin(_transport.WriteAsync(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length), - asyncCallback, stateObject); - } - - // Will need two async writes. Prepare the second: - WorkerAsyncResult workerResult = new WorkerAsyncResult(this, stateObject, asyncCallback, - message, 0, message.Length); - - // Charge the first: - IAsyncResult result = TaskToApm.Begin(_transport.WriteAsync(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length), - _beginWriteCallback, workerResult); - - if (result.CompletedSynchronously) - { - BeginWriteComplete(result); - } - - return workerResult; - } - - private void BeginWriteCallback(IAsyncResult transportResult) - { - if (!(transportResult.AsyncState is WorkerAsyncResult)) - { - NetEventSource.Fail(this, $"The state expected to be WorkerAsyncResult, received {transportResult}."); - } - - if (transportResult.CompletedSynchronously) - { - return; - } - - var workerResult = (WorkerAsyncResult)transportResult.AsyncState!; - - try - { - BeginWriteComplete(transportResult); - } - catch (Exception e) - { - if (e is OutOfMemoryException) - { - throw; - } - - workerResult.InvokeCallback(e); - } - } - - // IO COMPLETION CALLBACK - // - // Called when user IO request was wrapped to do several underlined IO. - // - private void BeginWriteComplete(IAsyncResult transportResult) - { - do - { - WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState!; - - // First, complete the previous portion write. - TaskToApm.End(transportResult); - - // Check on exit criterion. - if (workerResult.Offset == workerResult.End) - { - workerResult.InvokeCallback(); - return; - } - - // Setup exit criterion. - workerResult.Offset = workerResult.End; - - // Write next portion (frame body) using Async IO. - transportResult = TaskToApm.Begin(_transport.WriteAsync(workerResult.Buffer!, 0, workerResult.End), - _beginWriteCallback, workerResult); - } - while (transportResult.CompletedSynchronously); - } - - public void EndWriteMessage(IAsyncResult asyncResult) - { - if (asyncResult == null) - { - throw new ArgumentNullException(nameof(asyncResult)); - } - - WorkerAsyncResult? workerResult = asyncResult as WorkerAsyncResult; - - if (workerResult != null) + await adapter.WriteAsync(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length).ConfigureAwait(false); + if (message.Length != 0) { - if (!workerResult.InternalPeekCompleted) - { - workerResult.InternalWaitForCompletion(); - } - - if (workerResult.Result is Exception e) - { - ExceptionDispatchInfo.Throw(e); - } - } - else - { - TaskToApm.End(asyncResult); + await adapter.WriteAsync(message, 0, message.Length).ConfigureAwait(false); } } } - // - // This class wraps an Async IO request. It is based on our internal LazyAsyncResult helper. - // - If ParentResult is not null then the base class (LazyAsyncResult) methods must not be used. - // - If ParentResult == null, then real user IO request is wrapped. - // - - internal class WorkerAsyncResult : LazyAsyncResult - { - public byte[]? Buffer; - public int Offset; - public int End; - public bool HeaderDone; // This might be reworked so we read both header and frame in one chunk. - - public WorkerAsyncResult(object asyncObject, object asyncState, - AsyncCallback savedAsyncCallback, - byte[]? buffer, int offset, int end) - : base(asyncObject, asyncState, savedAsyncCallback) - { - Buffer = buffer; - Offset = offset; - End = end; - } - } - // Describes the header used in framing of the stream data. - internal class FrameHeader + internal sealed class FrameHeader { public const int IgnoreValue = -1; public const int HandshakeDoneId = 20; @@ -493,121 +101,44 @@ internal class FrameHeader public const int HandshakeId = 22; public const int DefaultMajorV = 1; public const int DefaultMinorV = 0; + public const int Size = 5; + public const int MaxMessageSize = 0xFFFF; - private int _MessageId; - private int _MajorV; - private int _MinorV; - private int _PayloadSize; - - public FrameHeader() - { - _MessageId = HandshakeId; - _MajorV = DefaultMajorV; - _MinorV = DefaultMinorV; - _PayloadSize = -1; - } - - public FrameHeader(int messageId, int majorV, int minorV) - { - _MessageId = messageId; - _MajorV = majorV; - _MinorV = minorV; - _PayloadSize = -1; - } - - public int Size - { - get - { - return 5; - } - } - - public int MaxMessageSize - { - get - { - return 0xFFFF; - } - } - - public int MessageId - { - get - { - return _MessageId; - } - set - { - _MessageId = value; - } - } + private int _payloadSize = -1; - public int MajorV - { - get - { - return _MajorV; - } - } - - public int MinorV - { - get - { - return _MinorV; - } - } + public int MessageId { get; set; } = HandshakeId; + public int MajorV { get; private set; } = DefaultMajorV; + public int MinorV { get; private set; } = DefaultMinorV; public int PayloadSize { - get - { - return _PayloadSize; - } + get => _payloadSize; set { if (value > MaxMessageSize) { - throw new ArgumentException(SR.Format(SR.net_frame_max_size, - MaxMessageSize.ToString(NumberFormatInfo.InvariantInfo), - value.ToString(NumberFormatInfo.InvariantInfo)), "PayloadSize"); + throw new ArgumentException(SR.Format(SR.net_frame_max_size, MaxMessageSize, value), nameof(PayloadSize)); } - _PayloadSize = value; + _payloadSize = value; } } public void CopyTo(byte[] dest, int start) { - dest[start++] = (byte)_MessageId; - dest[start++] = (byte)_MajorV; - dest[start++] = (byte)_MinorV; - dest[start++] = (byte)((_PayloadSize >> 8) & 0xFF); - dest[start] = (byte)(_PayloadSize & 0xFF); + dest[start++] = (byte)MessageId; + dest[start++] = (byte)MajorV; + dest[start++] = (byte)MinorV; + dest[start++] = (byte)((_payloadSize >> 8) & 0xFF); + dest[start] = (byte)(_payloadSize & 0xFF); } - public void CopyFrom(byte[] bytes, int start, FrameHeader verifier) + public void CopyFrom(byte[] bytes, int start) { - _MessageId = bytes[start++]; - _MajorV = bytes[start++]; - _MinorV = bytes[start++]; - _PayloadSize = (int)((bytes[start++] << 8) | bytes[start]); - - if (verifier.MessageId != FrameHeader.IgnoreValue && MessageId != verifier.MessageId) - { - throw new InvalidOperationException(SR.Format(SR.net_io_header_id, "MessageId", MessageId, verifier.MessageId)); - } - - if (verifier.MajorV != FrameHeader.IgnoreValue && MajorV != verifier.MajorV) - { - throw new InvalidOperationException(SR.Format(SR.net_io_header_id, "MajorV", MajorV, verifier.MajorV)); - } - - if (verifier.MinorV != FrameHeader.IgnoreValue && MinorV != verifier.MinorV) - { - throw new InvalidOperationException(SR.Format(SR.net_io_header_id, "MinorV", MinorV, verifier.MinorV)); - } + MessageId = bytes[start++]; + MajorV = bytes[start++]; + MinorV = bytes[start++]; + _payloadSize = (bytes[start++] << 8) | bytes[start]; } } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs index 69c96735809da..a8dba5b6b0b6b 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs @@ -19,9 +19,9 @@ public class ClientAsyncAuthenticateTest { private readonly ITestOutputHelper _log; - public ClientAsyncAuthenticateTest() + public ClientAsyncAuthenticateTest(ITestOutputHelper output) { - _log = TestLogging.GetInstance(); + _log = output; } [Fact] @@ -44,11 +44,7 @@ public async Task ClientAsyncAuthenticate_ServerRequireEncryption_ConnectWithEnc public async Task ClientAsyncAuthenticate_ServerNoEncryption_NoConnect() { // Don't use Tls13 since we are trying to use NullEncryption - Type expectedExceptionType = TestConfiguration.SupportsHandshakeAlerts && TestConfiguration.SupportsNullEncryption ? - typeof(AuthenticationException) : - typeof(IOException); - - await Assert.ThrowsAsync(expectedExceptionType, + await Assert.ThrowsAsync( () => ClientAsyncSslHelper( EncryptionPolicy.NoEncryption, SslProtocolSupport.DefaultSslProtocols, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 )); @@ -67,7 +63,7 @@ public async Task ClientAsyncAuthenticate_Ssl2WithSelf_Success() { // Test Ssl2 against itself. This is a standalone test as even on versions where Windows supports Ssl2, // it appears to have rules around not using it when other protocols are mentioned. - if (!PlatformDetection.IsWindows10Version1607OrGreater) + if (PlatformDetection.SupportsSsl2) { #pragma warning disable 0618 await ClientAsyncSslHelper(SslProtocols.Ssl2, SslProtocols.Ssl2); @@ -120,12 +116,12 @@ public static IEnumerable ProtocolMismatchData() yield return new object[] { SslProtocols.Ssl2, SslProtocols.Tls12, typeof(Exception) }; yield return new object[] { SslProtocols.Ssl3, SslProtocols.Tls12, typeof(Exception) }; #pragma warning restore 0618 - yield return new object[] { SslProtocols.Tls, SslProtocols.Tls11, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(IOException) }; - yield return new object[] { SslProtocols.Tls, SslProtocols.Tls12, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(IOException) }; + yield return new object[] { SslProtocols.Tls, SslProtocols.Tls11, typeof(AuthenticationException) }; + yield return new object[] { SslProtocols.Tls, SslProtocols.Tls12, typeof(AuthenticationException) }; yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls, typeof(AuthenticationException) }; yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, typeof(AuthenticationException) }; yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, typeof(AuthenticationException) }; - yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(IOException) }; + yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, typeof(AuthenticationException) }; } #region Helpers diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs index 4a57ca9063161..ed3a2c635e692 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs @@ -84,7 +84,7 @@ public async Task ClientDefaultEncryption_ServerNoEncryption_NoConnect() using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null)) { - await Assert.ThrowsAsync(TestConfiguration.SupportsHandshakeAlerts ? typeof(AuthenticationException) : typeof(IOException), () => + await Assert.ThrowsAsync(() => sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false)); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamInvalidOperationTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamInvalidOperationTest.cs index bdde8c6bded93..68c6368969902 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamInvalidOperationTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamInvalidOperationTest.cs @@ -98,56 +98,6 @@ public async Task NegotiateStream_EndReadEndWriteInvalidParameter_Throws() } } - [Fact] - public async Task NegotiateStream_ConcurrentAsyncReadOrWrite_ThrowsNotSupportedException() - { - byte[] recvBuf = new byte[s_sampleMsg.Length]; - var network = new VirtualNetwork(); - - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) - using (var client = new NegotiateStream(clientStream)) - using (var server = new NegotiateStream(serverStream)) - { - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - client.AuthenticateAsClientAsync(CredentialCache.DefaultNetworkCredentials, string.Empty), - server.AuthenticateAsServerAsync()); - - // Custom EndWrite/Read will not reset the variable which monitors concurrent write/read. - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - Task.Factory.FromAsync(client.BeginWrite, (ar) => { Assert.NotNull(ar); }, s_sampleMsg, 0, s_sampleMsg.Length, client), - Task.Factory.FromAsync(server.BeginRead, (ar) => { Assert.NotNull(ar); }, recvBuf, 0, s_sampleMsg.Length, server)); - - Assert.Throws(() => client.BeginWrite(s_sampleMsg, 0, s_sampleMsg.Length, (ar) => { Assert.Null(ar); }, null)); - Assert.Throws(() => server.BeginRead(recvBuf, 0, s_sampleMsg.Length, (ar) => { Assert.Null(ar); }, null)); - } - } - - [Fact] - public async Task NegotiateStream_ConcurrentSyncReadOrWrite_ThrowsNotSupportedException() - { - byte[] recvBuf = new byte[s_sampleMsg.Length]; - var network = new VirtualNetwork(); - - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) - using (var client = new NegotiateStream(clientStream)) - using (var server = new NegotiateStream(serverStream)) - { - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - client.AuthenticateAsClientAsync(CredentialCache.DefaultNetworkCredentials, string.Empty), - server.AuthenticateAsServerAsync()); - - // Custom EndWrite/Read will not reset the variable which monitors concurrent write/read. - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - Task.Factory.FromAsync(client.BeginWrite, (ar) => { Assert.NotNull(ar); }, s_sampleMsg, 0, s_sampleMsg.Length, client), - Task.Factory.FromAsync(server.BeginRead, (ar) => { Assert.NotNull(ar); }, recvBuf, 0, s_sampleMsg.Length, server)); - - Assert.Throws(() => client.Write(s_sampleMsg, 0, s_sampleMsg.Length)); - Assert.Throws(() => server.Read(recvBuf, 0, s_sampleMsg.Length)); - } - } - [Fact] public async Task NegotiateStream_DisposeTooEarly_Throws() { @@ -336,7 +286,6 @@ public async Task NegotiateStream_EndAuthenticateInvalidParameter_Throws() AssertExtensions.Throws(nameof(asyncResult), () => authStream.EndAuthenticateAsClient(result)); authStream.EndAuthenticateAsClient(asyncResult); - Assert.Throws(() => authStream.EndAuthenticateAsClient(asyncResult)); }, CredentialCache.DefaultNetworkCredentials, string.Empty, client), Task.Factory.FromAsync(server.BeginAuthenticateAsServer, (asyncResult) => @@ -348,7 +297,6 @@ public async Task NegotiateStream_EndAuthenticateInvalidParameter_Throws() AssertExtensions.Throws(nameof(asyncResult), () => authStream.EndAuthenticateAsServer(result)); authStream.EndAuthenticateAsServer(asyncResult); - Assert.Throws(() => authStream.EndAuthenticateAsServer(asyncResult)); }, server)); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs index a507020420be9..1ffe2216a5a9e 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs @@ -2,11 +2,13 @@ // 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.Diagnostics; +using System.IO; using System.Linq; using System.Net.Test.Common; +using System.Security.Authentication.ExtendedProtection; using System.Security.Principal; using System.Text; +using System.Threading; using System.Threading.Tasks; using Xunit; @@ -19,7 +21,7 @@ public abstract class NegotiateStreamStreamToStreamTest public static bool IsNtlmInstalled => Capability.IsNtlmInstalled(); private const int PartialBytesToRead = 5; - private static readonly byte[] s_sampleMsg = Encoding.UTF8.GetBytes("Sample Test Message"); + protected static readonly byte[] s_sampleMsg = Encoding.UTF8.GetBytes("Sample Test Message"); private const int MaxWriteDataSize = 63 * 1024; // NegoState.MaxWriteDataSize private static string s_longString = new string('A', MaxWriteDataSize) + 'Z'; @@ -27,14 +29,20 @@ public abstract class NegotiateStreamStreamToStreamTest protected abstract Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName); protected abstract Task AuthenticateAsServerAsync(NegotiateStream server); - - [ConditionalFact(nameof(IsNtlmInstalled))] - public async Task NegotiateStream_StreamToStream_Authentication_Success() + protected abstract Task ReadAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default); + protected abstract Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default); + protected virtual bool SupportsCancelableReadsWrites => false; + protected virtual bool IsEncryptedAndSigned => true; + + [ConditionalTheory(nameof(IsNtlmInstalled))] + [InlineData(0)] + [InlineData(1)] + public async Task NegotiateStream_StreamToStream_Authentication_Success(int delay) { VirtualNetwork network = new VirtualNetwork(); - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var clientStream = new VirtualNetworkStream(network, isServer: false) { DelayMilliseconds = delay }) + using (var serverStream = new VirtualNetworkStream(network, isServer: true) { DelayMilliseconds = delay }) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { @@ -49,10 +57,10 @@ public async Task NegotiateStream_StreamToStream_Authentication_Success() // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); - Assert.True(client.IsEncrypted); + Assert.Equal(IsEncryptedAndSigned, client.IsEncrypted); Assert.False(client.IsMutuallyAuthenticated); Assert.False(client.IsServer); - Assert.True(client.IsSigned); + Assert.Equal(IsEncryptedAndSigned, client.IsSigned); Assert.False(client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; @@ -63,10 +71,10 @@ public async Task NegotiateStream_StreamToStream_Authentication_Success() // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); - Assert.True(server.IsEncrypted); + Assert.Equal(IsEncryptedAndSigned, server.IsEncrypted); Assert.False(server.IsMutuallyAuthenticated); Assert.True(server.IsServer); - Assert.True(server.IsSigned); + Assert.Equal(IsEncryptedAndSigned, server.IsSigned); Assert.False(server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; @@ -78,6 +86,43 @@ public async Task NegotiateStream_StreamToStream_Authentication_Success() } } + [ConditionalTheory(nameof(IsNtlmInstalled))] + [InlineData(0)] + [InlineData(1)] + public async Task NegotiateStream_StreamToStream_Authenticated_DisposeAsync(int delay) + { + var network = new VirtualNetwork(); + await using (var client = new NegotiateStream(new VirtualNetworkStream(network, isServer: false) { DelayMilliseconds = delay })) + await using (var server = new NegotiateStream(new VirtualNetworkStream(network, isServer: true) { DelayMilliseconds = delay })) + { + Assert.False(client.IsServer); + Assert.False(server.IsServer); + + Assert.False(client.IsAuthenticated); + Assert.False(server.IsAuthenticated); + + Assert.False(client.IsMutuallyAuthenticated); + Assert.False(server.IsMutuallyAuthenticated); + + Assert.False(client.IsEncrypted); + Assert.False(server.IsEncrypted); + + Assert.False(client.IsSigned); + Assert.False(server.IsSigned); + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + AuthenticateAsClientAsync(client, CredentialCache.DefaultNetworkCredentials, string.Empty), + AuthenticateAsServerAsync(server)); + } + } + + [ConditionalFact(nameof(IsNtlmInstalled))] + public async Task NegotiateStream_StreamToStream_Unauthenticated_Dispose() + { + new NegotiateStream(new MemoryStream()).Dispose(); + await new NegotiateStream(new MemoryStream()).DisposeAsync(); + } + [ConditionalFact(nameof(IsNtlmInstalled))] public async Task NegotiateStream_StreamToStream_Authentication_TargetName_Success() { @@ -105,10 +150,10 @@ public async Task NegotiateStream_StreamToStream_Authentication_TargetName_Succe // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); - Assert.True(client.IsEncrypted); + Assert.Equal(IsEncryptedAndSigned, client.IsEncrypted); Assert.False(client.IsMutuallyAuthenticated); Assert.False(client.IsServer); - Assert.True(client.IsSigned); + Assert.Equal(IsEncryptedAndSigned, client.IsSigned); Assert.False(client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; @@ -119,10 +164,10 @@ public async Task NegotiateStream_StreamToStream_Authentication_TargetName_Succe // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); - Assert.True(server.IsEncrypted); + Assert.Equal(IsEncryptedAndSigned, server.IsEncrypted); Assert.False(server.IsMutuallyAuthenticated); Assert.True(server.IsServer); - Assert.True(server.IsSigned); + Assert.Equal(IsEncryptedAndSigned, server.IsSigned); Assert.False(server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; @@ -165,10 +210,10 @@ public async Task NegotiateStream_StreamToStream_Authentication_EmptyCredentials // Expected Client property values: Assert.True(client.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, client.ImpersonationLevel); - Assert.True(client.IsEncrypted); + Assert.Equal(IsEncryptedAndSigned, client.IsEncrypted); Assert.False(client.IsMutuallyAuthenticated); Assert.False(client.IsServer); - Assert.True(client.IsSigned); + Assert.Equal(IsEncryptedAndSigned, client.IsSigned); Assert.False(client.LeaveInnerStreamOpen); IIdentity serverIdentity = client.RemoteIdentity; @@ -179,10 +224,10 @@ public async Task NegotiateStream_StreamToStream_Authentication_EmptyCredentials // Expected Server property values: Assert.True(server.IsAuthenticated); Assert.Equal(TokenImpersonationLevel.Identification, server.ImpersonationLevel); - Assert.True(server.IsEncrypted); + Assert.Equal(IsEncryptedAndSigned, server.IsEncrypted); Assert.False(server.IsMutuallyAuthenticated); Assert.True(server.IsServer); - Assert.True(server.IsSigned); + Assert.Equal(IsEncryptedAndSigned, server.IsSigned); Assert.False(server.LeaveInnerStreamOpen); IIdentity clientIdentity = server.RemoteIdentity; @@ -195,15 +240,17 @@ public async Task NegotiateStream_StreamToStream_Authentication_EmptyCredentials } } - [ConditionalFact(nameof(IsNtlmInstalled))] - public async Task NegotiateStream_StreamToStream_Successive_ClientWrite_Sync_Success() + [ConditionalTheory(nameof(IsNtlmInstalled))] + [InlineData(0)] + [InlineData(1)] + public async Task NegotiateStream_StreamToStream_Successive_ClientWrite_Success(int delay) { byte[] recvBuf = new byte[s_sampleMsg.Length]; VirtualNetwork network = new VirtualNetwork(); int bytesRead = 0; - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var clientStream = new VirtualNetworkStream(network, isServer: false) { DelayMilliseconds = delay }) + using (var serverStream = new VirtualNetworkStream(network, isServer: true) { DelayMilliseconds = delay }) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { @@ -216,99 +263,35 @@ public async Task NegotiateStream_StreamToStream_Successive_ClientWrite_Sync_Suc await TestConfiguration.WhenAllOrAnyFailedWithTimeout(auth); - client.Write(s_sampleMsg, 0, s_sampleMsg.Length); - server.Read(recvBuf, 0, s_sampleMsg.Length); - - Assert.True(s_sampleMsg.SequenceEqual(recvBuf)); - - client.Write(s_sampleMsg, 0, s_sampleMsg.Length); - - // Test partial sync read. - bytesRead = server.Read(recvBuf, 0, PartialBytesToRead); - Assert.Equal(PartialBytesToRead, bytesRead); - - bytesRead = server.Read(recvBuf, PartialBytesToRead, s_sampleMsg.Length - PartialBytesToRead); - Assert.Equal(s_sampleMsg.Length - PartialBytesToRead, bytesRead); - - Assert.True(s_sampleMsg.SequenceEqual(recvBuf)); - } - } - - [ConditionalFact(nameof(IsNtlmInstalled))] - public async Task NegotiateStream_StreamToStream_Successive_ClientWrite_Async_Success() - { - byte[] recvBuf = new byte[s_sampleMsg.Length]; - VirtualNetwork network = new VirtualNetwork(); - int bytesRead = 0; - - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) - using (var client = new NegotiateStream(clientStream)) - using (var server = new NegotiateStream(serverStream)) - { - Assert.False(client.IsAuthenticated); - Assert.False(server.IsAuthenticated); - - Task[] auth = new Task[2]; - auth[0] = AuthenticateAsClientAsync(client, CredentialCache.DefaultNetworkCredentials, string.Empty); - auth[1] = AuthenticateAsServerAsync(server); - - await TestConfiguration.WhenAllOrAnyFailedWithTimeout(auth); - - auth[0] = client.WriteAsync(s_sampleMsg, 0, s_sampleMsg.Length); - auth[1] = server.ReadAsync(recvBuf, 0, s_sampleMsg.Length); + auth[0] = WriteAsync(client, s_sampleMsg, 0, s_sampleMsg.Length); + auth[1] = ReadAsync(server, recvBuf, 0, s_sampleMsg.Length); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(auth); Assert.True(s_sampleMsg.SequenceEqual(recvBuf)); - await client.WriteAsync(s_sampleMsg, 0, s_sampleMsg.Length); + await WriteAsync(client, s_sampleMsg, 0, s_sampleMsg.Length); // Test partial async read. - bytesRead = await server.ReadAsync(recvBuf, 0, PartialBytesToRead); + bytesRead = await ReadAsync(server, recvBuf, 0, PartialBytesToRead); Assert.Equal(PartialBytesToRead, bytesRead); - bytesRead = await server.ReadAsync(recvBuf, PartialBytesToRead, s_sampleMsg.Length - PartialBytesToRead); + bytesRead = await ReadAsync(server, recvBuf, PartialBytesToRead, s_sampleMsg.Length - PartialBytesToRead); Assert.Equal(s_sampleMsg.Length - PartialBytesToRead, bytesRead); Assert.True(s_sampleMsg.SequenceEqual(recvBuf)); } } - [ConditionalFact(nameof(IsNtlmInstalled))] - public async Task NegotiateStream_ReadWriteLongMsgSync_Success() - { - byte[] recvBuf = new byte[s_longMsg.Length]; - var network = new VirtualNetwork(); - int bytesRead = 0; - - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) - using (var client = new NegotiateStream(clientStream)) - using (var server = new NegotiateStream(serverStream)) - { - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - client.AuthenticateAsClientAsync(CredentialCache.DefaultNetworkCredentials, string.Empty), - server.AuthenticateAsServerAsync()); - - client.Write(s_longMsg, 0, s_longMsg.Length); - - while (bytesRead < s_longMsg.Length) - { - bytesRead += server.Read(recvBuf, bytesRead, s_longMsg.Length - bytesRead); - } - - Assert.True(s_longMsg.SequenceEqual(recvBuf)); - } - } - - [ConditionalFact(nameof(IsNtlmInstalled))] - public async Task NegotiateStream_ReadWriteLongMsgAsync_Success() + [ConditionalTheory(nameof(IsNtlmInstalled))] + [InlineData(0)] + [InlineData(1)] + public async Task NegotiateStream_ReadWriteLongMsg_Success(int delay) { byte[] recvBuf = new byte[s_longMsg.Length]; var network = new VirtualNetwork(); int bytesRead = 0; - using (var clientStream = new VirtualNetworkStream(network, isServer: false)) - using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var clientStream = new VirtualNetworkStream(network, isServer: false) { DelayMilliseconds = delay }) + using (var serverStream = new VirtualNetworkStream(network, isServer: true) { DelayMilliseconds = delay }) using (var client = new NegotiateStream(clientStream)) using (var server = new NegotiateStream(serverStream)) { @@ -316,11 +299,11 @@ public async Task NegotiateStream_ReadWriteLongMsgAsync_Success() client.AuthenticateAsClientAsync(CredentialCache.DefaultNetworkCredentials, string.Empty), server.AuthenticateAsServerAsync()); - await client.WriteAsync(s_longMsg, 0, s_longMsg.Length); + await WriteAsync(client, s_longMsg, 0, s_longMsg.Length); while (bytesRead < s_longMsg.Length) { - bytesRead += await server.ReadAsync(recvBuf, bytesRead, s_longMsg.Length - bytesRead); + bytesRead += await ReadAsync(server, recvBuf, bytesRead, s_longMsg.Length - bytesRead); } Assert.True(s_longMsg.SequenceEqual(recvBuf)); @@ -356,18 +339,91 @@ public void NegotiateStream_StreamToStream_FlushAsync_Propagated() Assert.True(task.IsCompleted); } } + + [ConditionalFact(nameof(IsNtlmInstalled))] + public async Task NegotiateStream_StreamToStream_Successive_CancelableReadsWrites() + { + if (!SupportsCancelableReadsWrites) + { + return; + } + + byte[] recvBuf = new byte[s_sampleMsg.Length]; + VirtualNetwork network = new VirtualNetwork(); + + using (var clientStream = new VirtualNetworkStream(network, isServer: false)) + using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var client = new NegotiateStream(clientStream)) + using (var server = new NegotiateStream(serverStream)) + { + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + AuthenticateAsClientAsync(client, CredentialCache.DefaultNetworkCredentials, string.Empty), + AuthenticateAsServerAsync(server)); + + clientStream.DelayMilliseconds = int.MaxValue; + serverStream.DelayMilliseconds = int.MaxValue; + + var cts = new CancellationTokenSource(); + Task t = WriteAsync(client, s_sampleMsg, 0, s_sampleMsg.Length, cts.Token); + Assert.False(t.IsCompleted); + cts.Cancel(); + await Assert.ThrowsAnyAsync(() => t); + + cts = new CancellationTokenSource(); + t = ReadAsync(server, s_sampleMsg, 0, s_sampleMsg.Length, cts.Token); + Assert.False(t.IsCompleted); + cts.Cancel(); + await Assert.ThrowsAnyAsync(() => t); + } + } } - public sealed class NegotiateStreamStreamToStreamTest_Async : NegotiateStreamStreamToStreamTest + public sealed class NegotiateStreamStreamToStreamTest_Async_Array : NegotiateStreamStreamToStreamTest { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => client.AuthenticateAsClientAsync(credential, targetName); protected override Task AuthenticateAsServerAsync(NegotiateStream server) => server.AuthenticateAsServerAsync(); + + protected override Task ReadAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + stream.ReadAsync(buffer, offset, count, cancellationToken); + + protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + stream.WriteAsync(buffer, offset, count, cancellationToken); + + protected override bool SupportsCancelableReadsWrites => true; } - public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadNullBinding : NegotiateStreamStreamToStreamTest + public class NegotiateStreamStreamToStreamTest_Async_Memory : NegotiateStreamStreamToStreamTest + { + protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => + client.AuthenticateAsClientAsync(credential, targetName); + + protected override Task AuthenticateAsServerAsync(NegotiateStream server) => + server.AuthenticateAsServerAsync(); + + protected override Task ReadAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + stream.ReadAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask(); + + protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + stream.WriteAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask(); + + protected override bool SupportsCancelableReadsWrites => true; + } + + public class NegotiateStreamStreamToStreamTest_Async_Memory_NotEncrypted : NegotiateStreamStreamToStreamTest_Async_Memory + { + protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => + client.AuthenticateAsClientAsync(credential, targetName, ProtectionLevel.None, TokenImpersonationLevel.Identification); + + protected override Task AuthenticateAsServerAsync(NegotiateStream server) => + server.AuthenticateAsServerAsync(CredentialCache.DefaultNetworkCredentials, ProtectionLevel.None, TokenImpersonationLevel.Identification); + + protected override bool IsEncryptedAndSigned => false; + } + + public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadNullBinding : NegotiateStreamStreamToStreamTest_Async_Memory { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => client.AuthenticateAsClientAsync(credential, null, targetName); @@ -376,7 +432,7 @@ public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadNullBind server.AuthenticateAsServerAsync(null); } - public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadProtectionLevel : NegotiateStreamStreamToStreamTest + public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadProtectionLevel : NegotiateStreamStreamToStreamTest_Async_Memory { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => client.AuthenticateAsClientAsync(credential, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); @@ -385,7 +441,7 @@ public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadProtecti server.AuthenticateAsServerAsync((NetworkCredential)CredentialCache.DefaultCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); } - public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadAllParameters : NegotiateStreamStreamToStreamTest + public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadAllParameters : NegotiateStreamStreamToStreamTest_Async_Memory { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => client.AuthenticateAsClientAsync(credential, null, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); @@ -394,25 +450,62 @@ public sealed class NegotiateStreamStreamToStreamTest_Async_TestOverloadAllParam server.AuthenticateAsServerAsync((NetworkCredential)CredentialCache.DefaultCredentials, null, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification); } - public sealed class NegotiateStreamStreamToStreamTest_BeginEnd : NegotiateStreamStreamToStreamTest + public class NegotiateStreamStreamToStreamTest_BeginEnd : NegotiateStreamStreamToStreamTest { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Factory.FromAsync(client.BeginAuthenticateAsClient, client.EndAuthenticateAsClient, credential, targetName, null); protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Factory.FromAsync(server.BeginAuthenticateAsServer, server.EndAuthenticateAsServer, null); + + protected override Task ReadAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + Task.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, offset, count, null); + + protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, buffer, offset, count, null); } - public sealed class NegotiateStreamStreamToStreamTest_Sync : NegotiateStreamStreamToStreamTest + public sealed class NegotiateStreamStreamToStreamTest_BeginEnd_TestOverloadNullBinding : NegotiateStreamStreamToStreamTest_BeginEnd + { + protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => + Task.Factory.FromAsync(client.BeginAuthenticateAsClient, client.EndAuthenticateAsClient, credential, (ChannelBinding)null, targetName, null); + + protected override Task AuthenticateAsServerAsync(NegotiateStream server) => + Task.Factory.FromAsync(server.BeginAuthenticateAsServer, server.EndAuthenticateAsServer, (ExtendedProtectionPolicy)null, null); + } + + public sealed class NegotiateStreamStreamToStreamTest_BeginEnd_TestOverloadProtectionLevel : NegotiateStreamStreamToStreamTest_BeginEnd + { + protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => + Task.Factory.FromAsync( + (callback, state) => client.BeginAuthenticateAsClient(credential, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, callback, state), + client.EndAuthenticateAsClient, null); + + protected override Task AuthenticateAsServerAsync(NegotiateStream server) => + Task.Factory.FromAsync( + (callback, state) => server.BeginAuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification, callback, state), + server.EndAuthenticateAsServer, null); + } + + public class NegotiateStreamStreamToStreamTest_Sync : NegotiateStreamStreamToStreamTest { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Run(() => client.AuthenticateAsClient(credential, targetName)); protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Run(() => server.AuthenticateAsServer()); + + protected override Task ReadAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + Task.FromResult(stream.Read(buffer, offset, count)); + + protected override Task WriteAsync(NegotiateStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + stream.Write(buffer, offset, count); + return Task.CompletedTask; + } } - public sealed class NegotiateStreamStreamToStreamTest_Sync_TestOverloadNullBinding : NegotiateStreamStreamToStreamTest + public sealed class NegotiateStreamStreamToStreamTest_Sync_TestOverloadNullBinding : NegotiateStreamStreamToStreamTest_Sync { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Run(() => client.AuthenticateAsClient(credential, null, targetName)); @@ -421,7 +514,7 @@ public sealed class NegotiateStreamStreamToStreamTest_Sync_TestOverloadNullBindi Task.Run(() => server.AuthenticateAsServer(null)); } - public sealed class NegotiateStreamStreamToStreamTest_Sync_TestOverloadAllParameters : NegotiateStreamStreamToStreamTest + public sealed class NegotiateStreamStreamToStreamTest_Sync_TestOverloadAllParameters : NegotiateStreamStreamToStreamTest_Sync { protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => Task.Run(() => client.AuthenticateAsClient(credential, targetName, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification)); @@ -429,4 +522,15 @@ public sealed class NegotiateStreamStreamToStreamTest_Sync_TestOverloadAllParame protected override Task AuthenticateAsServerAsync(NegotiateStream server) => Task.Run(() => server.AuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification)); } + + public class NegotiateStreamStreamToStreamTest_Sync_NotEncrypted : NegotiateStreamStreamToStreamTest_Sync + { + protected override Task AuthenticateAsClientAsync(NegotiateStream client, NetworkCredential credential, string targetName) => + Task.Run(() => client.AuthenticateAsClient(credential, targetName, ProtectionLevel.None, TokenImpersonationLevel.Identification)); + + protected override Task AuthenticateAsServerAsync(NegotiateStream server) => + Task.Run(() => server.AuthenticateAsServer((NetworkCredential)CredentialCache.DefaultCredentials, ProtectionLevel.None, TokenImpersonationLevel.Identification)); + + protected override bool IsEncryptedAndSigned => false; + } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs index 12918eaf9c2a4..cc59578b61930 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs @@ -17,9 +17,9 @@ public class ServerAllowNoEncryptionTest { private readonly ITestOutputHelper _log; - public ServerAllowNoEncryptionTest() + public ServerAllowNoEncryptionTest(ITestOutputHelper output) { - _log = TestLogging.GetInstance(); + _log = output; } // The following method is invoked by the RemoteCertificateValidationDelegate. diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs index 5ecb21d630a9a..bc58e68aa5eba 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs @@ -23,9 +23,9 @@ public class ServerAsyncAuthenticateTest : IDisposable private readonly ITestOutputHelper _logVerbose; private readonly X509Certificate2 _serverCertificate; - public ServerAsyncAuthenticateTest() + public ServerAsyncAuthenticateTest(ITestOutputHelper output) { - _log = TestLogging.GetInstance(); + _log = output; _logVerbose = VerboseTestLogging.GetInstance(); _serverCertificate = Configuration.Certificates.GetServerCertificate(); } @@ -44,7 +44,7 @@ public async Task ServerAsyncAuthenticate_EachSupportedProtocol_Success(SslProto [Theory] [MemberData(nameof(ProtocolMismatchData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/29642")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/36192", TestPlatforms.AnyUnix)] public async Task ServerAsyncAuthenticate_MismatchProtocols_Fails( SslProtocols serverProtocol, SslProtocols clientProtocol, @@ -73,17 +73,24 @@ public async Task ServerAsyncAuthenticate_EachSupportedProtocol_Success(SslProto public static IEnumerable ProtocolMismatchData() { + if (PlatformDetection.SupportsSsl3) + { #pragma warning disable 0618 - yield return new object[] { SslProtocols.Ssl2, SslProtocols.Ssl3, typeof(Exception) }; - yield return new object[] { SslProtocols.Ssl2, SslProtocols.Tls12, typeof(Exception) }; - yield return new object[] { SslProtocols.Ssl3, SslProtocols.Tls12, typeof(Exception) }; + yield return new object[] { SslProtocols.Ssl3, SslProtocols.Tls12, typeof(Exception) }; + if (PlatformDetection.SupportsSsl2) + { + yield return new object[] { SslProtocols.Ssl2, SslProtocols.Ssl3, typeof(Exception) }; + yield return new object[] { SslProtocols.Ssl2, SslProtocols.Tls12, typeof(Exception) }; + } #pragma warning restore 0618 + } + yield return new object[] { SslProtocols.Tls, SslProtocols.Tls11, typeof(AuthenticationException) }; yield return new object[] { SslProtocols.Tls, SslProtocols.Tls12, typeof(AuthenticationException) }; - yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(TimeoutException) }; + yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls, typeof(AuthenticationException) }; yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, typeof(AuthenticationException) }; - yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(TimeoutException) }; - yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(TimeoutException) }; + yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, typeof(AuthenticationException) }; + yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, typeof(AuthenticationException) }; } #region Helpers diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs index 65efb78767f9c..5dd06233c06a3 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs @@ -17,9 +17,9 @@ public class ServerNoEncryptionTest { private readonly ITestOutputHelper _log; - public ServerNoEncryptionTest() + public ServerNoEncryptionTest(ITestOutputHelper output) { - _log = TestLogging.GetInstance(); + _log = output; } // The following method is invoked by the RemoteCertificateValidationDelegate. @@ -43,7 +43,7 @@ public async Task ServerNoEncryption_ClientRequireEncryption_NoConnect() using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.RequireEncryption)) { - await Assert.ThrowsAsync(TestConfiguration.SupportsHandshakeAlerts ? typeof(AuthenticationException) : typeof(IOException), () => + await Assert.ThrowsAsync(() => sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false)); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs index 1b15a408084ef..f538b55bebcec 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs @@ -17,9 +17,9 @@ public class ServerRequireEncryptionTest { private readonly ITestOutputHelper _log; - public ServerRequireEncryptionTest() + public ServerRequireEncryptionTest(ITestOutputHelper output) { - _log = TestLogging.GetInstance(); + _log = output; } // The following method is invoked by the RemoteCertificateValidationDelegate. diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslAuthenticationOptionsTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslAuthenticationOptionsTest.cs index ada4a652b6e77..af9e02ad03ed6 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslAuthenticationOptionsTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslAuthenticationOptionsTest.cs @@ -14,8 +14,10 @@ namespace System.Net.Security.Tests { using Configuration = System.Net.Test.Common.Configuration; - public class SslClientAuthenticationOptionsTest + public abstract class SslClientAuthenticationOptionsTestBase { + protected abstract bool TestAuthenticateAsync { get; } + [Fact] public async Task ClientOptions_ServerOptions_NotMutatedDuringAuthentication() { @@ -74,9 +76,9 @@ public async Task ClientOptions_ServerOptions_NotMutatedDuringAuthentication() }; // Authenticate - Task clientTask = client.AuthenticateAsClientAsync(clientOptions, default); - Task serverTask = server.AuthenticateAsServerAsync(serverOptions, default); - await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(); + Task clientTask = client.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions); + Task serverTask = server.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions); + await new[] {clientTask, serverTask}.WhenAllOrAnyFailed(); // Validate that client options are unchanged Assert.Equal(clientAllowRenegotiation, clientOptions.AllowRenegotiation); @@ -105,4 +107,14 @@ public async Task ClientOptions_ServerOptions_NotMutatedDuringAuthentication() } } } + + public sealed class SslClientAuthenticationOptionsTestBase_Sync : SslClientAuthenticationOptionsTestBase + { + protected override bool TestAuthenticateAsync => false; + } + + public sealed class SslClientAuthenticationOptionsTestBase_Async : SslClientAuthenticationOptionsTestBase + { + protected override bool TestAuthenticateAsync => true; + } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAllowRenegotiationTests.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAllowRenegotiationTests.cs index 1895d118ea6f2..b4147844b9060 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAllowRenegotiationTests.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAllowRenegotiationTests.cs @@ -17,8 +17,10 @@ namespace System.Net.Security.Tests { using Configuration = System.Net.Test.Common.Configuration; - public class SslStreamAllowRenegotiationTests + public abstract class SslStreamAllowRenegotiationTestsBase { + protected abstract bool TestAuthenticateAsync { get; } + [Fact] [OuterLoop] // Test hits external azure server. public async Task SslStream_AllowRenegotiation_True_Succeeds() @@ -49,7 +51,7 @@ public async Task SslStream_AllowRenegotiation_True_Succeeds() }; // Perform handshake to establish secure connection. - await ssl.AuthenticateAsClientAsync(options, CancellationToken.None); + await ssl.AuthenticateAsClientAsync(TestAuthenticateAsync, options); Assert.True(ssl.IsAuthenticated); Assert.True(ssl.IsEncrypted); @@ -89,7 +91,7 @@ public async Task SslStream_AllowRenegotiation_False_Throws() }; // Perform handshake to establish secure connection. - await ssl.AuthenticateAsClientAsync(options, CancellationToken.None); + await ssl.AuthenticateAsClientAsync(TestAuthenticateAsync, options); Assert.True(ssl.IsAuthenticated); Assert.True(ssl.IsEncrypted); @@ -103,4 +105,14 @@ public async Task SslStream_AllowRenegotiation_False_Throws() } } } + + public sealed class SslStreamAllowRenegotiationTests_Sync : SslStreamAllowRenegotiationTestsBase + { + protected override bool TestAuthenticateAsync => false; + } + + public sealed class SslStreamAllowRenegotiationTests_Async : SslStreamAllowRenegotiationTestsBase + { + protected override bool TestAuthenticateAsync => true; + } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs index de5212a93fc4c..c5284653585b7 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs @@ -21,19 +21,21 @@ namespace System.Net.Security.Tests { using Configuration = System.Net.Test.Common.Configuration; - public class SslStreamAlpnTests + public abstract class SslStreamAlpnTestBase { private static bool BackendSupportsAlpn => PlatformDetection.SupportsAlpn; private static bool ClientSupportsAlpn => PlatformDetection.SupportsClientAlpn; readonly ITestOutputHelper _output; public static readonly object[][] Http2Servers = Configuration.Http.Http2Servers; - public SslStreamAlpnTests(ITestOutputHelper output) + // Whether AuthenticateAs(Client/Server) or AuthenticateAs(Client/Server)Async will be called + public abstract bool TestAuthenticateAsync { get; } + + protected SslStreamAlpnTestBase(ITestOutputHelper output) { _output = output; } - private async Task DoHandshakeWithOptions(SslStream clientSslStream, SslStream serverSslStream, SslClientAuthenticationOptions clientOptions, SslServerAuthenticationOptions serverOptions) { using (X509Certificate2 certificate = Configuration.Certificates.GetServerCertificate()) @@ -42,8 +44,8 @@ private async Task DoHandshakeWithOptions(SslStream clientSslStream, SslStream s clientOptions.TargetHost = certificate.GetNameInfo(X509NameType.SimpleName, false); serverOptions.ServerCertificate = certificate; - Task t1 = clientSslStream.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); - Task t2 = serverSslStream.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); + Task t1 = clientSslStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions); + Task t2 = serverSslStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); } @@ -95,8 +97,8 @@ public async Task SslStream_StreamToStream_DuplicateOptions_Throws() serverOptions.ServerCertificate = certificate; serverOptions.RemoteCertificateValidationCallback = AllowAnyServerCertificate; - Task t1 = Assert.ThrowsAsync(() => client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None)); - Task t2 = Assert.ThrowsAsync(() => server.AuthenticateAsServerAsync(serverOptions, CancellationToken.None)); + Task t1 = Assert.ThrowsAsync(() => client.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions)); + Task t2 = Assert.ThrowsAsync(() => server.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions)); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); } @@ -163,11 +165,11 @@ public async Task SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail() { // schannel sends alert on ALPN failure, openssl does not. Task t1 = Assert.ThrowsAsync(TestConfiguration.SupportsAlpnAlerts ? typeof(AuthenticationException) : typeof(IOException), () => - clientStream.AuthenticateAsClientAsync(clientOptions, CancellationToken.None)); + clientStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions)); try { - await serverStream.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); + await serverStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions); Assert.True(false, "AuthenticationException was not thrown."); } catch (AuthenticationException) { server.Dispose(); } @@ -176,8 +178,8 @@ public async Task SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail() } else { - Task t1 = clientStream.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); - Task t2 = serverStream.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); + Task t1 = clientStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions); + Task t2 = serverStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); @@ -211,7 +213,7 @@ public async Task SslStream_Http2_Alpn_Success(Uri server) TargetHost = server.Host }; - await clientStream.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); + await clientStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions); Assert.Equal("h2", clientStream.NegotiatedApplicationProtocol.ToString()); } } @@ -246,4 +248,20 @@ public static IEnumerable Alpn_TestData() } } } + + public sealed class SslStreamAlpnTest_Async : SslStreamAlpnTestBase + { + public override bool TestAuthenticateAsync => true; + + public SslStreamAlpnTest_Async(ITestOutputHelper output) + : base (output) { } + } + + public sealed class SslStreamAlpnTest_Sync : SslStreamAlpnTestBase + { + public override bool TestAuthenticateAsync => false; + + public SslStreamAlpnTest_Sync(ITestOutputHelper output) + : base(output) { } + } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamExtensions.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamExtensions.cs new file mode 100644 index 0000000000000..e7e423ee89580 --- /dev/null +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamExtensions.cs @@ -0,0 +1,25 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Security.Tests +{ + internal static class SslStreamExtensions + { + public static Task AuthenticateAsClientAsync(this SslStream stream, + bool async, SslClientAuthenticationOptions clientOptions, + CancellationToken cancellationToken = default) + { + return async + ? stream.AuthenticateAsClientAsync(clientOptions, cancellationToken) + : Task.Run(() => stream.AuthenticateAsClient(clientOptions)); + } + public static Task AuthenticateAsServerAsync(this SslStream stream, + bool async, SslServerAuthenticationOptions serverOptions, + CancellationToken cancellationToken = default) + { + return async + ? stream.AuthenticateAsServerAsync(serverOptions, cancellationToken) + : Task.Run(() => stream.AuthenticateAsServer(serverOptions)); + } + } +} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs index a54624100da2a..b98a9ea992bde 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.IO; using System.Net.Test.Common; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; @@ -201,9 +202,7 @@ private static SslServerAuthenticationOptions DefaultServerOptions() private async Task WithVirtualConnection(Func serverClientConnection, RemoteCertificateValidationCallback clientCertValidate) { - VirtualNetwork vn = new VirtualNetwork(); - using (VirtualNetworkStream serverStream = new VirtualNetworkStream(vn, isServer: true), - clientStream = new VirtualNetworkStream(vn, isServer: false)) + (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); using (SslStream server = new SslStream(serverStream, leaveInnerStreamOpen: false), client = new SslStream(clientStream, leaveInnerStreamOpen: false, clientCertValidate)) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs index 93baf83fd156f..9fb2ac9fefbd6 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs @@ -395,7 +395,7 @@ public async Task SslStream_StreamToStream_WriteAsync_ReadByte_Success() [Fact] public async Task SslStream_StreamToStream_WriteAsync_ReadAsync_Pending_Success() { - if (this is SslStreamStreamToStreamTest_Sync) + if (this is SslStreamStreamToStreamTest_SyncBase) { // This test assumes operations complete asynchronously. return; @@ -488,7 +488,7 @@ public async Task SslStream_ConcurrentBidirectionalReadsWrites_Success() [Fact] public async Task SslStream_StreamToStream_Dispose_Throws() { - if (this is SslStreamStreamToStreamTest_Sync) + if (this is SslStreamStreamToStreamTest_SyncBase) { // This test assumes operations complete asynchronously. return; @@ -511,7 +511,7 @@ public async Task SslStream_StreamToStream_Dispose_Throws() await WriteAsync(serverSslStream, new byte[] { 1 }, 0, 1) .TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); - // Shouldn't throw, the context is diposed now. + // Shouldn't throw, the context is disposed now. // Since the server read task is in progress, the read buffer is not returned to ArrayPool. serverSslStream.Dispose(); @@ -821,19 +821,8 @@ protected override async Task DoHandshake(SslStream clientSslStream, SslStream s Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, buffer, offset, count, null); } - public sealed class SslStreamStreamToStreamTest_Sync : SslStreamStreamToStreamTest + public abstract class SslStreamStreamToStreamTest_SyncBase : SslStreamStreamToStreamTest { - protected override async Task DoHandshake(SslStream clientSslStream, SslStream serverSslStream, X509Certificate serverCertificate = null, X509Certificate clientCertificate = null) - { - X509CertificateCollection clientCerts = clientCertificate != null ? new X509CertificateCollection() { clientCertificate } : null; - await WithServerCertificate(serverCertificate, async (certificate, name) => - { - Task t1 = Task.Run(() => clientSslStream.AuthenticateAsClient(name, clientCerts, SslProtocols.None, checkCertificateRevocation: false)); - Task t2 = Task.Run(() => serverSslStream.AuthenticateAsServer(certificate, clientCertificateRequired: clientCertificate != null, checkCertificateRevocation: false)); - await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); - }); - } - protected override Task ReadAsync(Stream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -868,6 +857,108 @@ protected override Task WriteAsync(Stream stream, byte[] buffer, int offset, int return Task.FromException(e); } } + + [Fact] + public async Task SslStream_StreamToStream_Handshake_DisposeClient_Throws() + { + VirtualNetwork network = new VirtualNetwork(); + + var clientStream = new VirtualNetworkStream(network, isServer: false); + using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var clientSslStream = new SslStream(clientStream, false, AllowAnyServerCertificate)) + using (var serverSslStream = new SslStream(serverStream)) + { + clientStream.Dispose(); + + await Assert.ThrowsAsync(() => DoHandshake(clientSslStream, serverSslStream)); + } + } + + [Fact] + public async Task SslStream_StreamToStream_Handshake_DisposeServer_Throws() + { + VirtualNetwork network = new VirtualNetwork(); + + var serverStream = new VirtualNetworkStream(network, isServer: true); + using (var clientStream = new VirtualNetworkStream(network, isServer: false)) + using (var clientSslStream = new SslStream(clientStream, false, AllowAnyServerCertificate)) + using (var serverSslStream = new SslStream(serverStream)) + { + serverStream.Dispose(); + + await Assert.ThrowsAsync(() => DoHandshake(clientSslStream, serverSslStream)); + } + } + + [Fact] + public async Task SslStream_StreamToStream_Handshake_DisposeClientSsl_Throws() + { + VirtualNetwork network = new VirtualNetwork() { DisableConnectionBreaking = true }; + + using (var clientStream = new VirtualNetworkStream(network, isServer: false)) + using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var serverSslStream = new SslStream(serverStream)) + { + var clientSslStream = new SslStream(clientStream, false, AllowAnyServerCertificate); + clientSslStream.Dispose(); + + await Assert.ThrowsAsync(() => DoHandshake(clientSslStream, serverSslStream)); + } + } + + [Fact] + public async Task SslStream_StreamToStream_Handshake_DisposeServerSsl_Throws() + { + VirtualNetwork network = new VirtualNetwork() {DisableConnectionBreaking = true}; + + using (var clientStream = new VirtualNetworkStream(network, isServer: false)) + using (var serverStream = new VirtualNetworkStream(network, isServer: true)) + using (var clientSslStream = new SslStream(clientStream, false, AllowAnyServerCertificate)) + { + var serverSslStream = new SslStream(serverStream); + serverSslStream.Dispose(); + + await Assert.ThrowsAsync(() => DoHandshake(clientSslStream, serverSslStream)); + } + } + } + + public sealed class SslStreamStreamToStreamTest_SyncParameters : SslStreamStreamToStreamTest_SyncBase + { + protected override async Task DoHandshake(SslStream clientSslStream, SslStream serverSslStream, X509Certificate serverCertificate = null, X509Certificate clientCertificate = null) + { + X509CertificateCollection clientCerts = clientCertificate != null ? new X509CertificateCollection() { clientCertificate } : null; + await WithServerCertificate(serverCertificate, async (certificate, name) => + { + Task t1 = Task.Run(() => clientSslStream.AuthenticateAsClient(name, clientCerts, SslProtocols.None, checkCertificateRevocation: false)); + Task t2 = Task.Run(() => serverSslStream.AuthenticateAsServer(certificate, clientCertificateRequired: clientCertificate != null, checkCertificateRevocation: false)); + await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); + }); + } + } + + public sealed class SslStreamStreamToStreamTest_SyncSslOptions : SslStreamStreamToStreamTest_SyncBase + { + protected override async Task DoHandshake(SslStream clientSslStream, SslStream serverSslStream, X509Certificate serverCertificate = null, X509Certificate clientCertificate = null) + { + X509CertificateCollection clientCerts = clientCertificate != null ? new X509CertificateCollection() { clientCertificate } : null; + await WithServerCertificate(serverCertificate, async (certificate, name) => + { + SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions + { + TargetHost = name, + ClientCertificates = clientCerts, + EnabledSslProtocols = SslProtocols.None, + }; + SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions() + { + ServerCertificate = certificate, ClientCertificateRequired = clientCertificate != null, + }; + Task t1 = Task.Run(() => clientSslStream.AuthenticateAsClient(clientOptions)); + Task t2 = Task.Run(() => serverSslStream.AuthenticateAsServer(serverOptions)); + await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); + }); + } } public sealed class SslStreamStreamToStreamTest_MemoryAsync : SslStreamStreamToStreamTest_CancelableReadWriteAsync diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs index 4943401bc51ee..bc704fae67fda 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs @@ -2,6 +2,7 @@ // 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.IO; using System.Net.Http; using System.Net.Test.Common; using System.Security.Cryptography.X509Certificates; @@ -21,10 +22,7 @@ public abstract class SslStreamSystemDefaultTest public SslStreamSystemDefaultTest() { - var network = new VirtualNetwork(); - var clientNet = new VirtualNetworkStream(network, isServer:false); - var serverNet = new VirtualNetworkStream(network, isServer: true); - + (Stream clientNet, Stream serverNet) = TestHelper.GetConnectedTcpStreams(); _clientStream = new SslStream(clientNet, false, ClientCertCallback); _serverStream = new SslStream(serverNet, false, ServerCertCallback); } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index 8a245e86d3069..94026f1078c10 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -9,6 +9,7 @@ + @@ -66,6 +67,8 @@ Link="ProductionCode\Common\System\Threading\Tasks\TaskToApm.cs" /> + diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs index 9769590181342..1473b3065c46a 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs @@ -16,7 +16,7 @@ namespace System.Net.Security.Tests internal static class TestConfiguration { public const int PassingTestTimeoutMilliseconds = 4 * 60 * 1000; - public const int FailingTestTimeoutMiliseconds = 250; + public const int FailingTestTimeoutMiliseconds = 500; public const string Realm = "TEST.COREFX.NET"; public const string KerberosUser = "krb_user"; @@ -32,9 +32,7 @@ internal static class TestConfiguration public static bool SupportsHandshakeAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.Windows); } } - public static bool SupportsAlpnAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion.CompareTo(new Version(1,1,0)) >= 0); } } - - public static bool SupportsVersionAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion.CompareTo(new Version(1,1,0)) >= 0; } } + public static bool SupportsAlpnAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion.CompareTo(new Version(1,0,2)) >= 0); } } public static Task WhenAllOrAnyFailedWithTimeout(params Task[] tasks) => tasks.WhenAllOrAnyFailed(PassingTestTimeoutMilliseconds); diff --git a/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeLazyAsyncResult.cs b/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeLazyAsyncResult.cs deleted file mode 100644 index 709fc583536f2..0000000000000 --- a/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeLazyAsyncResult.cs +++ /dev/null @@ -1,43 +0,0 @@ -// 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.Threading; - -namespace System.Net.Security -{ - internal class LazyAsyncResult : IAsyncResult - { - public LazyAsyncResult(SslStream sslState, object asyncState, AsyncCallback asyncCallback) - { - AsyncState = asyncState; - asyncCallback?.Invoke(this); - } - - public object AsyncState { get; } - - public WaitHandle AsyncWaitHandle - { - get - { - throw new NotImplementedException(); - } - } - - public bool CompletedSynchronously - { - get - { - return true; - } - } - - public bool IsCompleted - { - get - { - return true; - } - } - } -} diff --git a/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs b/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs index 3dffb86a4da38..ccd294beb54dd 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/Fakes/FakeSslStream.Implementation.cs @@ -38,7 +38,7 @@ private void ValidateCreateContext(SslAuthenticationOptions sslAuthenticationOpt } private ValueTask WriteAsyncInternal(TWriteAdapter writeAdapter, ReadOnlyMemory buffer) - where TWriteAdapter : struct, ISslIOAdapter => default; + where TWriteAdapter : struct, IReadWriteAdapter => default; private ValueTask ReadAsyncInternal(TReadAdapter adapter, Memory buffer) => default; diff --git a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj index 49823f8c08916..50d702a0b094c 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj @@ -24,7 +24,6 @@ - @@ -45,8 +44,8 @@ Link="ProductionCode\System\Net\Security\SslApplicationProtocol.cs" /> - + + + @@ -192,8 +193,8 @@ The specified value cannot be negative. - - Argument must be between {0} and {1}. + + Argument '{2}' must be between {0} and {1}. Sockets on this platform are invalid for use after a failed connection attempt. @@ -258,4 +259,7 @@ Asynchronous operations are not allowed on this socket. The underlying OS handle might have been already bound to an IO completion port. - + + Null is not a valid value for {0}. + + \ No newline at end of file diff --git a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj index f8a2cce64caf2..ae41d45e7d897 100644 --- a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj +++ b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj @@ -2,7 +2,7 @@ System.Net.Sockets true - $(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Windows_NT + $(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix enable @@ -51,8 +51,6 @@ - + + + _streamSocket; @@ -120,34 +117,20 @@ public override int ReadTimeout { get { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + int timeout = (int)_streamSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout)!; + if (timeout == 0) { -#endif - int timeout = (int)_streamSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout)!; - if (timeout == 0) - { - return -1; - } - return timeout; -#if DEBUG + return -1; } -#endif + return timeout; } set { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + if (value <= 0 && value != System.Threading.Timeout.Infinite) { -#endif - if (value <= 0 && value != System.Threading.Timeout.Infinite) - { - throw new ArgumentOutOfRangeException(nameof(value), SR.net_io_timeout_use_gt_zero); - } - SetSocketTimeoutOption(SocketShutdown.Receive, value, false); -#if DEBUG + throw new ArgumentOutOfRangeException(nameof(value), SR.net_io_timeout_use_gt_zero); } -#endif + SetSocketTimeoutOption(SocketShutdown.Receive, value, false); } } @@ -157,34 +140,20 @@ public override int WriteTimeout { get { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + int timeout = (int)_streamSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout)!; + if (timeout == 0) { -#endif - int timeout = (int)_streamSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout)!; - if (timeout == 0) - { - return -1; - } - return timeout; -#if DEBUG + return -1; } -#endif + return timeout; } set { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + if (value <= 0 && value != System.Threading.Timeout.Infinite) { -#endif - if (value <= 0 && value != System.Threading.Timeout.Infinite) - { - throw new ArgumentOutOfRangeException(nameof(value), SR.net_io_timeout_use_gt_zero); - } - SetSocketTimeoutOption(SocketShutdown.Send, value, false); -#if DEBUG + throw new ArgumentOutOfRangeException(nameof(value), SR.net_io_timeout_use_gt_zero); } -#endif + SetSocketTimeoutOption(SocketShutdown.Send, value, false); } } @@ -194,18 +163,11 @@ public virtual bool DataAvailable { get { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) - { -#endif - ThrowIfDisposed(); + ThrowIfDisposed(); - // Ask the socket how many bytes are available. If it's - // not zero, return true. - return _streamSocket.Available != 0; -#if DEBUG - } -#endif + // Ask the socket how many bytes are available. If it's + // not zero, return true. + return _streamSocket.Available != 0; } } @@ -255,44 +217,37 @@ public override long Seek(long offset, SeekOrigin origin) // Number of bytes we read, or 0 if the socket is closed. public override int Read(byte[] buffer, int offset, int size) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) + bool canRead = CanRead; // Prevent race with Dispose. + ThrowIfDisposed(); + if (!canRead) { -#endif - bool canRead = CanRead; // Prevent race with Dispose. - ThrowIfDisposed(); - if (!canRead) - { - throw new InvalidOperationException(SR.net_writeonlystream); - } + throw new InvalidOperationException(SR.net_writeonlystream); + } - // Validate input parameters. - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - if ((uint)offset > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } - if ((uint)size > buffer.Length - offset) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } + // Validate input parameters. + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + if ((uint)offset > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if ((uint)size > buffer.Length - offset) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } - try - { - return _streamSocket.Receive(buffer, offset, size, 0); - } - catch (Exception exception) when (!(exception is OutOfMemoryException)) - { - // Some sort of error occurred on the socket call, - // set the SocketException as InnerException and throw. - throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception); - } -#if DEBUG + try + { + return _streamSocket.Receive(buffer, offset, size, 0); + } + catch (Exception exception) when (!(exception is OutOfMemoryException)) + { + // Some sort of error occurred on the socket call, + // set the SocketException as InnerException and throw. + throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } -#endif } public override int Read(Span buffer) @@ -341,46 +296,39 @@ public override unsafe int ReadByte() // way to indicate an error. public override void Write(byte[] buffer, int offset, int size) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) + bool canWrite = CanWrite; // Prevent race with Dispose. + ThrowIfDisposed(); + if (!canWrite) { -#endif - bool canWrite = CanWrite; // Prevent race with Dispose. - ThrowIfDisposed(); - if (!canWrite) - { - throw new InvalidOperationException(SR.net_readonlystream); - } + throw new InvalidOperationException(SR.net_readonlystream); + } - // Validate input parameters. - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - if ((uint)offset > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } - if ((uint)size > buffer.Length - offset) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } + // Validate input parameters. + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + if ((uint)offset > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if ((uint)size > buffer.Length - offset) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } - try - { - // Since the socket is in blocking mode this will always complete - // after ALL the requested number of bytes was transferred. - _streamSocket.Send(buffer, offset, size, SocketFlags.None); - } - catch (Exception exception) when (!(exception is OutOfMemoryException)) - { - // Some sort of error occurred on the socket call, - // set the SocketException as InnerException and throw. - throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception); - } -#if DEBUG + try + { + // Since the socket is in blocking mode this will always complete + // after ALL the requested number of bytes was transferred. + _streamSocket.Send(buffer, offset, size, SocketFlags.None); + } + catch (Exception exception) when (!(exception is OutOfMemoryException)) + { + // Some sort of error occurred on the socket call, + // set the SocketException as InnerException and throw. + throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } -#endif } public override void Write(ReadOnlySpan buffer) @@ -412,61 +360,42 @@ public override void Write(ReadOnlySpan buffer) public void Close(int timeout) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) + if (timeout < -1) { -#endif - if (timeout < -1) - { - throw new ArgumentOutOfRangeException(nameof(timeout)); - } - _closeTimeout = timeout; - Dispose(); -#if DEBUG + throw new ArgumentOutOfRangeException(nameof(timeout)); } -#endif + _closeTimeout = timeout; + Dispose(); } private volatile bool _disposed = false; protected override void Dispose(bool disposing) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) + // Mark this as disposed before changing anything else. + bool disposed = _disposed; + _disposed = true; + if (!disposed && disposing) { -#endif - // Mark this as disposed before changing anything else. - bool disposed = _disposed; - _disposed = true; - if (!disposed && disposing) + // The only resource we need to free is the network stream, since this + // is based on the client socket, closing the stream will cause us + // to flush the data to the network, close the stream and (in the + // NetoworkStream code) close the socket as well. + _readable = false; + _writeable = false; + if (_ownsSocket) { - // The only resource we need to free is the network stream, since this - // is based on the client socket, closing the stream will cause us - // to flush the data to the network, close the stream and (in the - // NetoworkStream code) close the socket as well. - _readable = false; - _writeable = false; - if (_ownsSocket) - { - // If we own the Socket (false by default), close it - // ignoring possible exceptions (eg: the user told us - // that we own the Socket but it closed at some point of time, - // here we would get an ObjectDisposedException) - _streamSocket.InternalShutdown(SocketShutdown.Both); - _streamSocket.Close(_closeTimeout); - } + // If we own the Socket (false by default), close it + // ignoring possible exceptions (eg: the user told us + // that we own the Socket but it closed at some point of time, + // here we would get an ObjectDisposedException) + _streamSocket.InternalShutdown(SocketShutdown.Both); + _streamSocket.Close(_closeTimeout); } -#if DEBUG } -#endif + base.Dispose(disposing); } - ~NetworkStream() - { -#if DEBUG - DebugThreadTracking.SetThreadSource(ThreadKinds.Finalization); -#endif - Dispose(false); - } + ~NetworkStream() => Dispose(false); // BeginRead - provide async read functionality. // @@ -484,50 +413,43 @@ protected override void Dispose(bool disposing) // An IASyncResult, representing the read. public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback? callback, object? state) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + bool canRead = CanRead; // Prevent race with Dispose. + ThrowIfDisposed(); + if (!canRead) { -#endif - bool canRead = CanRead; // Prevent race with Dispose. - ThrowIfDisposed(); - if (!canRead) - { - throw new InvalidOperationException(SR.net_writeonlystream); - } + throw new InvalidOperationException(SR.net_writeonlystream); + } - // Validate input parameters. - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - if ((uint)offset > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } - if ((uint)size > buffer.Length - offset) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } + // Validate input parameters. + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + if ((uint)offset > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if ((uint)size > buffer.Length - offset) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } - try - { - return _streamSocket.BeginReceive( - buffer, - offset, - size, - SocketFlags.None, - callback, - state); - } - catch (Exception exception) when (!(exception is OutOfMemoryException)) - { - // Some sort of error occurred on the socket call, - // set the SocketException as InnerException and throw. - throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception); - } -#if DEBUG + try + { + return _streamSocket.BeginReceive( + buffer, + offset, + size, + SocketFlags.None, + callback, + state); + } + catch (Exception exception) when (!(exception is OutOfMemoryException)) + { + // Some sort of error occurred on the socket call, + // set the SocketException as InnerException and throw. + throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } -#endif } // EndRead - handle the end of an async read. @@ -540,31 +462,24 @@ public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, Asyn // The number of bytes read. May throw an exception. public override int EndRead(IAsyncResult asyncResult) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) - { -#endif - ThrowIfDisposed(); + ThrowIfDisposed(); - // Validate input parameters. - if (asyncResult == null) - { - throw new ArgumentNullException(nameof(asyncResult)); - } + // Validate input parameters. + if (asyncResult == null) + { + throw new ArgumentNullException(nameof(asyncResult)); + } - try - { - return _streamSocket.EndReceive(asyncResult); - } - catch (Exception exception) when (!(exception is OutOfMemoryException)) - { - // Some sort of error occurred on the socket call, - // set the SocketException as InnerException and throw. - throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception); - } -#if DEBUG + try + { + return _streamSocket.EndReceive(asyncResult); + } + catch (Exception exception) when (!(exception is OutOfMemoryException)) + { + // Some sort of error occurred on the socket call, + // set the SocketException as InnerException and throw. + throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } -#endif } // BeginWrite - provide async write functionality. @@ -583,51 +498,44 @@ public override int EndRead(IAsyncResult asyncResult) // An IASyncResult, representing the write. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback? callback, object? state) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) + bool canWrite = CanWrite; // Prevent race with Dispose. + ThrowIfDisposed(); + if (!canWrite) { -#endif - bool canWrite = CanWrite; // Prevent race with Dispose. - ThrowIfDisposed(); - if (!canWrite) - { - throw new InvalidOperationException(SR.net_readonlystream); - } + throw new InvalidOperationException(SR.net_readonlystream); + } - // Validate input parameters. - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - if ((uint)offset > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } - if ((uint)size > buffer.Length - offset) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } + // Validate input parameters. + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + if ((uint)offset > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if ((uint)size > buffer.Length - offset) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } - try - { - // Call BeginSend on the Socket. - return _streamSocket.BeginSend( - buffer, - offset, - size, - SocketFlags.None, - callback, - state); - } - catch (Exception exception) when (!(exception is OutOfMemoryException)) - { - // Some sort of error occurred on the socket call, - // set the SocketException as InnerException and throw. - throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception); - } -#if DEBUG + try + { + // Call BeginSend on the Socket. + return _streamSocket.BeginSend( + buffer, + offset, + size, + SocketFlags.None, + callback, + state); + } + catch (Exception exception) when (!(exception is OutOfMemoryException)) + { + // Some sort of error occurred on the socket call, + // set the SocketException as InnerException and throw. + throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } -#endif } // Handle the end of an asynchronous write. @@ -636,31 +544,24 @@ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, Asy // Returns: The number of bytes read. May throw an exception. public override void EndWrite(IAsyncResult asyncResult) { -#if DEBUG - using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) - { -#endif - ThrowIfDisposed(); + ThrowIfDisposed(); - // Validate input parameters. - if (asyncResult == null) - { - throw new ArgumentNullException(nameof(asyncResult)); - } + // Validate input parameters. + if (asyncResult == null) + { + throw new ArgumentNullException(nameof(asyncResult)); + } - try - { - _streamSocket.EndSend(asyncResult); - } - catch (Exception exception) when (!(exception is OutOfMemoryException)) - { - // Some sort of error occurred on the socket call, - // set the SocketException as InnerException and throw. - throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception); - } -#if DEBUG + try + { + _streamSocket.EndSend(asyncResult); + } + catch (Exception exception) when (!(exception is OutOfMemoryException)) + { + // Some sort of error occurred on the socket call, + // set the SocketException as InnerException and throw. + throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } -#endif } // ReadAsync - provide async read functionality. diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index 2e3f3d50ada63..e307dc4d6812b 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -188,36 +188,45 @@ private unsafe Socket(SafeSocketHandle handle, bool loadPropertiesFromHandle) { try { - // Local and Remote EP may be different sizes for something like UDS. + // Local and remote end points may be different sizes for protocols like Unix Domain Sockets. bufferLength = buffer.Length; - if (SocketPal.GetPeerName(handle, buffer, ref bufferLength) != SocketError.Success) + switch (SocketPal.GetPeerName(handle, buffer, ref bufferLength)) { - return; - } + case SocketError.Success: + switch (_addressFamily) + { + case AddressFamily.InterNetwork: + _remoteEndPoint = new IPEndPoint( + new IPAddress((long)SocketAddressPal.GetIPv4Address(buffer.Slice(0, bufferLength)) & 0x0FFFFFFFF), + SocketAddressPal.GetPort(buffer)); + break; + + case AddressFamily.InterNetworkV6: + Span address = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes]; + SocketAddressPal.GetIPv6Address(buffer.Slice(0, bufferLength), address, out uint scope); + _remoteEndPoint = new IPEndPoint( + new IPAddress(address, scope), + SocketAddressPal.GetPort(buffer)); + break; + + case AddressFamily.Unix: + socketAddress = new Internals.SocketAddress(_addressFamily, buffer.Slice(0, bufferLength)); + _remoteEndPoint = new UnixDomainSocketEndPoint(IPEndPointExtensions.GetNetSocketAddress(socketAddress)); + break; + } - switch (_addressFamily) - { - case AddressFamily.InterNetwork: - _remoteEndPoint = new IPEndPoint( - new IPAddress((long)SocketAddressPal.GetIPv4Address(buffer.Slice(0, bufferLength)) & 0x0FFFFFFFF), - SocketAddressPal.GetPort(buffer)); - break; - - case AddressFamily.InterNetworkV6: - Span address = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes]; - SocketAddressPal.GetIPv6Address(buffer.Slice(0, bufferLength), address, out uint scope); - _remoteEndPoint = new IPEndPoint( - new IPAddress(address, scope), - SocketAddressPal.GetPort(buffer)); + _isConnected = true; break; - case AddressFamily.Unix: - socketAddress = new Internals.SocketAddress(_addressFamily, buffer.Slice(0, bufferLength)); - _remoteEndPoint = new UnixDomainSocketEndPoint(IPEndPointExtensions.GetNetSocketAddress(socketAddress)); + case SocketError.InvalidArgument: + // On some OSes (e.g. macOS), EINVAL means the socket has been shut down. + // This can happen if, for example, socketpair was used and the parent + // process closed its copy of the child's socket. Since we don't know + // whether we're actually connected or not, err on the side of saying + // we're connected. + _isConnected = true; break; } - - _isConnected = true; } catch { } } @@ -1595,7 +1604,7 @@ public int Receive(IList> buffers, SocketFlags socketFlags, o if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"SRC:{LocalEndPoint} DST:{RemoteEndPoint}"); int bytesTransferred; - errorCode = SocketPal.Receive(_handle, buffers, ref socketFlags, out bytesTransferred); + errorCode = SocketPal.Receive(_handle, buffers, socketFlags, out bytesTransferred); #if TRACE_VERBOSE if (NetEventSource.IsEnabled) @@ -1908,7 +1917,7 @@ public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName opti } if (lingerOption.LingerTime < 0 || lingerOption.LingerTime > (int)ushort.MaxValue) { - throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 0, (int)ushort.MaxValue), "optionValue.LingerTime"); + throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper_Named, 0, (int)ushort.MaxValue, "optionValue.LingerTime"), nameof(optionValue)); } SetLingerOption(lingerOption); } @@ -3816,7 +3825,7 @@ public bool AcceptAsync(SocketAsyncEventArgs e) } if (e.HasMultipleBuffers) { - throw new ArgumentException(SR.net_multibuffernotsupported, "BufferList"); + throw new ArgumentException(SR.net_multibuffernotsupported, nameof(e)); } if (_rightEndPoint == null) { @@ -3979,11 +3988,11 @@ public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType } if (e.HasMultipleBuffers) { - throw new ArgumentException(SR.net_multibuffernotsupported, "BufferList"); + throw new ArgumentException(SR.net_multibuffernotsupported, nameof(e)); } if (e.RemoteEndPoint == null) { - throw new ArgumentNullException("remoteEP"); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e)); } EndPoint endPointSnapshot = e.RemoteEndPoint; @@ -4116,11 +4125,11 @@ public bool ReceiveFromAsync(SocketAsyncEventArgs e) } if (e.RemoteEndPoint == null) { - throw new ArgumentNullException(nameof(e.RemoteEndPoint)); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e)); } if (!CanTryAddressFamily(e.RemoteEndPoint.AddressFamily)) { - throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), "RemoteEndPoint"); + throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), nameof(e)); } SocketPal.CheckDualModeReceiveSupport(this); @@ -4166,11 +4175,11 @@ public bool ReceiveMessageFromAsync(SocketAsyncEventArgs e) } if (e.RemoteEndPoint == null) { - throw new ArgumentNullException(nameof(e.RemoteEndPoint)); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e)); } if (!CanTryAddressFamily(e.RemoteEndPoint.AddressFamily)) { - throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), "RemoteEndPoint"); + throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), nameof(e)); } SocketPal.CheckDualModeReceiveSupport(this); @@ -4250,7 +4259,7 @@ public bool SendPacketsAsync(SocketAsyncEventArgs e) } if (e.SendPacketsElements == null) { - throw new ArgumentNullException("e.SendPacketsElements"); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.SendPacketsElements"), nameof(e)); } if (!Connected) { @@ -4288,7 +4297,7 @@ public bool SendToAsync(SocketAsyncEventArgs e) } if (e.RemoteEndPoint == null) { - throw new ArgumentNullException(nameof(RemoteEndPoint)); + throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e)); } // Prepare SocketAddress diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs index 1e4242a251ab4..a35d181f32839 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs @@ -126,17 +126,12 @@ private enum State public readonly SocketAsyncContext AssociatedContext; public AsyncOperation Next = null!; // initialized by helper called from ctor - protected object? CallbackOrEvent; public SocketError ErrorCode; public byte[]? SocketAddress; public int SocketAddressLen; public CancellationTokenRegistration CancellationRegistration; - public ManualResetEventSlim? Event - { - get { return CallbackOrEvent as ManualResetEventSlim; } - set { CallbackOrEvent = value; } - } + public ManualResetEventSlim? Event { get; set; } public AsyncOperation(SocketAsyncContext context) { @@ -147,6 +142,7 @@ public AsyncOperation(SocketAsyncContext context) public void Reset() { _state = (int)State.Waiting; + Event = null; Next = this; #if DEBUG _callbackQueued = 0; @@ -240,10 +236,10 @@ public bool TryCancel() // It's our responsibility to set the error code and queue the completion. DoAbort(); - var @event = CallbackOrEvent as ManualResetEventSlim; - if (@event != null) + ManualResetEventSlim? e = Event; + if (e != null) { - @event.Set(); + e.Set(); } else { @@ -360,13 +356,10 @@ private abstract class SendOperation : WriteOperation protected sealed override void Abort() { } - public Action? Callback - { - set => CallbackOrEvent = value; - } + public Action? Callback { get; set; } public override void InvokeCallback(bool allowPooling) => - ((Action)CallbackOrEvent!)(BytesTransferred, SocketAddress, SocketAddressLen, SocketFlags.None, ErrorCode); + Callback!(BytesTransferred, SocketAddress, SocketAddressLen, SocketFlags.None, ErrorCode); } private sealed class BufferMemorySendOperation : SendOperation @@ -383,7 +376,7 @@ protected override bool DoTryComplete(SocketAsyncContext context) public override void InvokeCallback(bool allowPooling) { - var cb = (Action)CallbackOrEvent!; + var cb = Callback!; int bt = BytesTransferred; byte[]? sa = SocketAddress; int sal = SocketAddressLen; @@ -412,7 +405,7 @@ protected override bool DoTryComplete(SocketAsyncContext context) public override void InvokeCallback(bool allowPooling) { - var cb = (Action)CallbackOrEvent!; + var cb = Callback!; int bt = BytesTransferred; byte[]? sa = SocketAddress; int sal = SocketAddressLen; @@ -450,19 +443,16 @@ private abstract class ReceiveOperation : ReadOperation protected sealed override void Abort() { } - public Action? Callback - { - set => CallbackOrEvent = value; - } + public Action? Callback { get; set; } public override void InvokeCallback(bool allowPooling) => - ((Action)CallbackOrEvent!)( - BytesTransferred, SocketAddress, SocketAddressLen, ReceivedFlags, ErrorCode); + Callback!(BytesTransferred, SocketAddress, SocketAddressLen, ReceivedFlags, ErrorCode); } private sealed class BufferMemoryReceiveOperation : ReceiveOperation { public Memory Buffer; + public bool SetReceivedFlags; public BufferMemoryReceiveOperation(SocketAsyncContext context) : base(context) { } @@ -479,13 +469,23 @@ protected override bool DoTryComplete(SocketAsyncContext context) } else { - return SocketPal.TryCompleteReceiveFrom(context._socket, Buffer.Span, null, Flags, SocketAddress, ref SocketAddressLen, out BytesTransferred, out ReceivedFlags, out ErrorCode); + if (!SetReceivedFlags) + { + Debug.Assert(SocketAddress == null); + + ReceivedFlags = SocketFlags.None; + return SocketPal.TryCompleteReceive(context._socket, Buffer.Span, Flags, out BytesTransferred, out ErrorCode); + } + else + { + return SocketPal.TryCompleteReceiveFrom(context._socket, Buffer.Span, null, Flags, SocketAddress, ref SocketAddressLen, out BytesTransferred, out ReceivedFlags, out ErrorCode); + } } } public override void InvokeCallback(bool allowPooling) { - var cb = (Action)CallbackOrEvent!; + var cb = Callback!; int bt = BytesTransferred; byte[]? sa = SocketAddress; int sal = SocketAddressLen; @@ -512,7 +512,7 @@ private sealed class BufferListReceiveOperation : ReceiveOperation public override void InvokeCallback(bool allowPooling) { - var cb = (Action)CallbackOrEvent!; + var cb = Callback!; int bt = BytesTransferred; byte[]? sa = SocketAddress; int sal = SocketAddressLen; @@ -555,17 +555,13 @@ private sealed class ReceiveMessageFromOperation : ReadOperation protected sealed override void Abort() { } - public Action Callback - { - set => CallbackOrEvent = value; - } + public Action? Callback { get; set; } protected override bool DoTryComplete(SocketAsyncContext context) => SocketPal.TryCompleteReceiveMessageFrom(context._socket, Buffer.Span, Buffers, Flags, SocketAddress!, ref SocketAddressLen, IsIPv4, IsIPv6, out BytesTransferred, out ReceivedFlags, out IPPacketInformation, out ErrorCode); public override void InvokeCallback(bool allowPooling) => - ((Action)CallbackOrEvent!)( - BytesTransferred, SocketAddress!, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode); + Callback!(BytesTransferred, SocketAddress!, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode); } private sealed class AcceptOperation : ReadOperation @@ -574,10 +570,7 @@ private sealed class AcceptOperation : ReadOperation public AcceptOperation(SocketAsyncContext context) : base(context) { } - public Action? Callback - { - set => CallbackOrEvent = value; - } + public Action? Callback { get; set; } protected override void Abort() => AcceptedFileDescriptor = (IntPtr)(-1); @@ -591,7 +584,7 @@ protected override bool DoTryComplete(SocketAsyncContext context) public override void InvokeCallback(bool allowPooling) { - var cb = (Action)CallbackOrEvent!; + var cb = Callback!; IntPtr fd = AcceptedFileDescriptor; byte[] sa = SocketAddress!; int sal = SocketAddressLen; @@ -610,10 +603,7 @@ private sealed class ConnectOperation : WriteOperation { public ConnectOperation(SocketAsyncContext context) : base(context) { } - public Action Callback - { - set => CallbackOrEvent = value; - } + public Action? Callback { get; set; } protected override void Abort() { } @@ -625,7 +615,7 @@ protected override bool DoTryComplete(SocketAsyncContext context) } public override void InvokeCallback(bool allowPooling) => - ((Action)CallbackOrEvent!)(ErrorCode); + Callback!(ErrorCode); } private sealed class SendFileOperation : WriteOperation @@ -639,13 +629,10 @@ private sealed class SendFileOperation : WriteOperation protected override void Abort() { } - public Action Callback - { - set => CallbackOrEvent = value; - } + public Action? Callback { get; set; } public override void InvokeCallback(bool allowPooling) => - ((Action)CallbackOrEvent!)(BytesTransferred, ErrorCode); + Callback!(BytesTransferred, ErrorCode); protected override bool DoTryComplete(SocketAsyncContext context) => SocketPal.TryCompleteSendFile(context._socket, FileHandle, ref Offset, ref Count, ref BytesTransferred, out ErrorCode); @@ -1465,13 +1452,13 @@ public SocketError ConnectAsync(byte[] socketAddress, int socketAddressLen, Acti return SocketError.IOPending; } - public SocketError Receive(Memory buffer, ref SocketFlags flags, int timeout, out int bytesReceived) + public SocketError Receive(Memory buffer, SocketFlags flags, int timeout, out int bytesReceived) { int socketAddressLen = 0; return ReceiveFrom(buffer, ref flags, null, ref socketAddressLen, timeout, out bytesReceived); } - public SocketError Receive(Span buffer, ref SocketFlags flags, int timeout, out int bytesReceived) + public SocketError Receive(Span buffer, SocketFlags flags, int timeout, out int bytesReceived) { int socketAddressLen = 0; return ReceiveFrom(buffer, ref flags, null, ref socketAddressLen, timeout, out bytesReceived); @@ -1545,6 +1532,39 @@ public unsafe SocketError ReceiveFrom(Span buffer, ref SocketFlags flags, } } + public SocketError ReceiveAsync(Memory buffer, SocketFlags flags, out int bytesReceived, Action callback, CancellationToken cancellationToken = default) + { + SetNonBlocking(); + + SocketError errorCode; + int observedSequenceNumber; + if (_receiveQueue.IsReady(this, out observedSequenceNumber) && + SocketPal.TryCompleteReceive(_socket, buffer.Span, flags, out bytesReceived, out errorCode)) + { + return errorCode; + } + + BufferMemoryReceiveOperation operation = RentBufferMemoryReceiveOperation(); + operation.SetReceivedFlags = false; + operation.Callback = callback; + operation.Buffer = buffer; + operation.Flags = flags; + operation.SocketAddress = null; + operation.SocketAddressLen = 0; + + if (!_receiveQueue.StartAsyncOperation(this, operation, observedSequenceNumber, cancellationToken)) + { + bytesReceived = operation.BytesTransferred; + errorCode = operation.ErrorCode; + + ReturnOperation(operation); + return errorCode; + } + + bytesReceived = 0; + return SocketError.IOPending; + } + public SocketError ReceiveFromAsync(Memory buffer, SocketFlags flags, byte[]? socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, Action callback, CancellationToken cancellationToken = default) { SetNonBlocking(); @@ -1558,6 +1578,7 @@ public SocketError ReceiveFromAsync(Memory buffer, SocketFlags flags, byt } BufferMemoryReceiveOperation operation = RentBufferMemoryReceiveOperation(); + operation.SetReceivedFlags = true; operation.Callback = callback; operation.Buffer = buffer; operation.Flags = flags; @@ -1579,7 +1600,7 @@ public SocketError ReceiveFromAsync(Memory buffer, SocketFlags flags, byt return SocketError.IOPending; } - public SocketError Receive(IList> buffers, ref SocketFlags flags, int timeout, out int bytesReceived) + public SocketError Receive(IList> buffers, SocketFlags flags, int timeout, out int bytesReceived) { return ReceiveFrom(buffers, ref flags, null, 0, timeout, out bytesReceived); } @@ -1995,7 +2016,8 @@ public SocketError SendFileAsync(SafeFileHandle fileHandle, long offset, long co // be scheduled instead. It's not functionally incorrect to schedule the release of a synchronous operation, just it may // lead to thread pool starvation issues if the synchronous operations are blocking thread pool threads (typically not // advised) and more threads are not immediately available to run work items that would release those operations. - public unsafe Interop.Sys.SocketEvents HandleSyncEventsSpeculatively(Interop.Sys.SocketEvents events) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Interop.Sys.SocketEvents HandleSyncEventsSpeculatively(Interop.Sys.SocketEvents events) { if ((events & Interop.Sys.SocketEvents.Error) != 0) { diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs index 26a8be4bf128a..053cc4fcb6f77 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs @@ -2,13 +2,11 @@ // 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.Collections.Concurrent; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; -using System.Threading.Tasks; namespace System.Net.Sockets { @@ -56,22 +54,40 @@ public bool TryRegister(SafeSocketHandle socket, out Interop.Error error) private static readonly object s_lock = new object(); - // In debug builds, force there to be 2 engines. In release builds, use half the number of processors when - // there are at least 6. The lower bound is to avoid using multiple engines on systems which aren't servers. -#pragma warning disable CA1802 // const works for debug, but needs to be static readonly for release - private static readonly int s_engineCount = -#if DEBUG - 2; -#else - Environment.ProcessorCount >= 6 ? Environment.ProcessorCount / 2 : 1; -#endif -#pragma warning restore CA1802 + private static readonly int s_maxEngineCount = GetEngineCount(); + + private static int GetEngineCount() + { + // The responsibility of SocketAsyncEngine is to get notifications from epoll|kqueue + // and schedule corresponding work items to ThreadPool (socket reads and writes). + // + // Using TechEmpower benchmarks that generate a LOT of SMALL socket reads and writes under a VERY HIGH load + // we have observed that a single engine is capable of keeping busy up to thirty x64 and eight ARM64 CPU Cores. + // + // The vast majority of real-life scenarios is never going to generate such a huge load (hundreds of thousands of requests per second) + // and having a single producer should be almost always enough. + // + // We want to be sure that we can handle extreme loads and that's why we have decided to use these values. + // + // It's impossible to predict all possible scenarios so we have added a possibility to configure this value using environment variables. + if (uint.TryParse(Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_SOCKETS_THREAD_COUNT"), out uint count)) + { + return (int)count; + } + + Architecture architecture = RuntimeInformation.ProcessArchitecture; + int coresPerEngine = architecture == Architecture.Arm64 || architecture == Architecture.Arm + ? 8 + : 30; + + return Math.Max(1, (int)Math.Round(Environment.ProcessorCount / (double)coresPerEngine)); + } // // The current engines. We replace an engine when it runs out of "handle" values. // Must be accessed under s_lock. // - private static readonly SocketAsyncEngine?[] s_currentEngines = new SocketAsyncEngine?[s_engineCount]; + private static readonly SocketAsyncEngine?[] s_currentEngines = new SocketAsyncEngine?[s_maxEngineCount]; private static int s_allocateFromEngine = 0; private readonly IntPtr _port; @@ -106,8 +122,6 @@ public bool TryRegister(SafeSocketHandle socket, out Interop.Error error) // private static readonly IntPtr MaxHandles = IntPtr.Size == 4 ? (IntPtr)int.MaxValue : (IntPtr)long.MaxValue; #endif - private static readonly IntPtr MinHandlesForAdditionalEngine = s_engineCount == 1 ? MaxHandles : (IntPtr)32; - // // Sentinel handle value to identify events from the "shutdown pipe," used to signal an event loop to stop // processing events. @@ -120,16 +134,10 @@ public bool TryRegister(SafeSocketHandle socket, out Interop.Error error) // private IntPtr _nextHandle; - // - // Count of handles that have been allocated for this event port, but not yet freed. - // Must be accessed under s_lock. - // - private IntPtr _outstandingHandles; - // // Maps handle values to SocketAsyncContext instances. // - private readonly ConcurrentDictionary _handleToContextMap = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _handleToContextMap = new ConcurrentDictionary(); // // Queue of events generated by EventLoop() that would be processed by the thread pool @@ -149,16 +157,6 @@ public bool TryRegister(SafeSocketHandle socket, out Interop.Error error) // private bool IsFull { get { return _nextHandle == MaxHandles; } } - // True if we've don't have sufficient active sockets to allow allocating a new engine. - private bool HasLowNumberOfSockets - { - get - { - return IntPtr.Size == 4 ? _outstandingHandles.ToInt32() < MinHandlesForAdditionalEngine.ToInt32() : - _outstandingHandles.ToInt64() < MinHandlesForAdditionalEngine.ToInt64(); - } - } - // // Allocates a new {SocketAsyncEngine, handle} pair. // @@ -169,21 +167,7 @@ private static void AllocateToken(SocketAsyncContext context, out SocketAsyncEng engine = s_currentEngines[s_allocateFromEngine]; if (engine == null) { - // We minimize the number of engines on applications that have a low number of concurrent sockets. - for (int i = 0; i < s_allocateFromEngine; i++) - { - var previousEngine = s_currentEngines[i]; - if (previousEngine == null || previousEngine.HasLowNumberOfSockets) - { - s_allocateFromEngine = i; - engine = previousEngine; - break; - } - } - if (engine == null) - { - s_currentEngines[s_allocateFromEngine] = engine = new SocketAsyncEngine(); - } + s_currentEngines[s_allocateFromEngine] = engine = new SocketAsyncEngine(); } handle = engine.AllocateHandle(context); @@ -195,10 +179,7 @@ private static void AllocateToken(SocketAsyncContext context, out SocketAsyncEng } // Round-robin to the next engine once we have sufficient sockets on this one. - if (!engine.HasLowNumberOfSockets) - { - s_allocateFromEngine = (s_allocateFromEngine + 1) % s_engineCount; - } + s_allocateFromEngine = (s_allocateFromEngine + 1) % s_maxEngineCount; } } @@ -208,12 +189,11 @@ private IntPtr AllocateHandle(SocketAsyncContext context) Debug.Assert(!IsFull, "Expected !IsFull"); IntPtr handle = _nextHandle; - _handleToContextMap.TryAdd(handle, context); - + Debug.Assert(handle != ShutdownHandle, "ShutdownHandle must not be added to the dictionary"); + bool added = _handleToContextMap.TryAdd(handle, new SocketAsyncContextWrapper(context)); + Debug.Assert(added, "Add should always succeed"); _nextHandle = IntPtr.Add(_nextHandle, 1); - _outstandingHandles = IntPtr.Add(_outstandingHandles, 1); - Debug.Assert(handle != ShutdownHandle, $"Expected handle != ShutdownHandle: {handle}"); return handle; } @@ -227,14 +207,11 @@ private void FreeHandle(IntPtr handle) { if (_handleToContextMap.TryRemove(handle, out _)) { - _outstandingHandles = IntPtr.Subtract(_outstandingHandles, 1); - Debug.Assert(_outstandingHandles.ToInt64() >= 0, $"Unexpected _outstandingHandles: {_outstandingHandles}"); - // // If we've allocated all possible handles for this instance, and freed them all, then // we don't need the event loop any more, and can reclaim resources. // - if (IsFull && _outstandingHandles == IntPtr.Zero) + if (IsFull && _handleToContextMap.IsEmpty) { shutdownNeeded = true; } @@ -318,8 +295,10 @@ private void EventLoop() { bool shutdown = false; Interop.Sys.SocketEvent* buffer = _buffer; - ConcurrentDictionary handleToContextMap = _handleToContextMap; + ConcurrentDictionary handleToContextMap = _handleToContextMap; ConcurrentQueue eventQueue = _eventQueue; + IntPtr shutdownHandle = ShutdownHandle; + SocketAsyncContext? context = null; while (!shutdown) { int numEvents = EventBufferCount; @@ -333,38 +312,36 @@ private void EventLoop() Debug.Assert(numEvents > 0, $"Unexpected numEvents: {numEvents}"); bool enqueuedEvent = false; - for (int i = 0; i < numEvents; i++) + foreach (var socketEvent in new ReadOnlySpan(buffer, numEvents)) { - IntPtr handle = buffer[i].Data; - if (handle == ShutdownHandle) - { - shutdown = true; - } - else + IntPtr handle = socketEvent.Data; + + if (handleToContextMap.TryGetValue(handle, out SocketAsyncContextWrapper contextWrapper) && (context = contextWrapper.Context) != null) { Debug.Assert(handle.ToInt64() < MaxHandles.ToInt64(), $"Unexpected values: handle={handle}, MaxHandles={MaxHandles}"); - handleToContextMap.TryGetValue(handle, out SocketAsyncContext? context); - if (context != null) + + Interop.Sys.SocketEvents events = context.HandleSyncEventsSpeculatively(socketEvent.Events); + if (events != Interop.Sys.SocketEvents.None) { - Interop.Sys.SocketEvents events = buffer[i].Events; - events = context.HandleSyncEventsSpeculatively(events); - if (events != Interop.Sys.SocketEvents.None) - { - var ev = new SocketIOEvent(context, events); - eventQueue.Enqueue(ev); - enqueuedEvent = true; - - // This is necessary when the JIT generates unoptimized code (debug builds, live debugging, - // quick JIT, etc.) to ensure that the context does not remain referenced by this method, as - // such code may keep the stack location live for longer than necessary - ev = default; - } + var ev = new SocketIOEvent(context, events); + eventQueue.Enqueue(ev); + enqueuedEvent = true; // This is necessary when the JIT generates unoptimized code (debug builds, live debugging, // quick JIT, etc.) to ensure that the context does not remain referenced by this method, as // such code may keep the stack location live for longer than necessary - context = null; + ev = default; } + + // This is necessary when the JIT generates unoptimized code (debug builds, live debugging, + // quick JIT, etc.) to ensure that the context does not remain referenced by this method, as + // such code may keep the stack location live for longer than necessary + context = null; + contextWrapper = default; + } + else if (handle == shutdownHandle) + { + shutdown = true; } } @@ -488,6 +465,18 @@ private bool TryRegister(SafeSocketHandle socket, IntPtr handle, out Interop.Err return error == Interop.Error.SUCCESS; } + // struct wrapper is used in order to improve the performance of the epoll thread hot path by up to 3% of some TechEmpower benchmarks + // the goal is to have a dedicated generic instantiation and using: + // System.Collections.Concurrent.ConcurrentDictionary`2[System.IntPtr,System.Net.Sockets.SocketAsyncContextWrapper]::TryGetValueInternal(!0,int32,!1&) + // instead of: + // System.Collections.Concurrent.ConcurrentDictionary`2[System.IntPtr,System.__Canon]::TryGetValueInternal(!0,int32,!1&) + private readonly struct SocketAsyncContextWrapper + { + public SocketAsyncContextWrapper(SocketAsyncContext context) => Context = context; + + internal SocketAsyncContext Context { get; } + } + private readonly struct SocketIOEvent { public SocketAsyncContext Context { get; } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Unix.cs index d2ca491a52ae9..99147f05a429c 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Unix.cs @@ -128,7 +128,17 @@ internal unsafe SocketError DoOperationReceive(SafeSocketHandle handle, Cancella SocketError errorCode; if (_bufferList == null) { - errorCode = handle.AsyncContext.ReceiveAsync(_buffer.Slice(_offset, _count), _socketFlags, out bytesReceived, out flags, TransferCompletionCallback, cancellationToken); + // TCP has no out-going receive flags. We can use different syscalls which give better performance. + bool noReceivedFlags = _currentSocket!.ProtocolType == ProtocolType.Tcp; + if (noReceivedFlags) + { + errorCode = handle.AsyncContext.ReceiveAsync(_buffer.Slice(_offset, _count), _socketFlags, out bytesReceived, TransferCompletionCallback, cancellationToken); + flags = SocketFlags.None; + } + else + { + errorCode = handle.AsyncContext.ReceiveAsync(_buffer.Slice(_offset, _count), _socketFlags, out bytesReceived, out flags, TransferCompletionCallback, cancellationToken); + } } else { diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs index 68f8c82df2956..f174b732c2552 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs @@ -96,7 +96,29 @@ public static unsafe SocketError CreateSocket(AddressFamily addressFamily, Socke return errorCode; } - private static unsafe int Receive(SafeSocketHandle socket, SocketFlags flags, Span buffer, byte[]? socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno) + private static unsafe int SysReceive(SafeSocketHandle socket, SocketFlags flags, Span buffer, out Interop.Error errno) + { + int received = 0; + + fixed (byte* b = &MemoryMarshal.GetReference(buffer)) + { + errno = Interop.Sys.Receive( + socket, + b, + buffer.Length, + flags, + &received); + } + + if (errno != Interop.Error.SUCCESS) + { + return -1; + } + + return received; + } + + private static unsafe int SysReceive(SafeSocketHandle socket, SocketFlags flags, Span buffer, byte[]? socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno) { Debug.Assert(socketAddress != null || socketAddressLen == 0, $"Unexpected values: socketAddress={socketAddress}, socketAddressLen={socketAddressLen}"); @@ -137,7 +159,30 @@ private static unsafe int Receive(SafeSocketHandle socket, SocketFlags flags, Sp return checked((int)received); } - private static unsafe int Send(SafeSocketHandle socket, SocketFlags flags, ReadOnlySpan buffer, ref int offset, ref int count, byte[]? socketAddress, int socketAddressLen, out Interop.Error errno) + private static unsafe int SysSend(SafeSocketHandle socket, SocketFlags flags, ReadOnlySpan buffer, ref int offset, ref int count, out Interop.Error errno) + { + int sent; + fixed (byte* b = &MemoryMarshal.GetReference(buffer)) + { + errno = Interop.Sys.Send( + socket, + &b[offset], + count, + flags, + &sent); + } + + if (errno != Interop.Error.SUCCESS) + { + return -1; + } + + offset += sent; + count -= sent; + return sent; + } + + private static unsafe int SysSend(SafeSocketHandle socket, SocketFlags flags, ReadOnlySpan buffer, ref int offset, ref int count, byte[] socketAddress, int socketAddressLen, out Interop.Error errno) { int sent; fixed (byte* sockAddr = socketAddress) @@ -177,7 +222,7 @@ private static unsafe int Send(SafeSocketHandle socket, SocketFlags flags, ReadO return sent; } - private static unsafe int Send(SafeSocketHandle socket, SocketFlags flags, IList> buffers, ref int bufferIndex, ref int offset, byte[]? socketAddress, int socketAddressLen, out Interop.Error errno) + private static unsafe int SysSend(SafeSocketHandle socket, SocketFlags flags, IList> buffers, ref int bufferIndex, ref int offset, byte[]? socketAddress, int socketAddressLen, out Interop.Error errno) { // Pin buffers and set up iovecs. int startIndex = bufferIndex, startOffset = offset; @@ -274,7 +319,7 @@ private static unsafe long SendFile(SafeSocketHandle socket, SafeFileHandle file return bytesSent; } - private static unsafe int Receive(SafeSocketHandle socket, SocketFlags flags, IList> buffers, byte[]? socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno) + private static unsafe int SysReceive(SafeSocketHandle socket, SocketFlags flags, IList> buffers, byte[]? socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno) { int available = 0; errno = Interop.Sys.GetBytesAvailable(socket, &available); @@ -373,7 +418,7 @@ private static unsafe int Receive(SafeSocketHandle socket, SocketFlags flags, IL return checked((int)received); } - private static unsafe int ReceiveMessageFrom(SafeSocketHandle socket, SocketFlags flags, Span buffer, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, out SocketFlags receivedFlags, out IPPacketInformation ipPacketInformation, out Interop.Error errno) + private static unsafe int SysReceiveMessageFrom(SafeSocketHandle socket, SocketFlags flags, Span buffer, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, out SocketFlags receivedFlags, out IPPacketInformation ipPacketInformation, out Interop.Error errno) { Debug.Assert(socketAddress != null, "Expected non-null socketAddress"); @@ -423,7 +468,7 @@ private static unsafe int ReceiveMessageFrom(SafeSocketHandle socket, SocketFlag return checked((int)received); } - private static unsafe int ReceiveMessageFrom( + private static unsafe int SysReceiveMessageFrom( SafeSocketHandle socket, SocketFlags flags, IList> buffers, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, out SocketFlags receivedFlags, out IPPacketInformation ipPacketInformation, out Interop.Error errno) @@ -617,6 +662,60 @@ public static unsafe bool TryCompleteConnect(SafeSocketHandle socket, int socket public static bool TryCompleteReceiveFrom(SafeSocketHandle socket, IList> buffers, SocketFlags flags, byte[]? socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode) => TryCompleteReceiveFrom(socket, default(Span), buffers, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode); + public static unsafe bool TryCompleteReceive(SafeSocketHandle socket, Span buffer, SocketFlags flags, out int bytesReceived, out SocketError errorCode) + { + try + { + Interop.Error errno; + int received; + + if (buffer.Length == 0) + { + // Special case a receive of 0 bytes into a single buffer. A common pattern is to ReceiveAsync 0 bytes in order + // to be asynchronously notified when data is available, without needing to dedicate a buffer. Some platforms (e.g. macOS), + // however complete a 0-byte read successfully when data isn't available, as the request can logically be satisfied + // synchronously. As such, we treat 0 specially, and perform a 1-byte peek. + byte oneBytePeekBuffer; + received = SysReceive(socket, flags | SocketFlags.Peek, new Span(&oneBytePeekBuffer, 1), out errno); + if (received > 0) + { + // Peeked for 1-byte, but the actual request was for 0. + received = 0; + } + } + else + { + // Receive > 0 bytes into a single buffer + received = SysReceive(socket, flags, buffer, out errno); + } + + if (received != -1) + { + bytesReceived = received; + errorCode = SocketError.Success; + return true; + } + + bytesReceived = 0; + + if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK) + { + errorCode = GetSocketErrorForErrorCode(errno); + return true; + } + + errorCode = SocketError.Success; + return false; + } + catch (ObjectDisposedException) + { + // The socket was closed, or is closing. + bytesReceived = 0; + errorCode = SocketError.OperationAborted; + return true; + } + } + public static unsafe bool TryCompleteReceiveFrom(SafeSocketHandle socket, Span buffer, IList>? buffers, SocketFlags flags, byte[]? socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode) { try @@ -627,7 +726,7 @@ public static unsafe bool TryCompleteReceiveFrom(SafeSocketHandle socket, Span(&oneBytePeekBuffer, 1), socketAddress, ref socketAddressLen, out receivedFlags, out errno); + received = SysReceive(socket, flags | SocketFlags.Peek, new Span(&oneBytePeekBuffer, 1), socketAddress, ref socketAddressLen, out receivedFlags, out errno); if (received > 0) { // Peeked for 1-byte, but the actual request was for 0. @@ -646,7 +745,7 @@ public static unsafe bool TryCompleteReceiveFrom(SafeSocketHandle socket, Span 0 bytes into a single buffer - received = Receive(socket, flags, buffer, socketAddress, ref socketAddressLen, out receivedFlags, out errno); + received = SysReceive(socket, flags, buffer, socketAddress, ref socketAddressLen, out receivedFlags, out errno); } if (received != -1) @@ -684,8 +783,8 @@ public static unsafe bool TryCompleteReceiveMessageFrom(SafeSocketHandle socket, Interop.Error errno; int received = buffers == null ? - ReceiveMessageFrom(socket, flags, buffer, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out receivedFlags, out ipPacketInformation, out errno) : - ReceiveMessageFrom(socket, flags, buffers, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out receivedFlags, out ipPacketInformation, out errno); + SysReceiveMessageFrom(socket, flags, buffer, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out receivedFlags, out ipPacketInformation, out errno) : + SysReceiveMessageFrom(socket, flags, buffers, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out receivedFlags, out ipPacketInformation, out errno); if (received != -1) { @@ -746,8 +845,9 @@ public static bool TryCompleteSendTo(SafeSocketHandle socket, ReadOnlySpan try { sent = buffers != null ? - Send(socket, flags, buffers, ref bufferIndex, ref offset, socketAddress, socketAddressLen, out errno) : - Send(socket, flags, buffer, ref offset, ref count, socketAddress, socketAddressLen, out errno); + SysSend(socket, flags, buffers, ref bufferIndex, ref offset, socketAddress, socketAddressLen, out errno) : + socketAddress == null ? SysSend(socket, flags, buffer, ref offset, ref count, out errno) : + SysSend(socket, flags, buffer, ref offset, ref count, socketAddress, socketAddressLen, out errno); } catch (ObjectDisposedException) { @@ -1009,12 +1109,12 @@ public static SocketError SendTo(SafeSocketHandle handle, byte[] buffer, int off return errorCode; } - public static SocketError Receive(SafeSocketHandle handle, IList> buffers, ref SocketFlags socketFlags, out int bytesTransferred) + public static SocketError Receive(SafeSocketHandle handle, IList> buffers, SocketFlags socketFlags, out int bytesTransferred) { SocketError errorCode; if (!handle.IsNonBlocking) { - errorCode = handle.AsyncContext.Receive(buffers, ref socketFlags, handle.ReceiveTimeout, out bytesTransferred); + errorCode = handle.AsyncContext.Receive(buffers, socketFlags, handle.ReceiveTimeout, out bytesTransferred); } else { @@ -1032,12 +1132,11 @@ public static SocketError Receive(SafeSocketHandle handle, byte[] buffer, int of { if (!handle.IsNonBlocking) { - return handle.AsyncContext.Receive(new Memory(buffer, offset, count), ref socketFlags, handle.ReceiveTimeout, out bytesTransferred); + return handle.AsyncContext.Receive(new Memory(buffer, offset, count), socketFlags, handle.ReceiveTimeout, out bytesTransferred); } - int socketAddressLen = 0; SocketError errorCode; - bool completed = TryCompleteReceiveFrom(handle, new Span(buffer, offset, count), socketFlags, null, ref socketAddressLen, out bytesTransferred, out socketFlags, out errorCode); + bool completed = TryCompleteReceive(handle, new Span(buffer, offset, count), socketFlags, out bytesTransferred, out errorCode); return completed ? errorCode : SocketError.WouldBlock; } @@ -1045,12 +1144,11 @@ public static SocketError Receive(SafeSocketHandle handle, Span buffer, So { if (!handle.IsNonBlocking) { - return handle.AsyncContext.Receive(buffer, ref socketFlags, handle.ReceiveTimeout, out bytesTransferred); + return handle.AsyncContext.Receive(buffer, socketFlags, handle.ReceiveTimeout, out bytesTransferred); } - int socketAddressLen = 0; SocketError errorCode; - bool completed = TryCompleteReceiveFrom(handle, buffer, socketFlags, null, ref socketAddressLen, out bytesTransferred, out socketFlags, out errorCode); + bool completed = TryCompleteReceive(handle, buffer, socketFlags, out bytesTransferred, out errorCode); return completed ? errorCode : SocketError.WouldBlock; } @@ -1453,17 +1551,17 @@ public static unsafe SocketError GetLingerOption(SafeSocketHandle handle, out Li public static unsafe SocketError Poll(SafeSocketHandle handle, int microseconds, SelectMode mode, out bool status) { - Interop.Sys.PollEvents inEvent = Interop.Sys.PollEvents.POLLNONE; + Interop.PollEvents inEvent = Interop.PollEvents.POLLNONE; switch (mode) { - case SelectMode.SelectRead: inEvent = Interop.Sys.PollEvents.POLLIN; break; - case SelectMode.SelectWrite: inEvent = Interop.Sys.PollEvents.POLLOUT; break; - case SelectMode.SelectError: inEvent = Interop.Sys.PollEvents.POLLPRI; break; + case SelectMode.SelectRead: inEvent = Interop.PollEvents.POLLIN; break; + case SelectMode.SelectWrite: inEvent = Interop.PollEvents.POLLOUT; break; + case SelectMode.SelectError: inEvent = Interop.PollEvents.POLLPRI; break; } int milliseconds = microseconds == -1 ? -1 : microseconds / 1000; - Interop.Sys.PollEvents outEvents; + Interop.PollEvents outEvents; Interop.Error err = Interop.Sys.Poll(handle, inEvent, milliseconds, out outEvents); if (err != Interop.Error.SUCCESS) { @@ -1473,9 +1571,9 @@ public static unsafe SocketError Poll(SafeSocketHandle handle, int microseconds, switch (mode) { - case SelectMode.SelectRead: status = (outEvents & (Interop.Sys.PollEvents.POLLIN | Interop.Sys.PollEvents.POLLHUP)) != 0; break; - case SelectMode.SelectWrite: status = (outEvents & Interop.Sys.PollEvents.POLLOUT) != 0; break; - case SelectMode.SelectError: status = (outEvents & (Interop.Sys.PollEvents.POLLERR | Interop.Sys.PollEvents.POLLPRI)) != 0; break; + case SelectMode.SelectRead: status = (outEvents & (Interop.PollEvents.POLLIN | Interop.PollEvents.POLLHUP)) != 0; break; + case SelectMode.SelectWrite: status = (outEvents & Interop.PollEvents.POLLOUT) != 0; break; + case SelectMode.SelectError: status = (outEvents & (Interop.PollEvents.POLLERR | Interop.PollEvents.POLLPRI)) != 0; break; default: status = false; break; } return SocketError.Success; @@ -1498,7 +1596,7 @@ public static unsafe SocketError Select(IList? checkRead, IList? checkWrite, ILi const int StackThreshold = 80; // arbitrary limit to avoid too much space on stack if (count < StackThreshold) { - Interop.Sys.PollEvent* eventsOnStack = stackalloc Interop.Sys.PollEvent[count]; + Interop.PollEvent* eventsOnStack = stackalloc Interop.PollEvent[count]; return SelectViaPoll( checkRead, checkReadInitialCount, checkWrite, checkWriteInitialCount, @@ -1507,8 +1605,8 @@ public static unsafe SocketError Select(IList? checkRead, IList? checkWrite, ILi } else { - var eventsOnHeap = new Interop.Sys.PollEvent[count]; - fixed (Interop.Sys.PollEvent* eventsOnHeapPtr = &eventsOnHeap[0]) + var eventsOnHeap = new Interop.PollEvent[count]; + fixed (Interop.PollEvent* eventsOnHeapPtr = &eventsOnHeap[0]) { return SelectViaPoll( checkRead, checkReadInitialCount, @@ -1523,7 +1621,7 @@ public static unsafe SocketError Select(IList? checkRead, IList? checkWrite, ILi IList? checkRead, int checkReadInitialCount, IList? checkWrite, int checkWriteInitialCount, IList? checkError, int checkErrorInitialCount, - Interop.Sys.PollEvent* events, int eventsLength, + Interop.PollEvent* events, int eventsLength, int microseconds) { // Add each of the list's contents to the events array @@ -1534,9 +1632,9 @@ public static unsafe SocketError Select(IList? checkRead, IList? checkWrite, ILi { // In case we can't increase the reference count for each Socket, // we'll unref refAdded Sockets in the finally block ordered: [checkRead, checkWrite, checkError]. - AddToPollArray(events, eventsLength, checkRead, ref offset, Interop.Sys.PollEvents.POLLIN | Interop.Sys.PollEvents.POLLHUP, ref refsAdded); - AddToPollArray(events, eventsLength, checkWrite, ref offset, Interop.Sys.PollEvents.POLLOUT, ref refsAdded); - AddToPollArray(events, eventsLength, checkError, ref offset, Interop.Sys.PollEvents.POLLPRI, ref refsAdded); + AddToPollArray(events, eventsLength, checkRead, ref offset, Interop.PollEvents.POLLIN | Interop.PollEvents.POLLHUP, ref refsAdded); + AddToPollArray(events, eventsLength, checkWrite, ref offset, Interop.PollEvents.POLLOUT, ref refsAdded); + AddToPollArray(events, eventsLength, checkError, ref offset, Interop.PollEvents.POLLPRI, ref refsAdded); Debug.Assert(offset == eventsLength, $"Invalid adds. offset={offset}, eventsLength={eventsLength}."); Debug.Assert(refsAdded == eventsLength, $"Invalid ref adds. refsAdded={refsAdded}, eventsLength={eventsLength}."); @@ -1562,9 +1660,9 @@ public static unsafe SocketError Select(IList? checkRead, IList? checkWrite, ILi } else { - FilterPollList(checkRead, events, checkReadInitialCount - 1, Interop.Sys.PollEvents.POLLIN | Interop.Sys.PollEvents.POLLHUP, ref refsAdded); - FilterPollList(checkWrite, events, checkWriteInitialCount + checkReadInitialCount - 1, Interop.Sys.PollEvents.POLLOUT, ref refsAdded); - FilterPollList(checkError, events, checkErrorInitialCount + checkWriteInitialCount + checkReadInitialCount - 1, Interop.Sys.PollEvents.POLLERR | Interop.Sys.PollEvents.POLLPRI, ref refsAdded); + FilterPollList(checkRead, events, checkReadInitialCount - 1, Interop.PollEvents.POLLIN | Interop.PollEvents.POLLHUP, ref refsAdded); + FilterPollList(checkWrite, events, checkWriteInitialCount + checkReadInitialCount - 1, Interop.PollEvents.POLLOUT, ref refsAdded); + FilterPollList(checkError, events, checkErrorInitialCount + checkWriteInitialCount + checkReadInitialCount - 1, Interop.PollEvents.POLLERR | Interop.PollEvents.POLLPRI, ref refsAdded); } return SocketError.Success; @@ -1580,7 +1678,7 @@ public static unsafe SocketError Select(IList? checkRead, IList? checkWrite, ILi } } - private static unsafe void AddToPollArray(Interop.Sys.PollEvent* arr, int arrLength, IList? socketList, ref int arrOffset, Interop.Sys.PollEvents events, ref int refsAdded) + private static unsafe void AddToPollArray(Interop.PollEvent* arr, int arrLength, IList? socketList, ref int arrOffset, Interop.PollEvents events, ref int refsAdded) { if (socketList == null) return; @@ -1603,12 +1701,12 @@ private static unsafe void AddToPollArray(Interop.Sys.PollEvent* arr, int arrLen bool success = false; socket.InternalSafeHandle.DangerousAddRef(ref success); int fd = (int)socket.InternalSafeHandle.DangerousGetHandle(); - arr[arrOffset++] = new Interop.Sys.PollEvent { Events = events, FileDescriptor = fd }; + arr[arrOffset++] = new Interop.PollEvent { Events = events, FileDescriptor = fd }; refsAdded++; } } - private static unsafe void FilterPollList(IList? socketList, Interop.Sys.PollEvent* arr, int arrEndOffset, Interop.Sys.PollEvents desiredEvents, ref int refsAdded) + private static unsafe void FilterPollList(IList? socketList, Interop.PollEvent* arr, int arrEndOffset, Interop.PollEvents desiredEvents, ref int refsAdded) { if (socketList == null) return; diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs index ed39e9be08b67..6ea3e1cc03aa2 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs @@ -338,7 +338,7 @@ public static unsafe SocketError SendTo(SafeSocketHandle handle, byte[] buffer, return SocketError.Success; } - public static SocketError Receive(SafeSocketHandle handle, IList> buffers, ref SocketFlags socketFlags, out int bytesTransferred) + public static SocketError Receive(SafeSocketHandle handle, IList> buffers, SocketFlags socketFlags, out int bytesTransferred) { const int StackThreshold = 16; // arbitrary limit to avoid too much space on stack (note: may be over-sized, that's OK - length passed separately) int count = buffers.Count; diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs index 9295802ed6977..71480cffbd6e0 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs @@ -427,18 +427,7 @@ protected virtual void Dispose(bool disposing) public void Dispose() => Dispose(true); - ~TcpClient() - { -#if DEBUG - DebugThreadTracking.SetThreadSource(ThreadKinds.Finalization); - using (DebugThreadTracking.SetThreadKind(ThreadKinds.System | ThreadKinds.Async)) - { -#endif - Dispose(false); -#if DEBUG - } -#endif - } + ~TcpClient() => Dispose(false); // Gets or sets the size of the receive buffer in bytes. public int ReceiveBufferSize diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs index 655534f857ca0..8c3af3465b9df 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs @@ -454,8 +454,8 @@ public void SetSocketOption_Linger_NotLingerOption_Throws_Argument() [Fact] public void SetSocketOption_Linger_InvalidLingerTime_Throws_Argument() { - AssertExtensions.Throws("optionValue.LingerTime", () => GetSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, -1))); - AssertExtensions.Throws("optionValue.LingerTime", () => GetSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, (int)ushort.MaxValue + 1))); + AssertExtensions.Throws("optionValue", () => GetSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, -1))); + AssertExtensions.Throws("optionValue", () => GetSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, (int)ushort.MaxValue + 1))); } [Fact] @@ -516,7 +516,7 @@ public void AcceptAsync_BufferList_Throws_Argument() BufferList = s_buffers }; - AssertExtensions.Throws("BufferList", () => GetSocket().AcceptAsync(eventArgs)); + AssertExtensions.Throws("e", () => GetSocket().AcceptAsync(eventArgs)); } [Fact] @@ -598,13 +598,13 @@ public void ConnectAsync_Static_BufferList_Throws_Argument() BufferList = s_buffers }; - AssertExtensions.Throws("BufferList", () => Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, eventArgs)); + AssertExtensions.Throws("e", () => Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, eventArgs)); } [Fact] - public void ConnectAsync_Static_NullRemoteEndPoint_Throws_ArgumentNull() + public void ConnectAsync_Static_NullRemoteEndPoint_Throws_ArgumentException() { - Assert.Throws(() => Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, s_eventArgs)); + Assert.Throws("e", () => Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, s_eventArgs)); } [Fact] @@ -620,9 +620,9 @@ public void ReceiveFromAsync_NullAsyncEventArgs_Throws_ArgumentNull() } [Fact] - public void ReceiveFromAsync_NullRemoteEndPoint_Throws_ArgumentNull() + public void ReceiveFromAsync_NullRemoteEndPoint_Throws_ArgumentException() { - Assert.Throws(() => GetSocket().ReceiveFromAsync(s_eventArgs)); + Assert.Throws("e", () => GetSocket().ReceiveFromAsync(s_eventArgs)); } [Fact] @@ -632,7 +632,7 @@ public void ReceiveFromAsync_AddressFamily_Throws_Argument() RemoteEndPoint = new IPEndPoint(IPAddress.IPv6Loopback, 1) }; - AssertExtensions.Throws("RemoteEndPoint", () => GetSocket(AddressFamily.InterNetwork).ReceiveFromAsync(eventArgs)); + AssertExtensions.Throws("e", () => GetSocket(AddressFamily.InterNetwork).ReceiveFromAsync(eventArgs)); } [Fact] @@ -642,9 +642,9 @@ public void ReceiveMessageFromAsync_NullAsyncEventArgs_Throws_ArgumentNull() } [Fact] - public void ReceiveMessageFromAsync_NullRemoteEndPoint_Throws_ArgumentNull() + public void ReceiveMessageFromAsync_NullRemoteEndPoint_Throws_ArgumentException() { - Assert.Throws(() => GetSocket().ReceiveMessageFromAsync(s_eventArgs)); + Assert.Throws("e", () => GetSocket().ReceiveMessageFromAsync(s_eventArgs)); } [Fact] @@ -654,7 +654,7 @@ public void ReceiveMessageFromAsync_AddressFamily_Throws_Argument() RemoteEndPoint = new IPEndPoint(IPAddress.IPv6Loopback, 1) }; - AssertExtensions.Throws("RemoteEndPoint", () => GetSocket(AddressFamily.InterNetwork).ReceiveMessageFromAsync(eventArgs)); + AssertExtensions.Throws("e", () => GetSocket(AddressFamily.InterNetwork).ReceiveMessageFromAsync(eventArgs)); } [Fact] @@ -670,9 +670,9 @@ public void SendPacketsAsync_NullAsyncEventArgs_Throws_ArgumentNull() } [Fact] - public void SendPacketsAsync_NullSendPacketsElements_Throws_ArgumentNull() + public void SendPacketsAsync_NullSendPacketsElements_Throws_ArgumentException() { - Assert.Throws(() => GetSocket().SendPacketsAsync(s_eventArgs)); + Assert.Throws("e", () => GetSocket().SendPacketsAsync(s_eventArgs)); } [Fact] @@ -694,7 +694,7 @@ public void SendToAsync_NullAsyncEventArgs_Throws_ArgumentNull() [Fact] public void SendToAsync_NullRemoteEndPoint_Throws_ArgumentNull() { - Assert.Throws(() => GetSocket().SendToAsync(s_eventArgs)); + Assert.Throws(() => GetSocket().SendToAsync(s_eventArgs)); } [Theory] diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs index 21e4750d4744b..ee81d7cdf81ac 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs @@ -751,7 +751,7 @@ public void EndAccept_Throws_ObjectDisposed() [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPreciseGcSupported))] [InlineData(false)] [InlineData(true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/35846", TestPlatforms.Linux)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/35846", TestPlatforms.AnyUnix)] public async Task NonDisposedSocket_SafeHandlesCollected(bool clientAsync) { List handles = await CreateHandlesAsync(clientAsync); diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs index bb88d9a93806d..e53c90d949f0a 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs @@ -1649,7 +1649,7 @@ public void Socket_ReceiveFromAsyncV4IPEndPointFromV4Client_Throws() args.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, UnusedPort); args.SetBuffer(new byte[1], 0, 1); - AssertExtensions.Throws("RemoteEndPoint", () => + AssertExtensions.Throws("e", () => { socket.ReceiveFromAsync(args); }); @@ -2188,7 +2188,7 @@ public void Socket_ReceiveMessageFromAsyncV4IPEndPointFromV4Client_Throws() args.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, UnusedPort); args.SetBuffer(new byte[1], 0, 1); - AssertExtensions.Throws("RemoteEndPoint", () => + AssertExtensions.Throws("e", () => { socket.ReceiveMessageFromAsync(args); }); diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/KeepAliveTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/KeepAliveTest.cs index 6a6e07a962257..77b41f8e8245a 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/KeepAliveTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/KeepAliveTest.cs @@ -54,6 +54,7 @@ public void Socket_KeepAlive_RetryCount_Success() } [ConditionalFact(typeof(KeepAliveTest), nameof(IsWindowsBelow1703))] // RetryCount not supported by earlier versions of Windows + [PlatformSpecific(TestPlatforms.Windows)] public void Socket_KeepAlive_RetryCount_Failure() { using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/LingerStateTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/LingerStateTest.cs index c2d98010766af..80c9c54e8d428 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/LingerStateTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/LingerStateTest.cs @@ -19,7 +19,7 @@ private void TestLingerState_Success(Socket sock, bool enabled, int lingerTime) private void TestLingerState_ArgumentException(Socket sock, bool enabled, int lingerTime) { - AssertExtensions.Throws("optionValue.LingerTime", () => + AssertExtensions.Throws("optionValue", () => { sock.LingerState = new LingerOption(enabled, lingerTime); }); diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs index 8c81909054b74..3406be9532737 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs @@ -111,7 +111,7 @@ public void NotConnected_Throw() [InlineData(SocketImplementationType.Async)] public void NullList_Throws(SocketImplementationType type) { - AssertExtensions.Throws("e.SendPacketsElements", () => SendPackets(type, (SendPacketsElement[])null, SocketError.Success, 0)); + AssertExtensions.Throws("e", () => SendPackets(type, (SendPacketsElement[])null, SocketError.Success, 0)); } [OuterLoop] diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendTo.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendTo.cs index c767e30b8f143..d10c877558277 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendTo.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendTo.cs @@ -47,7 +47,7 @@ public async Task NullEndpoint_Throws() { using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - await Assert.ThrowsAsync(() => SendToAsync(socket, new byte[1], null)); + await Assert.ThrowsAnyAsync(() => SendToAsync(socket, new byte[1], null)); } [Fact] diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 2a4a361444cb2..34654c50b39e1 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -484,6 +484,7 @@ public void UnixDomainSocketEndPoint_UsingAbstractSocketAddressOnUnsupported_Thr } [ConditionalFact(nameof(IsSubWindows10))] + [PlatformSpecific(TestPlatforms.Windows)] public void Socket_CreateUnixDomainSocket_Throws_OnWindows() { AssertExtensions.Throws("path", () => new UnixDomainSocketEndPoint(null)); diff --git a/src/libraries/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs b/src/libraries/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs index f4aa1444be251..0cdc475f1a94a 100644 --- a/src/libraries/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs +++ b/src/libraries/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs @@ -97,7 +97,9 @@ public partial class WebHeaderCollection : System.Collections.Specialized.NameVa public void Add(System.Net.HttpRequestHeader header, string? value) { } public void Add(System.Net.HttpResponseHeader header, string? value) { } public void Add(string header) { } +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Add(string name, string? value) { } +#pragma warning restore CS8765 protected void AddWithoutValidate(string headerName, string? headerValue) { } public override void Clear() { } public override string? Get(int index) { throw null; } @@ -106,16 +108,22 @@ public partial class WebHeaderCollection : System.Collections.Specialized.NameVa public override string GetKey(int index) { throw null; } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { } public override string[]? GetValues(int index) { throw null; } +#pragma warning disable CS8765 // Nullability of parameter 'header' doesn't match overridden member public override string[]? GetValues(string header) { throw null; } +#pragma warning restore CS8765 public static bool IsRestricted(string headerName) { throw null; } public static bool IsRestricted(string headerName, bool response) { throw null; } public override void OnDeserialization(object? sender) { } public void Remove(System.Net.HttpRequestHeader header) { } public void Remove(System.Net.HttpResponseHeader header) { } +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Remove(string name) { } +#pragma warning restore CS8765 public void Set(System.Net.HttpRequestHeader header, string? value) { } public void Set(System.Net.HttpResponseHeader header, string? value) { } +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Set(string name, string? value) { } +#pragma warning restore CS8765 void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { } public byte[] ToByteArray() { throw null; } public override string ToString() { throw null; } diff --git a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs index 875caac4c46fd..2214534a9d5ab 100644 --- a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs +++ b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs @@ -132,9 +132,9 @@ private bool AllowHttpResponseHeader } } -#pragma warning disable CS8610 // Nullability of parameter 'name' doesn't match overridden member +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Set(string name, string? value) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (string.IsNullOrEmpty(name)) { @@ -241,9 +241,9 @@ public static bool IsRestricted(string headerName, bool response) // header - Name of the header. // Return Value: // string[] - array of parsed string objects -#pragma warning disable CS8610 // Nullability of parameter 'header' doesn't match overridden member +#pragma warning disable CS8765 // Nullability of parameter 'header' doesn't match overridden member public override string[]? GetValues(string header) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { // First get the information about the header and the values for // the header. @@ -378,16 +378,16 @@ public void Add(string header) { if (value != null && value.Length > ushort.MaxValue) { - throw new ArgumentOutOfRangeException(nameof(value), value, SR.Format(CultureInfo.InvariantCulture, SR.net_headers_toolong, ushort.MaxValue)); + throw new ArgumentOutOfRangeException(nameof(header), value, SR.Format(CultureInfo.InvariantCulture, SR.net_headers_toolong, ushort.MaxValue)); } } InvalidateCachedArrays(); InnerCollection.Add(name, value); } -#pragma warning disable CS8610 // Nullability of parameter 'name' doesn't match overridden member +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Add(string name, string? value) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (name == null) { @@ -460,9 +460,9 @@ internal void ThrowOnRestrictedHeader(string headerName) /// /// Removes the specified header. /// -#pragma warning disable CS8610 // Nullability of parameter 'name' doesn't match overridden member +#pragma warning disable CS8765 // Nullability of parameter 'name' doesn't match overridden member public override void Remove(string name) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { if (string.IsNullOrEmpty(name)) { diff --git a/src/libraries/System.Net.WebSockets.WebSocketProtocol/src/System.Net.WebSockets.WebSocketProtocol.csproj b/src/libraries/System.Net.WebSockets.WebSocketProtocol/src/System.Net.WebSockets.WebSocketProtocol.csproj index dd5ff48f1a7b7..a85b95b6c768d 100644 --- a/src/libraries/System.Net.WebSockets.WebSocketProtocol/src/System.Net.WebSockets.WebSocketProtocol.csproj +++ b/src/libraries/System.Net.WebSockets.WebSocketProtocol/src/System.Net.WebSockets.WebSocketProtocol.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj index 4f65c31e1ce46..ef145e7ec407d 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj @@ -1,9 +1,10 @@ netstandard2.0;netstandard1.1 - true + + true diff --git a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj index d56053cbd493f..5548e9a52d379 100644 --- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj @@ -2,10 +2,10 @@ true netstandard2.0;netstandard1.1 - true - System.Numerics.Tensors + + true diff --git a/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs index 4c6fa0c0637d3..fc82fb83850f0 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Matrix4x4Tests.cs @@ -219,6 +219,23 @@ public void Matrix4x4InvertAffineTest() Assert.True(MathHelper.Equal(i, Matrix4x4.Identity)); } + // A test for Invert (Matrix4x4) + [Fact] + public void Matrix4x4InvertRank3() + { + // A 4x4 Matrix having a rank of 3 + Matrix4x4 mtx = new Matrix4x4(1.0f, 2.0f, 3.0f, 0.0f, + 5.0f, 1.0f, 6.0f, 0.0f, + 8.0f, 9.0f, 1.0f, 0.0f, + 4.0f, 7.0f, 3.0f, 0.0f); + + Matrix4x4 actual; + Assert.False(Matrix4x4.Invert(mtx, out actual)); + + Matrix4x4 i = mtx * actual; + Assert.False(MathHelper.Equal(i, Matrix4x4.Identity)); + } + void DecomposeTest(float yaw, float pitch, float roll, Vector3 expectedTranslation, Vector3 expectedScales) { Quaternion expectedRotation = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(yaw), diff --git a/src/libraries/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/Unsafe.cs b/src/libraries/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/Unsafe.cs index 62649b4c22463..ca63162736745 100644 --- a/src/libraries/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/Unsafe.cs +++ b/src/libraries/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/Unsafe.cs @@ -8,15 +8,6 @@ using System.Runtime.CompilerServices; using System.Runtime.Versioning; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -using nint = System.Int64; -#else -using nuint = System.UInt32; -using nint = System.Int32; -#endif - // // The implementations of most the methods in this file are provided as intrinsics. // In CoreCLR, the body of the functions are replaced by the EE with unsafe code. See see getILIntrinsicImplementationForUnsafe for details. @@ -145,19 +136,6 @@ public static int SizeOf() #endif } -#if TARGET_64BIT - /// - /// Adds an element offset to the given reference. - /// - [Intrinsic] - [NonVersionable] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ref T Add(ref T source, nint elementOffset) - { - return ref Unsafe.Add(ref source, (IntPtr)(void*)elementOffset); - } -#endif - /// /// Adds an byte offset to the given reference. /// diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 5957640bac106..c5c6a8603e8df 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -1343,7 +1343,7 @@ The specified object must not be an instance of a generic type. - The specified Type must not be a generic type definition. + The specified Type must not be a generic type. The specified Type must be a struct containing no references. diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 951552c11ba49..8857b33b6f8dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -8,6 +8,7 @@ enable + true @@ -193,6 +194,7 @@ + @@ -1054,6 +1056,9 @@ Common\System\HResults.cs + + Common\System\SR.cs + Common\System\Collections\Generic\ReferenceEqualityComparer.cs @@ -1750,14 +1755,16 @@ - + + + - - + + @@ -1773,6 +1780,14 @@ + + + Common\Interop\OSX\Interop.libobjc.cs + + + Common\Interop\OSX\Interop.Libraries.cs + + diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs index 7cd1e8e97a4e8..19164e5ce634c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.Loader; using System.Runtime.Remoting; @@ -386,6 +387,8 @@ public void SetThreadPrincipal(IPrincipal principal) return oh?.Unwrap(); } + [PreserveDependency("GetDefaultInstance", "System.Security.Principal.GenericPrincipal", "System.Security.Claims")] + [PreserveDependency("GetDefaultInstance", "System.Security.Principal.WindowsPrincipal", "System.Security.Principal.Windows")] internal IPrincipal? GetThreadPrincipal() { IPrincipal? principal = _defaultPrincipal; @@ -402,7 +405,7 @@ public void SetThreadPrincipal(IPrincipal principal) // Don't throw PNSE if null like for WindowsPrincipal as UnauthenticatedPrincipal should // be available on all platforms. Volatile.Write(ref s_getUnauthenticatedPrincipal, - (Func)mi.CreateDelegate(typeof(Func))); + mi.CreateDelegate>()); } principal = s_getUnauthenticatedPrincipal(); @@ -418,7 +421,7 @@ public void SetThreadPrincipal(IPrincipal principal) throw new PlatformNotSupportedException(SR.PlatformNotSupported_Principal); } Volatile.Write(ref s_getWindowsPrincipal, - (Func)mi.CreateDelegate(typeof(Func))); + mi.CreateDelegate>()); } principal = s_getWindowsPrincipal(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.Unix.cs index 6c6a823a521e0..18f55d3bb3981 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.Unix.cs @@ -2,26 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { public static partial class Buffer { #if TARGET_ARM64 - // Managed code is currently faster than glibc unoptimized memmove - // TODO-ARM64-UNIX-OPT revisit when glibc optimized memmove is in Linux distros - // https://github.com/dotnet/runtime/issues/8897 - private const nuint MemmoveNativeThreshold = ulong.MaxValue; + // Managed code is currently faster than glibc unoptimized memmove + // TODO-ARM64-UNIX-OPT revisit when glibc optimized memmove is in Linux distros + // https://github.com/dotnet/runtime/issues/8897 + private static nuint MemmoveNativeThreshold => nuint.MaxValue; #elif TARGET_ARM - private const nuint MemmoveNativeThreshold = 512; + private const nuint MemmoveNativeThreshold = 512; #else - private const nuint MemmoveNativeThreshold = 2048; + private const nuint MemmoveNativeThreshold = 2048; #endif } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.Windows.cs index 226a0cd7e1d1b..d5607de913478 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.Windows.cs @@ -2,13 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { public static partial class Buffer @@ -16,7 +9,7 @@ public static partial class Buffer #if TARGET_ARM64 // Determine optimal value for Windows. // https://github.com/dotnet/runtime/issues/8896 - private const nuint MemmoveNativeThreshold = ulong.MaxValue; + private static nuint MemmoveNativeThreshold => nuint.MaxValue; #else private const nuint MemmoveNativeThreshold = 2048; #endif diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs index e8d9b77828221..3880d590ca4ce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs @@ -12,15 +12,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; -#else -using nint = System.Int32; -using nuint = System.UInt32; -#endif - namespace System { public static partial class Buffer @@ -341,7 +332,7 @@ internal static void Memmove(ref T destination, ref T source, nuint elementCo private static void Memmove(ref byte dest, ref byte src, nuint len) { // P/Invoke into the native version when the buffers are overlapping. - if (((nuint)Unsafe.ByteOffset(ref src, ref dest) < len) || ((nuint)Unsafe.ByteOffset(ref dest, ref src) < len)) + if (((nuint)(nint)Unsafe.ByteOffset(ref src, ref dest) < len) || ((nuint)(nint)Unsafe.ByteOffset(ref dest, ref src) < len)) { goto BuffersOverlap; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs index 8235339820dfe..eb339b89576d6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs @@ -104,7 +104,8 @@ public static int CountDigits(uint value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CountHexDigits(ulong value) { - return (64 - BitOperations.LeadingZeroCount(value | 1) + 3) >> 2; + // The number of hex digits is log16(value) + 1, or log2(value) / 4 + 1 + return (BitOperations.Log2(value) >> 2) + 1; } // Counts the number of trailing '0' digits in a decimal number. diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Utilities.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Utilities.cs index 7e1caa039b36c..9fe7233e16486 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Utilities.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Utilities.cs @@ -14,8 +14,13 @@ internal static class Utilities internal static int SelectBucketIndex(int bufferSize) { Debug.Assert(bufferSize >= 0); - uint bits = ((uint)bufferSize - 1) >> 4; - return 32 - BitOperations.LeadingZeroCount(bits); + + // Buffers are bucketed so that a request between 2^(n-1) + 1 and 2^n is given a buffer of 2^n + // Bucket index is log2(bufferSize - 1) with the exception that buffers between 1 and 16 bytes + // are combined, and the index is slid down by 3 to compensate. + // Zero is a valid bufferSize, and it is assigned the highest bucket index so that zero-length + // buffers are not retained by the pool. The pool will return the Array.Empty singleton for these. + return BitOperations.Log2((uint)bufferSize - 1 | 15) - 3; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs index cb7f2cdde7f68..061672601a022 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs @@ -28,18 +28,12 @@ namespace System.Collections [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArrayList : IList, ICloneable { - private object?[] _items = null!; // Do not rename (binary serialization) + private object?[] _items; // Do not rename (binary serialization) private int _size; // Do not rename (binary serialization) private int _version; // Do not rename (binary serialization) private const int _defaultCapacity = 4; - // Note: this constructor is a bogus constructor that does nothing - // and is for use only with SyncArrayList. - internal ArrayList(bool trash) - { - } - // Constructs a ArrayList. The list is initially empty and has a capacity // of zero. Upon adding the first element to the list the capacity is // increased to _defaultCapacity, and then increased in multiples of two as required. @@ -1196,7 +1190,6 @@ private class SyncArrayList : ArrayList private readonly object _root; internal SyncArrayList(ArrayList list) - : base(false) { _list = list; _root = list.SyncRoot; @@ -2215,7 +2208,7 @@ private class Range : ArrayList private int _baseSize; private int _baseVersion; - internal Range(ArrayList list, int index, int count) : base(false) + internal Range(ArrayList list, int index, int count) { _baseList = list; _baseIndex = index; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs index b1253aa3ff290..321c2119cfe56 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs @@ -8,13 +8,6 @@ using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nint = System.Int64; -#else -using nint = System.Int32; -#endif - namespace System.Collections.Generic { #region ArraySortHelper for single arrays diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs index abdf95c05ed79..9ae197ee1bcf9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs @@ -101,10 +101,9 @@ public static uint FastMod(uint value, uint divisor, ulong multiplier) // which allows to avoid the long multiplication if the divisor is less than 2**31. Debug.Assert(divisor <= int.MaxValue); - ulong lowbits = multiplier * value; - // 64bit * 64bit => 128bit isn't currently supported by Math https://github.com/dotnet/runtime/issues/31184 - // otherwise we'd want this to be (uint)Math.BigMul(lowbits, divisor, out _) - uint highbits = (uint)((((lowbits >> 32) + 1) * divisor) >> 32); + // This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version + // is faster than BigMul currently because we only need the high bits. + uint highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32); Debug.Assert(highbits == value % divisor); return highbits; diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index 023d795019d41..1561e99a72434 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -581,9 +581,7 @@ public DateTime AddYears(int value) { if (value < -10000 || value > 10000) { - // DateTimeOffset.AddYears(int years) is implemented on top of DateTime.AddYears(int value). Use the more appropriate - // parameter name out of the two for the exception. - throw new ArgumentOutOfRangeException("years", SR.ArgumentOutOfRange_DateTimeBadYears); + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_DateTimeBadYears); } return AddMonths(value * 12); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs new file mode 100644 index 0000000000000..5ab29034e1a8b --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs @@ -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. + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that the specified method requires dynamic access to code that is not referenced + /// statically, for example through . + /// + /// + /// This allows tools to understand which methods are unsafe to call when removing unreferenced + /// code from an application. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)] + public sealed class RequiresUnreferencedCodeAttribute : Attribute + { + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of unreferenced code. + /// + public RequiresUnreferencedCodeAttribute(string message) + { + Message = message; + } + + /// + /// Gets a message that contains information about the usage of unreferenced code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requries unreferenced code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs index 1a41810b25965..2fbe8b40e18ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs @@ -6,6 +6,7 @@ using System; using System.Diagnostics; #endif +using System.Diagnostics.CodeAnalysis; using System.Threading; #if ES_BUILD_STANDALONE @@ -135,9 +136,10 @@ internal void ResetStatistics() // Values buffering private const int BufferedSize = 10; private const double UnusedBufferSlotValue = double.NegativeInfinity; - private volatile double[] _bufferedValues = null!; + private volatile double[] _bufferedValues; private volatile int _bufferedValuesIndex; + [MemberNotNull(nameof(_bufferedValues))] private void InitializeBuffer() { _bufferedValues = new double[BufferedSize]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs index 34a7b861e3057..8d0afa17111fc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs @@ -80,7 +80,8 @@ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl Contr } // Define an EventPipeEvent handle. - unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte* pMetadata, uint metadataLength) + unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, + byte *pMetadata, uint metadataLength) { IntPtr eventHandlePtr = EventPipeInternal.DefineEvent(m_provHandle, eventID, keywords, eventVersion, level, pMetadata, metadataLength); return eventHandlePtr; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs index fd81d059621b2..50f1f41bbbf9b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs @@ -9,6 +9,12 @@ namespace System.Diagnostics.Tracing #if FEATURE_PERFTRACING internal sealed class EventPipeMetadataGenerator { + private enum MetadataTag + { + Opcode = 1, + ParameterPayload = 2 + } + public static EventPipeMetadataGenerator Instance = new EventPipeMetadataGenerator(); private EventPipeMetadataGenerator() { } @@ -19,7 +25,8 @@ internal sealed class EventPipeMetadataGenerator EventParameterInfo[] eventParams = new EventParameterInfo[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { - eventParams[i].SetInfo(parameters[i].Name!, parameters[i].ParameterType); + EventParameterInfo.GetTypeInfoFromType(parameters[i].ParameterType, out TraceLoggingTypeInfo? paramTypeInfo); + eventParams[i].SetInfo(parameters[i].Name!, parameters[i].ParameterType, paramTypeInfo); } return GenerateMetadata( @@ -28,6 +35,7 @@ internal sealed class EventPipeMetadataGenerator eventMetadata.Descriptor.Keywords, eventMetadata.Descriptor.Level, eventMetadata.Descriptor.Version, + (EventOpcode)eventMetadata.Descriptor.Opcode, eventParams); } @@ -37,6 +45,7 @@ internal sealed class EventPipeMetadataGenerator EventKeywords keywords, EventLevel level, uint version, + EventOpcode opcode, TraceLoggingEventTypes eventTypes) { TraceLoggingTypeInfo[] typeInfos = eventTypes.typeInfos; @@ -52,7 +61,7 @@ internal sealed class EventPipeMetadataGenerator eventParams[i].SetInfo(paramName, typeInfos[i].DataType, typeInfos[i]); } - return GenerateMetadata(eventId, eventName, (long)keywords, (uint)level, version, eventParams); + return GenerateMetadata(eventId, eventName, (long)keywords, (uint)level, version, opcode, eventParams); } internal unsafe byte[]? GenerateMetadata( @@ -61,9 +70,11 @@ internal sealed class EventPipeMetadataGenerator long keywords, uint level, uint version, + EventOpcode opcode, EventParameterInfo[] parameters) { byte[]? metadata = null; + bool hasV2ParameterTypes = false; try { // eventID : 4 bytes @@ -72,8 +83,9 @@ internal sealed class EventPipeMetadataGenerator // eventVersion : 4 bytes // level : 4 bytes // parameterCount : 4 bytes - uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2; - uint defaultMetadataLength = metadataLength; + uint v1MetadataLength = 24 + ((uint)eventName.Length + 1) * 2; + uint v2MetadataLength = 0; + uint defaultV1MetadataLength = v1MetadataLength; // Check for an empty payload. // Write calls with no arguments by convention have a parameter of @@ -86,42 +98,115 @@ internal sealed class EventPipeMetadataGenerator // Increase the metadataLength for parameters. foreach (EventParameterInfo parameter in parameters) { - int pMetadataLength = parameter.GetMetadataLength(); - // The call above may return -1 which means we failed to get the metadata length. - // We then return a default metadata blob (with parameterCount of 0) to prevent it from generating malformed metadata. - if (pMetadataLength < 0) + uint pMetadataLength; + if (!parameter.GetMetadataLength(out pMetadataLength)) { - parameters = Array.Empty(); - metadataLength = defaultMetadataLength; + // The call above may return false which means it is an unsupported type for V1. + // If that is the case we use the v2 blob for metadata instead + hasV2ParameterTypes = true; break; } - metadataLength += (uint)pMetadataLength; + + v1MetadataLength += (uint)pMetadataLength; + } + + + if (hasV2ParameterTypes) + { + v1MetadataLength = defaultV1MetadataLength; + + // V2 length is the parameter count (4 bytes) plus the size of the params + v2MetadataLength = 4; + foreach (EventParameterInfo parameter in parameters) + { + uint pMetadataLength; + if (!parameter.GetMetadataLengthV2(out pMetadataLength)) + { + // We ran in to an unsupported type, return empty event metadata + parameters = Array.Empty(); + v1MetadataLength = defaultV1MetadataLength; + v2MetadataLength = 0; + hasV2ParameterTypes = false; + break; + } + + v2MetadataLength += (uint)pMetadataLength; + } } - metadata = new byte[metadataLength]; + // Optional opcode length needs 1 byte for the opcode + 5 bytes for the tag (4 bytes size, 1 byte kind) + uint opcodeMetadataLength = opcode == EventOpcode.Info ? 0u : 6u; + // Optional V2 metadata needs the size of the params + 5 bytes for the tag (4 bytes size, 1 byte kind) + uint v2MetadataPayloadLength = v2MetadataLength == 0 ? 0 : v2MetadataLength + 5; + uint totalV2MetadataLength = v2MetadataPayloadLength + opcodeMetadataLength; + uint totalMetadataLength = v1MetadataLength + totalV2MetadataLength; + metadata = new byte[totalMetadataLength]; - // Write metadata: eventID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name... + // Write metadata: metadataHeaderLength, eventID, eventName, keywords, eventVersion, level, + // parameterCount, param1..., optional extended metadata fixed (byte* pMetadata = metadata) { uint offset = 0; - WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)eventId); + + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (uint)eventId); fixed (char* pEventName = eventName) { - WriteToBuffer(pMetadata, metadataLength, ref offset, (byte*)pEventName, ((uint)eventName.Length + 1) * 2); + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (byte*)pEventName, ((uint)eventName.Length + 1) * 2); } - WriteToBuffer(pMetadata, metadataLength, ref offset, keywords); - WriteToBuffer(pMetadata, metadataLength, ref offset, version); - WriteToBuffer(pMetadata, metadataLength, ref offset, level); - WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)parameters.Length); - foreach (EventParameterInfo parameter in parameters) + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, keywords); + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, version); + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, level); + + if (hasV2ParameterTypes) + { + // If we have unsupported types, the V1 metadata must be empty. Write 0 count of params. + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, 0); + } + else + { + // Without unsupported V1 types we can write all the params now. + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (uint)parameters.Length); + foreach (var parameter in parameters) + { + if (!parameter.GenerateMetadata(pMetadata, ref offset, totalMetadataLength)) + { + // If we fail to generate metadata for any parameter, we should return the "default" metadata without any parameters + return GenerateMetadata(eventId, eventName, keywords, level, version, opcode, Array.Empty()); + } + } + } + + Debug.Assert(offset == v1MetadataLength); + + if (opcode != EventOpcode.Info) { - if (!parameter.GenerateMetadata(pMetadata, ref offset, metadataLength)) + // Size of opcode + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, 1); + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (byte)MetadataTag.Opcode); + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (byte)opcode); + } + + if (hasV2ParameterTypes) + { + // Write the V2 supported metadata now + // Starting with the size of the V2 payload + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, v2MetadataLength); + // Now the tag to identify it as a V2 parameter payload + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (byte)MetadataTag.ParameterPayload); + // Then the count of parameters + WriteToBuffer(pMetadata, totalMetadataLength, ref offset, (uint)parameters.Length); + // Finally the parameters themselves + foreach (var parameter in parameters) { - // If we fail to generate metadata for any parameter, we should return the "default" metadata without any parameters - return GenerateMetadata(eventId, eventName, keywords, level, version, Array.Empty()); + if (!parameter.GenerateMetadataV2(pMetadata, ref offset, totalMetadataLength)) + { + // If we fail to generate metadata for any parameter, we should return the "default" metadata without any parameters + return GenerateMetadata(eventId, eventName, keywords, level, version, opcode, Array.Empty()); + } } } - Debug.Assert(metadataLength == offset); + + Debug.Assert(totalMetadataLength == offset); } } catch @@ -147,28 +232,11 @@ internal static unsafe void WriteToBuffer(byte* buffer, uint bufferLength, ref u offset += srcLength; } - // Copy uint value to buffer. - internal static unsafe void WriteToBuffer(byte* buffer, uint bufferLength, ref uint offset, uint value) - { - Debug.Assert(bufferLength >= (offset + 4)); - *(uint*)(buffer + offset) = value; - offset += 4; - } - - // Copy long value to buffer. - internal static unsafe void WriteToBuffer(byte* buffer, uint bufferLength, ref uint offset, long value) + internal static unsafe void WriteToBuffer(byte* buffer, uint bufferLength, ref uint offset, T value) where T : unmanaged { - Debug.Assert(bufferLength >= (offset + 8)); - *(long*)(buffer + offset) = value; - offset += 8; - } - - // Copy char value to buffer. - internal static unsafe void WriteToBuffer(byte* buffer, uint bufferLength, ref uint offset, char value) - { - Debug.Assert(bufferLength >= (offset + 2)); - *(char*)(buffer + offset) = value; - offset += 2; + Debug.Assert(bufferLength >= (offset + sizeof(T))); + *(T*)(buffer + offset) = value; + offset += (uint)sizeof(T); } } @@ -307,16 +375,207 @@ private static unsafe bool GenerateMetadataForProperty(PropertyAnalysis property return true; } - internal int GetMetadataLength() + internal unsafe bool GenerateMetadataV2(byte* pMetadataBlob, ref uint offset, uint blobSize) + { + if (TypeInfo == null) + return false; + return GenerateMetadataForNamedTypeV2(ParameterName, TypeInfo, pMetadataBlob, ref offset, blobSize); + } + + private static unsafe bool GenerateMetadataForNamedTypeV2(string name, TraceLoggingTypeInfo typeInfo, byte* pMetadataBlob, ref uint offset, uint blobSize) { - int ret = 0; + Debug.Assert(pMetadataBlob != null); + + if (!GetMetadataLengthForNamedTypeV2(name, typeInfo, out uint length)) + { + return false; + } + + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, length); + + // Write the property name. + fixed (char *pPropertyName = name) + { + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (byte *)pPropertyName, ((uint)name.Length + 1) * 2); + } + + return GenerateMetadataForTypeV2(typeInfo, pMetadataBlob, ref offset, blobSize); + } + + private static unsafe bool GenerateMetadataForTypeV2(TraceLoggingTypeInfo? typeInfo, byte* pMetadataBlob, ref uint offset, uint blobSize) + { + Debug.Assert(typeInfo != null); + Debug.Assert(pMetadataBlob != null); + + // Check if this type is a nested struct. + if (typeInfo is InvokeTypeInfo invokeTypeInfo) + { + // Each nested struct is serialized as: + // TypeCode.Object : 4 bytes + // Number of properties : 4 bytes + // Property description 0...N + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (uint)TypeCode.Object); + + // Get the set of properties to be serialized. + PropertyAnalysis[]? properties = invokeTypeInfo.properties; + if (properties != null) + { + // Write the count of serializable properties. + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (uint)properties.Length); + + foreach (PropertyAnalysis prop in properties) + { + if (!GenerateMetadataForNamedTypeV2(prop.name, prop.typeInfo, pMetadataBlob, ref offset, blobSize)) + { + return false; + } + } + } + else + { + // This struct has zero serializable properties so we just write the property count. + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (uint)0); + } + } + else if (typeInfo is EnumerableTypeInfo enumerableTypeInfo) + { + // Each enumerable is serialized as: + // TypeCode.Array : 4 bytes + // ElementType : N bytes + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, EventPipeTypeCodeArray); + GenerateMetadataForTypeV2(enumerableTypeInfo.ElementInfo, pMetadataBlob, ref offset, blobSize); + } + else if (typeInfo is ScalarArrayTypeInfo arrayTypeInfo) + { + // Each enumerable is serialized as: + // TypeCode.Array : 4 bytes + // ElementType : N bytes + if (!arrayTypeInfo.DataType.HasElementType) + { + return false; + } + + TraceLoggingTypeInfo? elementTypeInfo; + if (!GetTypeInfoFromType(arrayTypeInfo.DataType.GetElementType(), out elementTypeInfo)) + { + return false; + } + + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, EventPipeTypeCodeArray); + GenerateMetadataForTypeV2(elementTypeInfo, pMetadataBlob, ref offset, blobSize); + } + else + { + // Each primitive type is serialized as: + // TypeCode : 4 bytes + TypeCode typeCode = GetTypeCodeExtended(typeInfo.DataType); + + // EventPipe does not support this type. Throw, which will cause no metadata to be registered for this event. + if (typeCode == TypeCode.Object) + { + return false; + } + + // Write the type code. + EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (uint)typeCode); + } + return true; + } + + internal static bool GetTypeInfoFromType(Type? type, out TraceLoggingTypeInfo? typeInfo) + { + if (type == typeof(bool)) + { + typeInfo = ScalarTypeInfo.Boolean(); + return true; + } + else if (type == typeof(byte)) + { + typeInfo = ScalarTypeInfo.Byte(); + return true; + } + else if (type == typeof(sbyte)) + { + typeInfo = ScalarTypeInfo.SByte(); + return true; + } + else if (type == typeof(char)) + { + typeInfo = ScalarTypeInfo.Char(); + return true; + } + else if (type == typeof(short)) + { + typeInfo = ScalarTypeInfo.Int16(); + return true; + } + else if (type == typeof(ushort)) + { + typeInfo = ScalarTypeInfo.UInt16(); + return true; + } + else if (type == typeof(int)) + { + typeInfo = ScalarTypeInfo.Int32(); + return true; + } + else if (type == typeof(uint)) + { + typeInfo = ScalarTypeInfo.UInt32(); + return true; + } + else if (type == typeof(long)) + { + typeInfo = ScalarTypeInfo.Int64(); + return true; + } + else if (type == typeof(ulong)) + { + typeInfo = ScalarTypeInfo.UInt64(); + return true; + } + else if (type == typeof(IntPtr)) + { + typeInfo = ScalarTypeInfo.IntPtr(); + return true; + } + else if (type == typeof(UIntPtr)) + { + typeInfo = ScalarTypeInfo.UIntPtr(); + return true; + } + else if (type == typeof(float)) + { + typeInfo = ScalarTypeInfo.Single(); + return true; + } + else if (type == typeof(double)) + { + typeInfo = ScalarTypeInfo.Double(); + return true; + } + else if (type == typeof(Guid)) + { + typeInfo = ScalarTypeInfo.Guid(); + return true; + } + else + { + typeInfo = null; + return false; + } + } + + internal bool GetMetadataLength(out uint size) + { + size = 0; TypeCode typeCode = GetTypeCodeExtended(ParameterType); if (typeCode == TypeCode.Object) { if (!(TypeInfo is InvokeTypeInfo typeInfo)) { - return -1; + return false; } // Each nested struct is serialized as: @@ -324,7 +583,7 @@ internal int GetMetadataLength() // Number of properties : 4 bytes // Property description 0...N // Nested struct property name : NULL-terminated string. - ret += sizeof(uint) // TypeCode + size += sizeof(uint) // TypeCode + sizeof(uint); // Property count // Get the set of properties to be serialized. @@ -333,21 +592,21 @@ internal int GetMetadataLength() { foreach (PropertyAnalysis prop in properties) { - ret += (int)GetMetadataLengthForProperty(prop); + size += GetMetadataLengthForProperty(prop); } } // For simplicity when writing a reader, we write a NULL char // after the metadata for a top-level struct (for its name) so that // readers don't have do special case the outer-most struct. - ret += sizeof(char); + size += sizeof(char); } else { - ret += (int)(sizeof(uint) + ((ParameterName.Length + 1) * 2)); + size += (uint)(sizeof(uint) + ((ParameterName.Length + 1) * 2)); } - return ret; + return true; } private static uint GetMetadataLengthForProperty(PropertyAnalysis property) @@ -388,6 +647,9 @@ private static uint GetMetadataLengthForProperty(PropertyAnalysis property) return ret; } + // Array is not part of TypeCode, we decided to use 19 to represent it. (18 is the last type code value, string) + private const int EventPipeTypeCodeArray = 19; + private static TypeCode GetTypeCodeExtended(Type parameterType) { // Guid is not part of TypeCode, we decided to use 17 to represent it, as it's the "free slot" @@ -406,6 +668,99 @@ private static TypeCode GetTypeCodeExtended(Type parameterType) return Type.GetTypeCode(parameterType); } + + internal bool GetMetadataLengthV2(out uint size) + { + return GetMetadataLengthForNamedTypeV2(ParameterName, TypeInfo, out size); + } + + private static bool GetMetadataLengthForTypeV2(TraceLoggingTypeInfo? typeInfo, out uint size) + { + size = 0; + if (typeInfo == null) + { + return false; + } + + if (typeInfo is InvokeTypeInfo invokeTypeInfo) + { + // Struct is serialized as: + // TypeCode.Object : 4 bytes + // Number of properties : 4 bytes + // Property description 0...N + size += sizeof(uint) // TypeCode + + sizeof(uint); // Property count + + // Get the set of properties to be serialized. + PropertyAnalysis[]? properties = invokeTypeInfo.properties; + if (properties != null) + { + foreach (PropertyAnalysis prop in properties) + { + if (!GetMetadataLengthForNamedTypeV2(prop.name, prop.typeInfo, out uint typeSize)) + { + return false; + } + + size += typeSize; + } + } + } + else if (typeInfo is EnumerableTypeInfo enumerableTypeInfo) + { + // IEnumerable is serialized as: + // TypeCode : 4 bytes + // ElementType : N bytes + size += sizeof(uint); + if (!GetMetadataLengthForTypeV2(enumerableTypeInfo.ElementInfo, out uint typeSize)) + { + return false; + } + + size += typeSize; + } + else if (typeInfo is ScalarArrayTypeInfo arrayTypeInfo) + { + TraceLoggingTypeInfo? elementTypeInfo; + if (!arrayTypeInfo.DataType.HasElementType + || !GetTypeInfoFromType(arrayTypeInfo.DataType.GetElementType(), out elementTypeInfo)) + { + return false; + } + + size += sizeof(uint); + if (!GetMetadataLengthForTypeV2(elementTypeInfo, out uint typeSize)) + { + return false; + } + + size += typeSize; + } + else + { + size += (uint)sizeof(uint); + } + + return true; + } + + private static bool GetMetadataLengthForNamedTypeV2(string name, TraceLoggingTypeInfo? typeInfo, out uint size) + { + // Named type is serialized + // SizeOfTypeDescription : 4 bytes + // Name : NULL-terminated UTF16 string + // Type : N bytes + size = (uint)(sizeof(uint) + + ((name.Length + 1) * 2)); + + if (!GetMetadataLengthForTypeV2(typeInfo, out uint typeSize)) + { + return false; + } + + size += typeSize; + return true; + } } #endif // FEATURE_PERFTRACING diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs index fd0bd6eab4a32..dbc70abfb741d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs @@ -1325,7 +1325,8 @@ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl Contr } // Define an EventPipeEvent handle. - unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte* pMetadata, uint metadataLength) + unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, + uint level, byte* pMetadata, uint metadataLength) { throw new System.NotSupportedException(); } @@ -1366,7 +1367,8 @@ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl Contr } // Define an EventPipeEvent handle. - unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte* pMetadata, uint metadataLength) + unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, + uint level, byte* pMetadata, uint metadataLength) { return IntPtr.Zero; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index fd42fb69b6183..90e260acd6254 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -691,7 +691,7 @@ private unsafe void DefineEventPipeEvents() uint eventVersion = m_eventData[i].Descriptor.Version; uint level = m_eventData[i].Descriptor.Level; - fixed (byte* pMetadata = metadata) + fixed (byte *pMetadata = metadata) { IntPtr eventHandle = m_eventPipeProvider.m_eventProvider.DefineEventHandle( eventID, @@ -2221,12 +2221,13 @@ private unsafe void WriteEventString(string msgString) string eventName = "EventSourceMessage"; EventParameterInfo paramInfo = default(EventParameterInfo); paramInfo.SetInfo("message", typeof(string)); - byte[]? metadata = EventPipeMetadataGenerator.Instance.GenerateMetadata(0, eventName, keywords, (uint)level, 0, new EventParameterInfo[] { paramInfo }); + byte[]? metadata = EventPipeMetadataGenerator.Instance.GenerateMetadata(0, eventName, keywords, (uint)level, 0, EventOpcode.Info, new EventParameterInfo[] { paramInfo }); uint metadataLength = (metadata != null) ? (uint)metadata.Length : 0; fixed (byte* pMetadata = metadata) { - m_writeEventStringEventHandle = m_eventPipeProvider.m_eventProvider.DefineEventHandle(0, eventName, keywords, 0, (uint)level, pMetadata, metadataLength); + m_writeEventStringEventHandle = m_eventPipeProvider.m_eventProvider.DefineEventHandle(0, eventName, keywords, 0, (uint)level, + pMetadata, metadataLength); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IEventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IEventProvider.cs index 2ceb92f99c034..fc50ec76af5b5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IEventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IEventProvider.cs @@ -39,6 +39,7 @@ internal interface IEventProvider int EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId); // Define an EventPipeEvent handle. - unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte* pMetadata, uint metadataLength); + unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, + uint level, byte *pMetadata, uint metadataLength); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index 336e981bd622a..663074856b21b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -35,7 +35,10 @@ internal sealed class RuntimeEventSource : EventSource private PollingCounter? _gen1SizeCounter; private PollingCounter? _gen2SizeCounter; private PollingCounter? _lohSizeCounter; + private PollingCounter? _pohSizeCounter; private PollingCounter? _assemblyCounter; + private PollingCounter? _ilBytesJittedCounter; + private PollingCounter? _methodsJittedCounter; #endif public static void Initialize() @@ -68,7 +71,6 @@ protected override void OnEventCommand(EventCommandEventArgs command) _completedItemsCounter ??= new IncrementingPollingCounter("threadpool-completed-items-count", this, () => ThreadPool.CompletedWorkItemCount) { DisplayName = "ThreadPool Completed Work Item Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; _allocRateCounter ??= new IncrementingPollingCounter("alloc-rate", this, () => GC.GetTotalAllocatedBytes()) { DisplayName = "Allocation Rate", DisplayUnits = "B", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; _timerCounter ??= new PollingCounter("active-timer-count", this, () => Timer.ActiveCount) { DisplayName = "Number of Active Timers" }; - #if !MONO _exceptionCounter ??= new IncrementingPollingCounter("exception-count", this, () => Exception.GetExceptionCount()) { DisplayName = "Exception Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; _gcTimeCounter ??= new PollingCounter("time-in-gc", this, () => GC.GetLastGCPercentTimeInGC()) { DisplayName = "% Time in GC since last GC", DisplayUnits = "%" }; @@ -76,7 +78,10 @@ protected override void OnEventCommand(EventCommandEventArgs command) _gen1SizeCounter ??= new PollingCounter("gen-1-size", this, () => GC.GetGenerationSize(1)) { DisplayName = "Gen 1 Size", DisplayUnits = "B" }; _gen2SizeCounter ??= new PollingCounter("gen-2-size", this, () => GC.GetGenerationSize(2)) { DisplayName = "Gen 2 Size", DisplayUnits = "B" }; _lohSizeCounter ??= new PollingCounter("loh-size", this, () => GC.GetGenerationSize(3)) { DisplayName = "LOH Size", DisplayUnits = "B" }; + _pohSizeCounter ??= new PollingCounter("poh-size", this, () => GC.GetGenerationSize(4)) { DisplayName = "POH (Pinned Object Heap) Size", DisplayUnits = "B" }; _assemblyCounter ??= new PollingCounter("assembly-count", this, () => System.Reflection.Assembly.GetAssemblyCount()) { DisplayName = "Number of Assemblies Loaded" }; + _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.CompilerServices.RuntimeHelpers.GetILBytesJitted()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" }; + _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.CompilerServices.RuntimeHelpers.GetMethodsJittedCount()) { DisplayName = "Number of Methods Jitted" }; #endif } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EnumerableTypeInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EnumerableTypeInfo.cs index 92a1a823f94ee..56d0e061d5a2d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EnumerableTypeInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EnumerableTypeInfo.cs @@ -25,6 +25,8 @@ public EnumerableTypeInfo(Type type, TraceLoggingTypeInfo elementInfo) this.elementInfo = elementInfo; } + internal TraceLoggingTypeInfo ElementInfo { get { return elementInfo; } } + public override void WriteMetadata( TraceLoggingMetadataCollector collector, string? name, diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs index 17bf2eb2aeda6..4ca0b83988f26 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs @@ -88,18 +88,19 @@ public IntPtr GetOrCreateEventHandle(EventProvider provider, TraceLoggingEventHa { if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero) { - byte[]? metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata( + byte[]? metadata = EventPipeMetadataGenerator.Instance.GenerateEventMetadata( descriptor.EventId, name, (EventKeywords)descriptor.Keywords, (EventLevel)descriptor.Level, descriptor.Version, + (EventOpcode)descriptor.Opcode, eventTypes); - uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0; + uint metadataLength = (metadata != null) ? (uint)metadata.Length : 0; unsafe { - fixed (byte* pMetadataBlob = metadataBlob) + fixed (byte* pMetadataBlob = metadata) { // Define the event. eventHandle = provider.m_eventProvider.DefineEventHandle( diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs index 9d80c82f1a4fe..33e294a7862c1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs @@ -10,7 +10,6 @@ using Internal.Runtime.CompilerServices; #if CORERT -using CorElementType = System.Runtime.RuntimeImports.RhCorElementType; using RuntimeType = System.Type; using EnumInfo = Internal.Runtime.Augments.EnumInfo; #endif diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.Unix.GetFolderPathCore.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs similarity index 99% rename from src/libraries/System.Private.CoreLib/src/System/Environment.Unix.GetFolderPathCore.cs rename to src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs index ad37bba3746e5..385b578890402 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.Unix.GetFolderPathCore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs @@ -46,7 +46,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio { Type dirType = Type.GetType("System.IO.Directory, System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true)!; MethodInfo mi = dirType.GetTypeInfo().GetDeclaredMethod("CreateDirectory")!; - return (Func)mi.CreateDelegate(typeof(Func)); + return mi.CreateDelegate>(); }); createDirectory(path); diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.OSX.cs new file mode 100644 index 0000000000000..0c8771938f041 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.OSX.cs @@ -0,0 +1,18 @@ +// 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. + +namespace System +{ + public static partial class Environment + { + private static OperatingSystem GetOSVersion() + { + Version version = Interop.libobjc.GetOperatingSystemVersion(); + + // For compatibility reasons with Mono, PlatformID.Unix is returned on MacOSX. PlatformID.MacOSX + // is hidden from the editor and shouldn't be used. + return new OperatingSystem(PlatformID.Unix, version); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.Unix.cs new file mode 100644 index 0000000000000..0ccea27611aed --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.Unix.cs @@ -0,0 +1,67 @@ +// 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. + +namespace System +{ + public static partial class Environment + { + private static OperatingSystem GetOSVersion() => GetOperatingSystem(Interop.Sys.GetUnixRelease()); + + // Tests exercise this method for corner cases via private reflection + private static OperatingSystem GetOperatingSystem(string release) + { + int major = 0, minor = 0, build = 0, revision = 0; + + // Parse the uname's utsname.release for the first four numbers found. + // This isn't perfect, but Version already doesn't map exactly to all possible release + // formats, e.g. 2.6.19-1.2895.fc6 + if (release != null) + { + int i = 0; + major = FindAndParseNextNumber(release, ref i); + minor = FindAndParseNextNumber(release, ref i); + build = FindAndParseNextNumber(release, ref i); + revision = FindAndParseNextNumber(release, ref i); + } + + return new OperatingSystem(PlatformID.Unix, new Version(major, minor, build, revision)); + } + + private static int FindAndParseNextNumber(string text, ref int pos) + { + // Move to the beginning of the number + for (; pos < text.Length; pos++) + { + char c = text[pos]; + if ('0' <= c && c <= '9') + { + break; + } + } + + // Parse the number; + int num = 0; + for (; pos < text.Length; pos++) + { + char c = text[pos]; + if ('0' > c || c > '9') + break; + + try + { + num = checked((num * 10) + (c - '0')); + } + // Integer overflow can occur for example with: + // Linux nelknet 4.15.0-24201807041620-generic + // To form a valid Version, num must be positive. + catch (OverflowException) + { + return int.MaxValue; + } + } + + return num; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs index c29a56c14b53f..81b516dd45f5d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs @@ -63,66 +63,6 @@ public static string MachineName internal const string NewLineConst = "\n"; - private static OperatingSystem GetOSVersion() => GetOperatingSystem(Interop.Sys.GetUnixRelease()); - - // Tests exercise this method for corner cases via private reflection - private static OperatingSystem GetOperatingSystem(string release) - { - int major = 0, minor = 0, build = 0, revision = 0; - - // Parse the uname's utsname.release for the first four numbers found. - // This isn't perfect, but Version already doesn't map exactly to all possible release - // formats, e.g. 2.6.19-1.2895.fc6 - if (release != null) - { - int i = 0; - major = FindAndParseNextNumber(release, ref i); - minor = FindAndParseNextNumber(release, ref i); - build = FindAndParseNextNumber(release, ref i); - revision = FindAndParseNextNumber(release, ref i); - } - - // For compatibility reasons with Mono, PlatformID.Unix is returned on MacOSX. PlatformID.MacOSX - // is hidden from the editor and shouldn't be used. - return new OperatingSystem(PlatformID.Unix, new Version(major, minor, build, revision)); - } - - private static int FindAndParseNextNumber(string text, ref int pos) - { - // Move to the beginning of the number - for (; pos < text.Length; pos++) - { - char c = text[pos]; - if ('0' <= c && c <= '9') - { - break; - } - } - - // Parse the number; - int num = 0; - for (; pos < text.Length; pos++) - { - char c = text[pos]; - if ('0' > c || c > '9') - break; - - try - { - num = checked((num * 10) + (c - '0')); - } - // Integer overflow can occur for example with: - // Linux nelknet 4.15.0-24201807041620-generic - // To form a valid Version, num must be positive. - catch (OverflowException) - { - return int.MaxValue; - } - } - - return num; - } - public static string SystemDirectory => GetFolderPathCore(SpecialFolder.System, SpecialFolderOption.None); public static int SystemPageSize => CheckedSysConf(Interop.Sys.SysConfName._SC_PAGESIZE); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CharUnicodeInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CharUnicodeInfo.cs index 9a1c24607e71f..51d0ae46b3ae1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CharUnicodeInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CharUnicodeInfo.cs @@ -9,13 +9,6 @@ using System.Text.Unicode; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System.Globalization { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs index 7fb13f2b54625..16bf6d16f4bae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs @@ -45,7 +45,7 @@ public sealed partial class CompareInfo : IDeserializationCallback private IntPtr _sortHandle; [NonSerialized] - private string _sortName = null!; // The name that defines our behavior + private string _sortName; // The name that defines our behavior [OptionalField(VersionAdded = 3)] private SortVersion? m_SortVersion; // Do not rename (binary serialization) @@ -181,6 +181,7 @@ public static bool IsSortable(Rune value) return IsSortable(valueAsUtf16.Slice(0, charCount)); } + [MemberNotNull(nameof(_sortName))] private void InitSort(CultureInfo culture) { _sortName = culture.SortName; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs index 0075e697cd63f..71011882bd9e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs @@ -1103,7 +1103,9 @@ public static CultureInfo GetCultureInfo(string name, string altName) } catch (ArgumentException) { +#pragma warning disable CA2208 // Instantiate argument exceptions correctly, combination of arguments used throw new CultureNotFoundException("name/altName", SR.Format(SR.Argument_OneOfCulturesNotSupported, name, altName)); +#pragma warning restore CA2208 } lock (nameTable) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs index 722c583920963..f7a7c687966f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace System.Globalization @@ -87,7 +88,7 @@ public sealed class DateTimeFormatInfo : IFormatProvider, ICloneable private const string sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; private const string universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"; - private Calendar calendar = null!; // initialized in helper called by ctors + private Calendar calendar; private int firstDayOfWeek = -1; private int calendarWeekRule = -1; @@ -389,6 +390,7 @@ public Calendar Calendar Debug.Assert(calendar != null, "DateTimeFormatInfo.Calendar: calendar != null"); return calendar; } + [MemberNotNull(nameof(calendar))] set { if (IsReadOnly) @@ -732,14 +734,19 @@ public string LongDatePattern // Remember the new string longDatePattern = value; - // Clear the token hash table - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - fullDateTimePattern = null; + OnLongDatePatternChanged(); } } + private void OnLongDatePatternChanged() + { + // Clear the token hash table + ClearTokenHashTable(); + + // Clean up cached values that will be affected by this property. + fullDateTimePattern = null; + } + /// /// For our "patterns" arrays we have 2 variables, a string and a string[] /// @@ -764,16 +771,21 @@ public string LongTimePattern // Remember the new string longTimePattern = value; - // Clear the token hash table - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - fullDateTimePattern = null; // Full date = long date + long Time - generalLongTimePattern = null; // General long date = short date + long Time - dateTimeOffsetPattern = null; + OnLongTimePatternChanged(); } } + private void OnLongTimePatternChanged() + { + // Clear the token hash table + ClearTokenHashTable(); + + // Clean up cached values that will be affected by this property. + fullDateTimePattern = null; // Full date = long date + long Time + generalLongTimePattern = null; // General long date = short date + long Time + dateTimeOffsetPattern = null; + } + /// /// Just to be confusing there's only 1 month day pattern, not a whole list /// @@ -862,16 +874,21 @@ public string ShortDatePattern // Remember the new string shortDatePattern = value; - // Clear the token hash table, note that even short dates could require this - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - generalLongTimePattern = null; // General long time = short date + long time - generalShortTimePattern = null; // General short time = short date + short Time - dateTimeOffsetPattern = null; + OnShortDatePatternChanged(); } } + private void OnShortDatePatternChanged() + { + // Clear the token hash table, note that even short dates could require this + ClearTokenHashTable(); + + // Clean up cached values that will be affected by this property. + generalLongTimePattern = null; // General long time = short date + long time + generalShortTimePattern = null; // General short time = short date + short Time + dateTimeOffsetPattern = null; + } + /// /// For our "patterns" arrays we have 2 variables, a string and a string[] /// @@ -896,14 +913,19 @@ public string ShortTimePattern // Remember the new string shortTimePattern = value; - // Clear the token hash table, note that even short times could require this - ClearTokenHashTable(); - - // Clean up cached values that will be affected by this property. - generalShortTimePattern = null; // General short date = short date + short time. + OnShortTimePatternChanged(); } } + private void OnShortTimePatternChanged() + { + // Clear the token hash table, note that even short times could require this + ClearTokenHashTable(); + + // Clean up cached values that will be affected by this property. + generalShortTimePattern = null; // General short date = short date + short time. + } + public string SortableDateTimePattern => sortableDateTimePattern; /// @@ -1036,11 +1058,16 @@ public string YearMonthPattern // Remember the new string yearMonthPattern = value; - // Clear the token hash table, note that even short times could require this - ClearTokenHashTable(); + OnYearMonthPatternChanged(); } } + private void OnYearMonthPatternChanged() + { + // Clear the token hash table, note that even short times could require this + ClearTokenHashTable(); + } + /// /// Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value" /// @@ -1682,7 +1709,7 @@ public void SetAllDateTimePatterns(string[] patterns, char format) { if (patterns[i] == null) { - throw new ArgumentNullException("patterns[" + i + "]", SR.ArgumentNull_ArrayValue); + throw new ArgumentNullException(nameof(patterns) + "[" + i + "]", SR.ArgumentNull_ArrayValue); } } @@ -1692,35 +1719,37 @@ public void SetAllDateTimePatterns(string[] patterns, char format) case 'd': allShortDatePatterns = patterns; shortDatePattern = allShortDatePatterns[0]; + OnShortDatePatternChanged(); break; case 'D': allLongDatePatterns = patterns; longDatePattern = allLongDatePatterns[0]; + OnLongDatePatternChanged(); break; case 't': allShortTimePatterns = patterns; shortTimePattern = allShortTimePatterns[0]; + OnShortTimePatternChanged(); break; case 'T': allLongTimePatterns = patterns; longTimePattern = allLongTimePatterns[0]; + OnLongTimePatternChanged(); break; case 'y': case 'Y': allYearMonthPatterns = patterns; yearMonthPattern = allYearMonthPatterns[0]; + OnYearMonthPatternChanged(); break; default: throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format)); } - - // Clear the token hash table, note that even short dates could require this - ClearTokenHashTable(); } public string[] AbbreviatedMonthGenitiveNames diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs index 2e8cf088cba05..6fa07d94dee63 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Text.Unicode; namespace System.Globalization @@ -15,7 +16,7 @@ namespace System.Globalization /// public class StringInfo { - private string _str = null!; // initialized in helper called by ctors + private string _str; private int[]? _indexes; @@ -56,6 +57,7 @@ public override bool Equals(object? value) public string String { get => _str; + [MemberNotNull(nameof(_str))] set { _str = value ?? throw new ArgumentNullException(nameof(value)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs index eaa2042fd9e55..0481c684cd8a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.cs @@ -10,13 +10,6 @@ using System.Text.Unicode; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else // TARGET_64BIT -using nuint = System.UInt32; -#endif // TARGET_64BIT - namespace System.Globalization { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs index 1055013fb6312..8b9a53f3952fc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs @@ -306,7 +306,10 @@ public virtual string ReadString() return new string(_charBuffer, 0, charsRead); } - sb ??= StringBuilderCache.Acquire(stringLength); // Actual string length in chars may be smaller. + // Since we could be reading from an untrusted data source, limit the initial size of the + // StringBuilder instance we're about to get or create. It'll expand automatically as needed. + + sb ??= StringBuilderCache.Acquire(Math.Min(stringLength, StringBuilderCache.MaxBuilderSize)); // Actual string length in chars may be smaller. sb.Append(_charBuffer, 0, charsRead); currPos += n; } while (currPos < stringLength); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs index 80fd193b5824b..b4393da162f44 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs @@ -394,7 +394,7 @@ public virtual unsafe void Write(string value) { if (charStart < 0 || charCount < 0 || charStart > value.Length - charCount) { - throw new ArgumentOutOfRangeException(nameof(charCount)); + throw new ArgumentOutOfRangeException(nameof(value)); } fixed (char* pChars = value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Lock.OSX.cs similarity index 100% rename from src/libraries/System.Private.CoreLib/src/System/IO/FileStream.OSX.cs rename to src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Lock.OSX.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Linux.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Lock.Unix.cs similarity index 100% rename from src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Linux.cs rename to src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Lock.Unix.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs index 25cec9463f3f2..752eca8306394 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs @@ -122,13 +122,12 @@ public static bool IsPathRooted(ReadOnlySpan path) public static string? GetPathRoot(string? path) { if (PathInternal.IsEffectivelyEmpty(path)) return null; - return IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString : string.Empty; } public static ReadOnlySpan GetPathRoot(ReadOnlySpan path) { - return PathInternal.IsEffectivelyEmpty(path) && IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString.AsSpan() : ReadOnlySpan.Empty; + return IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString.AsSpan() : ReadOnlySpan.Empty; } /// Gets whether the system is case-sensitive. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs index a2c6bd1764fe0..409e62b87609b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs @@ -23,7 +23,7 @@ namespace System.IO /// this gives better throughput; benchmarks showed about 12-15% better. public class UnmanagedMemoryAccessor : IDisposable { - private SafeBuffer _buffer = null!; // initialized in helper called by ctor + private SafeBuffer _buffer = null!; // initialized in helper called by ctor, but also not initialized by protected ctor private long _offset; private long _capacity; private FileAccess _access; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs index ecdb454203bf4..20fc078c95467 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs @@ -8,13 +8,6 @@ using System.Threading; using System.Threading.Tasks; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System.IO { /* @@ -415,7 +408,7 @@ public override long Position throw new IOException(SR.IO_SeekBeforeBegin); long newPosition = (long)value - (long)_mem; if (newPosition < 0) - throw new ArgumentOutOfRangeException("offset", SR.ArgumentOutOfRange_UnmanagedMemStreamLength); + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_UnmanagedMemStreamLength); Interlocked.Exchange(ref _position, newPosition); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index d82c18f1fa78e..720da614f236e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -11,9 +11,9 @@ #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types #if TARGET_64BIT -using nint = System.Int64; +using nint_t = System.Int64; #else -using nint = System.Int32; +using nint_t = System.Int32; #endif namespace System @@ -162,7 +162,7 @@ public unsafe int ToInt32() public static int Size { [NonVersionable] - get => sizeof(nint); + get => sizeof(nint_t); } [CLSCompliant(false)] @@ -172,25 +172,24 @@ public static int Size public static IntPtr MaxValue { [NonVersionable] - get => (IntPtr)nint.MaxValue; + get => (IntPtr)nint_t.MaxValue; } public static IntPtr MinValue { [NonVersionable] - get => (IntPtr)nint.MinValue; + get => (IntPtr)nint_t.MinValue; } - // Don't just delegate to nint.CompareTo as it needs to throw when not IntPtr + // Don't just delegate to nint_t.CompareTo as it needs to throw when not IntPtr public unsafe int CompareTo(object? value) { if (value is null) { return 1; } - if (value is IntPtr o) + if (value is nint i) { - nint i = (nint)o; if ((nint)_value < i) return -1; if ((nint)_value > i) return 1; return 0; @@ -199,31 +198,31 @@ public unsafe int CompareTo(object? value) throw new ArgumentException(SR.Arg_MustBeIntPtr); } - public unsafe int CompareTo(IntPtr value) => ((nint)_value).CompareTo((nint)value); + public unsafe int CompareTo(IntPtr value) => ((nint_t)_value).CompareTo((nint_t)value); [NonVersionable] - public unsafe bool Equals(IntPtr other) => (nint)_value == (nint)other; + public unsafe bool Equals(IntPtr other) => (nint_t)_value == (nint_t)other; - public unsafe override string ToString() => ((nint)_value).ToString(); - public unsafe string ToString(string? format) => ((nint)_value).ToString(format); - public unsafe string ToString(IFormatProvider? provider) => ((nint)_value).ToString(provider); - public unsafe string ToString(string? format, IFormatProvider? provider) => ((nint)_value).ToString(format, provider); + public unsafe override string ToString() => ((nint_t)_value).ToString(); + public unsafe string ToString(string? format) => ((nint_t)_value).ToString(format); + public unsafe string ToString(IFormatProvider? provider) => ((nint_t)_value).ToString(provider); + public unsafe string ToString(string? format, IFormatProvider? provider) => ((nint_t)_value).ToString(format, provider); - public static IntPtr Parse(string s) => (IntPtr)nint.Parse(s); - public static IntPtr Parse(string s, NumberStyles style) => (IntPtr)nint.Parse(s, style); - public static IntPtr Parse(string s, IFormatProvider? provider) => (IntPtr)nint.Parse(s, provider); - public static IntPtr Parse(string s, NumberStyles style, IFormatProvider? provider) => (IntPtr)nint.Parse(s, style, provider); + public static IntPtr Parse(string s) => (IntPtr)nint_t.Parse(s); + public static IntPtr Parse(string s, NumberStyles style) => (IntPtr)nint_t.Parse(s, style); + public static IntPtr Parse(string s, IFormatProvider? provider) => (IntPtr)nint_t.Parse(s, provider); + public static IntPtr Parse(string s, NumberStyles style, IFormatProvider? provider) => (IntPtr)nint_t.Parse(s, style, provider); public static bool TryParse(string? s, out IntPtr result) { Unsafe.SkipInit(out result); - return nint.TryParse(s, out Unsafe.As(ref result)); + return nint_t.TryParse(s, out Unsafe.As(ref result)); } public static bool TryParse(string? s, NumberStyles style, IFormatProvider? provider, out IntPtr result) { Unsafe.SkipInit(out result); - return nint.TryParse(s, style, provider, out Unsafe.As(ref result)); + return nint_t.TryParse(s, style, provider, out Unsafe.As(ref result)); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs b/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs index c8ff3fb7eaefe..9867caac97dbd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs @@ -8,13 +8,6 @@ using System.Text.Unicode; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { internal static partial class Marvin diff --git a/src/libraries/System.Private.CoreLib/src/System/Marvin.cs b/src/libraries/System.Private.CoreLib/src/System/Marvin.cs index 4e5b9d5a035b6..f397c230b5019 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Marvin.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Marvin.cs @@ -8,13 +8,6 @@ using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { internal static partial class Marvin diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index 9e90ad9ca1176..2b0ca9e0f279b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -18,6 +18,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.X86; using System.Runtime.Versioning; namespace System @@ -113,6 +114,61 @@ public static long BigMul(int a, int b) return ((long)a) * b; } + /// Produces the full product of two unsigned 64-bit numbers. + /// The first number to multiply. + /// The second number to multiply. + /// The low 64-bit of the product of the specied numbers. + /// The high 64-bit of the product of the specied numbers. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe ulong BigMul(ulong a, ulong b, out ulong low) + { + if (Bmi2.X64.IsSupported) + { + ulong tmp; + ulong high = Bmi2.X64.MultiplyNoFlags(a, b, &tmp); + low = tmp; + return high; + } + + return SoftwareFallback(a, b, out low); + + static ulong SoftwareFallback(ulong a, ulong b, out ulong low) + { + // Adaptation of algorithm for multiplication + // of 32-bit unsigned integers described + // in Hacker's Delight by Henry S. Warren, Jr. (ISBN 0-201-91465-4), Chapter 8 + // Basically, it's an optimized version of FOIL method applied to + // low and high dwords of each operand + + // Use 32-bit uints to optimize the fallback for 32-bit platforms. + uint al = (uint)a; + uint ah = (uint)(a >> 32); + uint bl = (uint)b; + uint bh = (uint)(b >> 32); + + ulong mull = ((ulong)al) * bl; + ulong t = ((ulong)ah) * bl + (mull >> 32); + ulong tl = ((ulong)al) * bh + (uint)t; + + low = tl << 32 | (uint)mull; + + return ((ulong)ah) * bh + (t >> 32) + (tl >> 32); + } + } + + /// Produces the full product of two 64-bit numbers. + /// The first number to multiply. + /// The second number to multiply. + /// The low 64-bit of the product of the specied numbers. + /// The high 64-bit of the product of the specied numbers. + public static long BigMul(long a, long b, out long low) + { + ulong high = BigMul((ulong)a, (ulong)b, out ulong ulow); + low = (long)ulow; + return (long)high - ((a >> 63) & b) - ((b >> 63) & a); + } + public static double BitDecrement(double x) { long bits = BitConverter.DoubleToInt64Bits(x); diff --git a/src/libraries/System.Private.CoreLib/src/System/Memory.cs b/src/libraries/System.Private.CoreLib/src/System/Memory.cs index cb8f631c5d44c..bed73caea1357 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Memory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Memory.cs @@ -12,13 +12,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else // TARGET_64BIT -using nuint = System.UInt32; -#endif // TARGET_64BIT - namespace System { /// @@ -364,7 +357,7 @@ public unsafe Span Span ThrowHelper.ThrowArgumentOutOfRangeException(); } #else - if ((uint)desiredStartIndex > (uint)lengthOfUnderlyingSpan || (uint)desiredLength > (uint)(lengthOfUnderlyingSpan - desiredStartIndex)) + if ((uint)desiredStartIndex > (uint)lengthOfUnderlyingSpan || (uint)desiredLength > (uint)lengthOfUnderlyingSpan - (uint)desiredStartIndex) { ThrowHelper.ThrowArgumentOutOfRangeException(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 2a66efac7709c..33bc6f9e1fffc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -8,13 +8,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif // TARGET_64BIT - namespace System { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs index 223a446ae8eb6..8a5416d728656 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs @@ -111,7 +111,7 @@ public static class Nullable { if (nullableEEType.IsNullable) { - return Internal.Reflection.Core.NonPortable.RuntimeTypeUnifier.GetRuntimeTypeForEEType(nullableEEType.NullableType); + return Type.GetTypeFromEETypePtr(nullableEEType.NullableType); } } return null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index c8356a0c9eb01..28b341633de4e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -4,6 +4,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; @@ -122,21 +123,18 @@ public static int LeadingZeroCount(ulong value) /// /// Returns the integer (floor) log of the specified value, base 2. - /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. + /// Note that by convention, input value 0 returns 0 since log(0) is undefined. /// /// The value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static int Log2(uint value) { - // Enforce conventional contract 0->0 (Log(0) is undefined) - if (value == 0) - { - return 0; - } + // The 0->0 contract is fulfilled by setting the LSB to 1. + // Log(1) is 0, and setting the LSB for values > 1 does not change the log2 result. + value |= 1; // value lzcnt actual expected - // ..0000 32 0 0 (by convention, guard clause) // ..0001 31 31-31 0 // ..0010 30 31-30 1 // 0010.. 2 31-2 29 @@ -152,8 +150,8 @@ public static int Log2(uint value) return 31 ^ ArmBase.LeadingZeroCount(value); } - // BSR returns the answer we're looking for directly. - // However BSR is much slower than LZCNT on AMD processors, so we leave it as a fallback only. + // BSR returns the log2 result directly. However BSR is slower than LZCNT + // on AMD processors, so we leave it as a fallback only. if (X86Base.IsSupported) { return (int)X86Base.BitScanReverse(value); @@ -165,18 +163,14 @@ public static int Log2(uint value) /// /// Returns the integer (floor) log of the specified value, base 2. - /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. + /// Note that by convention, input value 0 returns 0 since log(0) is undefined. /// /// The value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static int Log2(ulong value) { - // Enforce conventional contract 0->0 (Log(0) is undefined) - if (value == 0) - { - return 0; - } + value |= 1; if (Lzcnt.X64.IsSupported) { @@ -243,6 +237,19 @@ public static int PopCount(uint value) return (int)Popcnt.PopCount(value); } + if (AdvSimd.Arm64.IsSupported) + { + // PopCount works on vector so convert input value to vector first. + + // Vector64.CreateScalar(uint) generates suboptimal code by storing and + // loading the result to memory. + // See https://github.com/dotnet/runtime/issues/35976 for details. + // Hence use Vector64.Create(ulong) to create Vector64 and operate on that. + Vector64 input = Vector64.Create((ulong)value); + Vector64 aggregated = AdvSimd.Arm64.AddAcross(AdvSimd.PopCount(input.AsByte())); + return aggregated.ToScalar(); + } + return SoftwareFallback(value); static int SoftwareFallback(uint value) @@ -274,6 +281,14 @@ public static int PopCount(ulong value) return (int)Popcnt.X64.PopCount(value); } + if (AdvSimd.Arm64.IsSupported) + { + // PopCount works on vector so convert input value to vector first. + Vector64 input = Vector64.Create(value); + Vector64 aggregated = AdvSimd.Arm64.AddAcross(AdvSimd.PopCount(input.AsByte())); + return aggregated.ToScalar(); + } + #if TARGET_32BIT return PopCount((uint)value) // lo + PopCount((uint)(value >> 32)); // hi diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs index c49c02c18dd20..7323ba23e3dd7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs @@ -1,8 +1,10 @@ // 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 Internal.Runtime.CompilerServices; +using System.Diagnostics; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -1305,171 +1307,360 @@ public static Matrix4x4 CreateReflection(Plane value) d * (e * jo_kn - f * io_km + g * in_jm); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 Permute(Vector128 value, byte control) + { + if (Avx.IsSupported) + { + return Avx.Permute(value, control); + } + + Debug.Assert(Sse.IsSupported); + return Sse.Shuffle(value, value, control); + } + /// /// Attempts to calculate the inverse of the given matrix. If successful, result will contain the inverted matrix. /// /// The source matrix to invert. /// If successful, contains the inverted matrix. /// True if the source matrix could be inverted; False otherwise. - public static bool Invert(Matrix4x4 matrix, out Matrix4x4 result) + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe bool Invert(Matrix4x4 matrix, out Matrix4x4 result) { - // -1 - // If you have matrix M, inverse Matrix M can compute - // - // -1 1 - // M = --------- A - // det(M) - // - // A is adjugate (adjoint) of M, where, - // - // T - // A = C - // - // C is Cofactor matrix of M, where, - // i + j - // C = (-1) * det(M ) - // ij ij - // - // [ a b c d ] - // M = [ e f g h ] - // [ i j k l ] - // [ m n o p ] - // - // First Row - // 2 | f g h | - // C = (-1) | j k l | = + ( f ( kp - lo ) - g ( jp - ln ) + h ( jo - kn ) ) - // 11 | n o p | - // - // 3 | e g h | - // C = (-1) | i k l | = - ( e ( kp - lo ) - g ( ip - lm ) + h ( io - km ) ) - // 12 | m o p | - // - // 4 | e f h | - // C = (-1) | i j l | = + ( e ( jp - ln ) - f ( ip - lm ) + h ( in - jm ) ) - // 13 | m n p | - // - // 5 | e f g | - // C = (-1) | i j k | = - ( e ( jo - kn ) - f ( io - km ) + g ( in - jm ) ) - // 14 | m n o | - // - // Second Row - // 3 | b c d | - // C = (-1) | j k l | = - ( b ( kp - lo ) - c ( jp - ln ) + d ( jo - kn ) ) - // 21 | n o p | - // - // 4 | a c d | - // C = (-1) | i k l | = + ( a ( kp - lo ) - c ( ip - lm ) + d ( io - km ) ) - // 22 | m o p | - // - // 5 | a b d | - // C = (-1) | i j l | = - ( a ( jp - ln ) - b ( ip - lm ) + d ( in - jm ) ) - // 23 | m n p | - // - // 6 | a b c | - // C = (-1) | i j k | = + ( a ( jo - kn ) - b ( io - km ) + c ( in - jm ) ) - // 24 | m n o | - // - // Third Row - // 4 | b c d | - // C = (-1) | f g h | = + ( b ( gp - ho ) - c ( fp - hn ) + d ( fo - gn ) ) - // 31 | n o p | - // - // 5 | a c d | - // C = (-1) | e g h | = - ( a ( gp - ho ) - c ( ep - hm ) + d ( eo - gm ) ) - // 32 | m o p | - // - // 6 | a b d | - // C = (-1) | e f h | = + ( a ( fp - hn ) - b ( ep - hm ) + d ( en - fm ) ) - // 33 | m n p | - // - // 7 | a b c | - // C = (-1) | e f g | = - ( a ( fo - gn ) - b ( eo - gm ) + c ( en - fm ) ) - // 34 | m n o | - // - // Fourth Row - // 5 | b c d | - // C = (-1) | f g h | = - ( b ( gl - hk ) - c ( fl - hj ) + d ( fk - gj ) ) - // 41 | j k l | - // - // 6 | a c d | - // C = (-1) | e g h | = + ( a ( gl - hk ) - c ( el - hi ) + d ( ek - gi ) ) - // 42 | i k l | - // - // 7 | a b d | - // C = (-1) | e f h | = - ( a ( fl - hj ) - b ( el - hi ) + d ( ej - fi ) ) - // 43 | i j l | - // - // 8 | a b c | - // C = (-1) | e f g | = + ( a ( fk - gj ) - b ( ek - gi ) + c ( ej - fi ) ) - // 44 | i j k | - // - // Cost of operation - // 53 adds, 104 muls, and 1 div. - float a = matrix.M11, b = matrix.M12, c = matrix.M13, d = matrix.M14; - float e = matrix.M21, f = matrix.M22, g = matrix.M23, h = matrix.M24; - float i = matrix.M31, j = matrix.M32, k = matrix.M33, l = matrix.M34; - float m = matrix.M41, n = matrix.M42, o = matrix.M43, p = matrix.M44; + if (Sse.IsSupported) + { + return SseImpl(matrix, out result); + } - float kp_lo = k * p - l * o; - float jp_ln = j * p - l * n; - float jo_kn = j * o - k * n; - float ip_lm = i * p - l * m; - float io_km = i * o - k * m; - float in_jm = i * n - j * m; + return SoftwareFallback(matrix, out result); - float a11 = +(f * kp_lo - g * jp_ln + h * jo_kn); - float a12 = -(e * kp_lo - g * ip_lm + h * io_km); - float a13 = +(e * jp_ln - f * ip_lm + h * in_jm); - float a14 = -(e * jo_kn - f * io_km + g * in_jm); + static unsafe bool SseImpl(Matrix4x4 matrix, out Matrix4x4 result) + { + // This implementation is based on the DirectX Math Library XMMInverse method + // https://github.com/microsoft/DirectXMath/blob/master/Inc/DirectXMathMatrix.inl - float det = a * a11 + b * a12 + c * a13 + d * a14; + // Load the matrix values into rows + Vector128 row1 = Sse.LoadVector128(&matrix.M11); + Vector128 row2 = Sse.LoadVector128(&matrix.M21); + Vector128 row3 = Sse.LoadVector128(&matrix.M31); + Vector128 row4 = Sse.LoadVector128(&matrix.M41); - if (MathF.Abs(det) < float.Epsilon) - { - result = new Matrix4x4(float.NaN, float.NaN, float.NaN, float.NaN, - float.NaN, float.NaN, float.NaN, float.NaN, - float.NaN, float.NaN, float.NaN, float.NaN, - float.NaN, float.NaN, float.NaN, float.NaN); - return false; + // Transpose the matrix + Vector128 vTemp1 = Sse.Shuffle(row1, row2, 0x44); //_MM_SHUFFLE(1, 0, 1, 0) + Vector128 vTemp3 = Sse.Shuffle(row1, row2, 0xEE); //_MM_SHUFFLE(3, 2, 3, 2) + Vector128 vTemp2 = Sse.Shuffle(row3, row4, 0x44); //_MM_SHUFFLE(1, 0, 1, 0) + Vector128 vTemp4 = Sse.Shuffle(row3, row4, 0xEE); //_MM_SHUFFLE(3, 2, 3, 2) + + row1 = Sse.Shuffle(vTemp1, vTemp2, 0x88); //_MM_SHUFFLE(2, 0, 2, 0) + row2 = Sse.Shuffle(vTemp1, vTemp2, 0xDD); //_MM_SHUFFLE(3, 1, 3, 1) + row3 = Sse.Shuffle(vTemp3, vTemp4, 0x88); //_MM_SHUFFLE(2, 0, 2, 0) + row4 = Sse.Shuffle(vTemp3, vTemp4, 0xDD); //_MM_SHUFFLE(3, 1, 3, 1) + + Vector128 V00 = Permute(row3, 0x50); //_MM_SHUFFLE(1, 1, 0, 0) + Vector128 V10 = Permute(row4, 0xEE); //_MM_SHUFFLE(3, 2, 3, 2) + Vector128 V01 = Permute(row1, 0x50); //_MM_SHUFFLE(1, 1, 0, 0) + Vector128 V11 = Permute(row2, 0xEE); //_MM_SHUFFLE(3, 2, 3, 2) + Vector128 V02 = Sse.Shuffle(row3, row1, 0x88); //_MM_SHUFFLE(2, 0, 2, 0) + Vector128 V12 = Sse.Shuffle(row4, row2, 0xDD); //_MM_SHUFFLE(3, 1, 3, 1) + + Vector128 D0 = Sse.Multiply(V00, V10); + Vector128 D1 = Sse.Multiply(V01, V11); + Vector128 D2 = Sse.Multiply(V02, V12); + + V00 = Permute(row3, 0xEE); //_MM_SHUFFLE(3, 2, 3, 2) + V10 = Permute(row4, 0x50); //_MM_SHUFFLE(1, 1, 0, 0) + V01 = Permute(row1, 0xEE); //_MM_SHUFFLE(3, 2, 3, 2) + V11 = Permute(row2, 0x50); //_MM_SHUFFLE(1, 1, 0, 0) + V02 = Sse.Shuffle(row3, row1, 0xDD); //_MM_SHUFFLE(3, 1, 3, 1) + V12 = Sse.Shuffle(row4, row2, 0x88); //_MM_SHUFFLE(2, 0, 2, 0) + + // Note: We use this expansion pattern instead of Fused Multiply Add + // in order to support older hardware + D0 = Sse.Subtract(D0, Sse.Multiply(V00, V10)); + D1 = Sse.Subtract(D1, Sse.Multiply(V01, V11)); + D2 = Sse.Subtract(D2, Sse.Multiply(V02, V12)); + + // V11 = D0Y,D0W,D2Y,D2Y + V11 = Sse.Shuffle(D0, D2, 0x5D); //_MM_SHUFFLE(1, 1, 3, 1) + V00 = Permute(row2, 0x49); //_MM_SHUFFLE(1, 0, 2, 1) + V10 = Sse.Shuffle(V11, D0, 0x32); //_MM_SHUFFLE(0, 3, 0, 2) + V01 = Permute(row1, 0x12); //_MM_SHUFFLE(0, 1, 0, 2) + V11 = Sse.Shuffle(V11, D0, 0x99); //_MM_SHUFFLE(2, 1, 2, 1) + + // V13 = D1Y,D1W,D2W,D2W + Vector128 V13 = Sse.Shuffle(D1, D2, 0xFD); //_MM_SHUFFLE(3, 3, 3, 1) + V02 = Permute(row4, 0x49); //_MM_SHUFFLE(1, 0, 2, 1) + V12 = Sse.Shuffle(V13, D1, 0x32); //_MM_SHUFFLE(0, 3, 0, 2) + Vector128 V03 = Permute(row3, 0x12); //_MM_SHUFFLE(0, 1, 0, 2) + V13 = Sse.Shuffle(V13, D1, 0x99); //_MM_SHUFFLE(2, 1, 2, 1) + + Vector128 C0 = Sse.Multiply(V00, V10); + Vector128 C2 = Sse.Multiply(V01, V11); + Vector128 C4 = Sse.Multiply(V02, V12); + Vector128 C6 = Sse.Multiply(V03, V13); + + // V11 = D0X,D0Y,D2X,D2X + V11 = Sse.Shuffle(D0, D2, 0x4); //_MM_SHUFFLE(0, 0, 1, 0) + V00 = Permute(row2, 0x9e); //_MM_SHUFFLE(2, 1, 3, 2) + V10 = Sse.Shuffle(D0, V11, 0x93); //_MM_SHUFFLE(2, 1, 0, 3) + V01 = Permute(row1, 0x7b); //_MM_SHUFFLE(1, 3, 2, 3) + V11 = Sse.Shuffle(D0, V11, 0x26); //_MM_SHUFFLE(0, 2, 1, 2) + + // V13 = D1X,D1Y,D2Z,D2Z + V13 = Sse.Shuffle(D1, D2, 0xa4); //_MM_SHUFFLE(2, 2, 1, 0) + V02 = Permute(row4, 0x9e); //_MM_SHUFFLE(2, 1, 3, 2) + V12 = Sse.Shuffle(D1, V13, 0x93); //_MM_SHUFFLE(2, 1, 0, 3) + V03 = Permute(row3, 0x7b); //_MM_SHUFFLE(1, 3, 2, 3) + V13 = Sse.Shuffle(D1, V13, 0x26); //_MM_SHUFFLE(0, 2, 1, 2) + + C0 = Sse.Subtract(C0, Sse.Multiply(V00, V10)); + C2 = Sse.Subtract(C2, Sse.Multiply(V01, V11)); + C4 = Sse.Subtract(C4, Sse.Multiply(V02, V12)); + C6 = Sse.Subtract(C6, Sse.Multiply(V03, V13)); + + V00 = Permute(row2, 0x33); //_MM_SHUFFLE(0, 3, 0, 3) + + // V10 = D0Z,D0Z,D2X,D2Y + V10 = Sse.Shuffle(D0, D2, 0x4A); //_MM_SHUFFLE(1, 0, 2, 2) + V10 = Permute(V10, 0x2C); //_MM_SHUFFLE(0, 2, 3, 0) + V01 = Permute(row1, 0x8D); //_MM_SHUFFLE(2, 0, 3, 1) + + // V11 = D0X,D0W,D2X,D2Y + V11 = Sse.Shuffle(D0, D2, 0x4C); //_MM_SHUFFLE(1, 0, 3, 0) + V11 = Permute(V11, 0x93); //_MM_SHUFFLE(2, 1, 0, 3) + V02 = Permute(row4, 0x33); //_MM_SHUFFLE(0, 3, 0, 3) + + // V12 = D1Z,D1Z,D2Z,D2W + V12 = Sse.Shuffle(D1, D2, 0xEA); //_MM_SHUFFLE(3, 2, 2, 2) + V12 = Permute(V12, 0x2C); //_MM_SHUFFLE(0, 2, 3, 0) + V03 = Permute(row3, 0x8D); //_MM_SHUFFLE(2, 0, 3, 1) + + // V13 = D1X,D1W,D2Z,D2W + V13 = Sse.Shuffle(D1, D2, 0xEC); //_MM_SHUFFLE(3, 2, 3, 0) + V13 = Permute(V13, 0x93); //_MM_SHUFFLE(2, 1, 0, 3) + + V00 = Sse.Multiply(V00, V10); + V01 = Sse.Multiply(V01, V11); + V02 = Sse.Multiply(V02, V12); + V03 = Sse.Multiply(V03, V13); + + Vector128 C1 = Sse.Subtract(C0, V00); + C0 = Sse.Add(C0, V00); + Vector128 C3 = Sse.Add(C2, V01); + C2 = Sse.Subtract(C2, V01); + Vector128 C5 = Sse.Subtract(C4, V02); + C4 = Sse.Add(C4, V02); + Vector128 C7 = Sse.Add(C6, V03); + C6 = Sse.Subtract(C6, V03); + + C0 = Sse.Shuffle(C0, C1, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + C2 = Sse.Shuffle(C2, C3, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + C4 = Sse.Shuffle(C4, C5, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + C6 = Sse.Shuffle(C6, C7, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + + C0 = Permute(C0, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + C2 = Permute(C2, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + C4 = Permute(C4, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + C6 = Permute(C6, 0xD8); //_MM_SHUFFLE(3, 1, 2, 0) + + // Get the determinant + vTemp2 = row1; + float det = Vector4.Dot(C0.AsVector4(), vTemp2.AsVector4()); + + // Check determinate is not zero + if (MathF.Abs(det) < float.Epsilon) + { + result = new Matrix4x4(float.NaN, float.NaN, float.NaN, float.NaN, + float.NaN, float.NaN, float.NaN, float.NaN, + float.NaN, float.NaN, float.NaN, float.NaN, + float.NaN, float.NaN, float.NaN, float.NaN); + return false; + } + + // Create Vector128 copy of the determinant and invert them. + Vector128 ones = Vector128.Create(1.0f); + Vector128 vTemp = Vector128.Create(det); + vTemp = Sse.Divide(ones, vTemp); + + row1 = Sse.Multiply(C0, vTemp); + row2 = Sse.Multiply(C2, vTemp); + row3 = Sse.Multiply(C4, vTemp); + row4 = Sse.Multiply(C6, vTemp); + + Unsafe.SkipInit(out result); + ref Vector128 vResult = ref Unsafe.As>(ref result); + + vResult = row1; + Unsafe.Add(ref vResult, 1) = row2; + Unsafe.Add(ref vResult, 2) = row3; + Unsafe.Add(ref vResult, 3) = row4; + + return true; } - float invDet = 1.0f / det; - - result.M11 = a11 * invDet; - result.M21 = a12 * invDet; - result.M31 = a13 * invDet; - result.M41 = a14 * invDet; - - result.M12 = -(b * kp_lo - c * jp_ln + d * jo_kn) * invDet; - result.M22 = +(a * kp_lo - c * ip_lm + d * io_km) * invDet; - result.M32 = -(a * jp_ln - b * ip_lm + d * in_jm) * invDet; - result.M42 = +(a * jo_kn - b * io_km + c * in_jm) * invDet; - - float gp_ho = g * p - h * o; - float fp_hn = f * p - h * n; - float fo_gn = f * o - g * n; - float ep_hm = e * p - h * m; - float eo_gm = e * o - g * m; - float en_fm = e * n - f * m; - - result.M13 = +(b * gp_ho - c * fp_hn + d * fo_gn) * invDet; - result.M23 = -(a * gp_ho - c * ep_hm + d * eo_gm) * invDet; - result.M33 = +(a * fp_hn - b * ep_hm + d * en_fm) * invDet; - result.M43 = -(a * fo_gn - b * eo_gm + c * en_fm) * invDet; - - float gl_hk = g * l - h * k; - float fl_hj = f * l - h * j; - float fk_gj = f * k - g * j; - float el_hi = e * l - h * i; - float ek_gi = e * k - g * i; - float ej_fi = e * j - f * i; - - result.M14 = -(b * gl_hk - c * fl_hj + d * fk_gj) * invDet; - result.M24 = +(a * gl_hk - c * el_hi + d * ek_gi) * invDet; - result.M34 = -(a * fl_hj - b * el_hi + d * ej_fi) * invDet; - result.M44 = +(a * fk_gj - b * ek_gi + c * ej_fi) * invDet; - - return true; + static bool SoftwareFallback(Matrix4x4 matrix, out Matrix4x4 result) + { + // -1 + // If you have matrix M, inverse Matrix M can compute + // + // -1 1 + // M = --------- A + // det(M) + // + // A is adjugate (adjoint) of M, where, + // + // T + // A = C + // + // C is Cofactor matrix of M, where, + // i + j + // C = (-1) * det(M ) + // ij ij + // + // [ a b c d ] + // M = [ e f g h ] + // [ i j k l ] + // [ m n o p ] + // + // First Row + // 2 | f g h | + // C = (-1) | j k l | = + ( f ( kp - lo ) - g ( jp - ln ) + h ( jo - kn ) ) + // 11 | n o p | + // + // 3 | e g h | + // C = (-1) | i k l | = - ( e ( kp - lo ) - g ( ip - lm ) + h ( io - km ) ) + // 12 | m o p | + // + // 4 | e f h | + // C = (-1) | i j l | = + ( e ( jp - ln ) - f ( ip - lm ) + h ( in - jm ) ) + // 13 | m n p | + // + // 5 | e f g | + // C = (-1) | i j k | = - ( e ( jo - kn ) - f ( io - km ) + g ( in - jm ) ) + // 14 | m n o | + // + // Second Row + // 3 | b c d | + // C = (-1) | j k l | = - ( b ( kp - lo ) - c ( jp - ln ) + d ( jo - kn ) ) + // 21 | n o p | + // + // 4 | a c d | + // C = (-1) | i k l | = + ( a ( kp - lo ) - c ( ip - lm ) + d ( io - km ) ) + // 22 | m o p | + // + // 5 | a b d | + // C = (-1) | i j l | = - ( a ( jp - ln ) - b ( ip - lm ) + d ( in - jm ) ) + // 23 | m n p | + // + // 6 | a b c | + // C = (-1) | i j k | = + ( a ( jo - kn ) - b ( io - km ) + c ( in - jm ) ) + // 24 | m n o | + // + // Third Row + // 4 | b c d | + // C = (-1) | f g h | = + ( b ( gp - ho ) - c ( fp - hn ) + d ( fo - gn ) ) + // 31 | n o p | + // + // 5 | a c d | + // C = (-1) | e g h | = - ( a ( gp - ho ) - c ( ep - hm ) + d ( eo - gm ) ) + // 32 | m o p | + // + // 6 | a b d | + // C = (-1) | e f h | = + ( a ( fp - hn ) - b ( ep - hm ) + d ( en - fm ) ) + // 33 | m n p | + // + // 7 | a b c | + // C = (-1) | e f g | = - ( a ( fo - gn ) - b ( eo - gm ) + c ( en - fm ) ) + // 34 | m n o | + // + // Fourth Row + // 5 | b c d | + // C = (-1) | f g h | = - ( b ( gl - hk ) - c ( fl - hj ) + d ( fk - gj ) ) + // 41 | j k l | + // + // 6 | a c d | + // C = (-1) | e g h | = + ( a ( gl - hk ) - c ( el - hi ) + d ( ek - gi ) ) + // 42 | i k l | + // + // 7 | a b d | + // C = (-1) | e f h | = - ( a ( fl - hj ) - b ( el - hi ) + d ( ej - fi ) ) + // 43 | i j l | + // + // 8 | a b c | + // C = (-1) | e f g | = + ( a ( fk - gj ) - b ( ek - gi ) + c ( ej - fi ) ) + // 44 | i j k | + // + // Cost of operation + // 53 adds, 104 muls, and 1 div. + float a = matrix.M11, b = matrix.M12, c = matrix.M13, d = matrix.M14; + float e = matrix.M21, f = matrix.M22, g = matrix.M23, h = matrix.M24; + float i = matrix.M31, j = matrix.M32, k = matrix.M33, l = matrix.M34; + float m = matrix.M41, n = matrix.M42, o = matrix.M43, p = matrix.M44; + + float kp_lo = k * p - l * o; + float jp_ln = j * p - l * n; + float jo_kn = j * o - k * n; + float ip_lm = i * p - l * m; + float io_km = i * o - k * m; + float in_jm = i * n - j * m; + + float a11 = +(f * kp_lo - g * jp_ln + h * jo_kn); + float a12 = -(e * kp_lo - g * ip_lm + h * io_km); + float a13 = +(e * jp_ln - f * ip_lm + h * in_jm); + float a14 = -(e * jo_kn - f * io_km + g * in_jm); + + float det = a * a11 + b * a12 + c * a13 + d * a14; + + if (MathF.Abs(det) < float.Epsilon) + { + result = new Matrix4x4(float.NaN, float.NaN, float.NaN, float.NaN, + float.NaN, float.NaN, float.NaN, float.NaN, + float.NaN, float.NaN, float.NaN, float.NaN, + float.NaN, float.NaN, float.NaN, float.NaN); + return false; + } + + float invDet = 1.0f / det; + + result.M11 = a11 * invDet; + result.M21 = a12 * invDet; + result.M31 = a13 * invDet; + result.M41 = a14 * invDet; + + result.M12 = -(b * kp_lo - c * jp_ln + d * jo_kn) * invDet; + result.M22 = +(a * kp_lo - c * ip_lm + d * io_km) * invDet; + result.M32 = -(a * jp_ln - b * ip_lm + d * in_jm) * invDet; + result.M42 = +(a * jo_kn - b * io_km + c * in_jm) * invDet; + + float gp_ho = g * p - h * o; + float fp_hn = f * p - h * n; + float fo_gn = f * o - g * n; + float ep_hm = e * p - h * m; + float eo_gm = e * o - g * m; + float en_fm = e * n - f * m; + + result.M13 = +(b * gp_ho - c * fp_hn + d * fo_gn) * invDet; + result.M23 = -(a * gp_ho - c * ep_hm + d * eo_gm) * invDet; + result.M33 = +(a * fp_hn - b * ep_hm + d * en_fm) * invDet; + result.M43 = -(a * fo_gn - b * eo_gm + c * en_fm) * invDet; + + float gl_hk = g * l - h * k; + float fl_hj = f * l - h * j; + float fk_gj = f * k - g * j; + float el_hi = e * l - h * i; + float ek_gi = e * k - g * i; + float ej_fi = e * j - f * i; + + result.M14 = -(b * gl_hk - c * fl_hj + d * fk_gj) * invDet; + result.M24 = +(a * gl_hk - c * el_hi + d * ek_gi) * invDet; + result.M34 = -(a * fl_hj - b * el_hi + d * ej_fi) * invDet; + result.M44 = +(a * fk_gj - b * ek_gi + c * ej_fi) * invDet; + + return true; + } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index f20b762afbf13..4cfebe72cab69 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -10,13 +10,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nint = System.Int64; -#else -using nint = System.Int32; -#endif - namespace System.Numerics { /* Note: The following patterns are used throughout the code here and are described here @@ -91,12 +84,12 @@ public static Vector One } private static readonly Vector s_one = new Vector(GetOneValue()); - internal static Vector AllOnes + internal static Vector AllBitsSet { [Intrinsic] - get => s_allOnes; + get => s_allBitsSet; } - private static readonly Vector s_allOnes = new Vector(GetAllBitsSetValue()); + private static readonly Vector s_allBitsSet = new Vector(GetAllBitsSetValue()); #endregion Static Members #region Constructors @@ -485,11 +478,7 @@ public Vector(Span values) [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) { - if (!(obj is Vector)) - { - return false; - } - return Equals((Vector)obj); + return (obj is Vector other) && Equals(other); } /// @@ -500,130 +489,7 @@ public Vector(Span values) [Intrinsic] public readonly bool Equals(Vector other) { - if (Vector.IsHardwareAccelerated) - { - for (int g = 0; g < Count; g++) - { - if (!ScalarEquals(this[g], other[g])) - { - return false; - } - } - return true; - } - else - { - if (typeof(T) == typeof(byte)) - { - return - this.register.byte_0 == other.register.byte_0 - && this.register.byte_1 == other.register.byte_1 - && this.register.byte_2 == other.register.byte_2 - && this.register.byte_3 == other.register.byte_3 - && this.register.byte_4 == other.register.byte_4 - && this.register.byte_5 == other.register.byte_5 - && this.register.byte_6 == other.register.byte_6 - && this.register.byte_7 == other.register.byte_7 - && this.register.byte_8 == other.register.byte_8 - && this.register.byte_9 == other.register.byte_9 - && this.register.byte_10 == other.register.byte_10 - && this.register.byte_11 == other.register.byte_11 - && this.register.byte_12 == other.register.byte_12 - && this.register.byte_13 == other.register.byte_13 - && this.register.byte_14 == other.register.byte_14 - && this.register.byte_15 == other.register.byte_15; - } - else if (typeof(T) == typeof(sbyte)) - { - return - this.register.sbyte_0 == other.register.sbyte_0 - && this.register.sbyte_1 == other.register.sbyte_1 - && this.register.sbyte_2 == other.register.sbyte_2 - && this.register.sbyte_3 == other.register.sbyte_3 - && this.register.sbyte_4 == other.register.sbyte_4 - && this.register.sbyte_5 == other.register.sbyte_5 - && this.register.sbyte_6 == other.register.sbyte_6 - && this.register.sbyte_7 == other.register.sbyte_7 - && this.register.sbyte_8 == other.register.sbyte_8 - && this.register.sbyte_9 == other.register.sbyte_9 - && this.register.sbyte_10 == other.register.sbyte_10 - && this.register.sbyte_11 == other.register.sbyte_11 - && this.register.sbyte_12 == other.register.sbyte_12 - && this.register.sbyte_13 == other.register.sbyte_13 - && this.register.sbyte_14 == other.register.sbyte_14 - && this.register.sbyte_15 == other.register.sbyte_15; - } - else if (typeof(T) == typeof(ushort)) - { - return - this.register.uint16_0 == other.register.uint16_0 - && this.register.uint16_1 == other.register.uint16_1 - && this.register.uint16_2 == other.register.uint16_2 - && this.register.uint16_3 == other.register.uint16_3 - && this.register.uint16_4 == other.register.uint16_4 - && this.register.uint16_5 == other.register.uint16_5 - && this.register.uint16_6 == other.register.uint16_6 - && this.register.uint16_7 == other.register.uint16_7; - } - else if (typeof(T) == typeof(short)) - { - return - this.register.int16_0 == other.register.int16_0 - && this.register.int16_1 == other.register.int16_1 - && this.register.int16_2 == other.register.int16_2 - && this.register.int16_3 == other.register.int16_3 - && this.register.int16_4 == other.register.int16_4 - && this.register.int16_5 == other.register.int16_5 - && this.register.int16_6 == other.register.int16_6 - && this.register.int16_7 == other.register.int16_7; - } - else if (typeof(T) == typeof(uint)) - { - return - this.register.uint32_0 == other.register.uint32_0 - && this.register.uint32_1 == other.register.uint32_1 - && this.register.uint32_2 == other.register.uint32_2 - && this.register.uint32_3 == other.register.uint32_3; - } - else if (typeof(T) == typeof(int)) - { - return - this.register.int32_0 == other.register.int32_0 - && this.register.int32_1 == other.register.int32_1 - && this.register.int32_2 == other.register.int32_2 - && this.register.int32_3 == other.register.int32_3; - } - else if (typeof(T) == typeof(ulong)) - { - return - this.register.uint64_0 == other.register.uint64_0 - && this.register.uint64_1 == other.register.uint64_1; - } - else if (typeof(T) == typeof(long)) - { - return - this.register.int64_0 == other.register.int64_0 - && this.register.int64_1 == other.register.int64_1; - } - else if (typeof(T) == typeof(float)) - { - return - this.register.single_0 == other.register.single_0 - && this.register.single_1 == other.register.single_1 - && this.register.single_2 == other.register.single_2 - && this.register.single_3 == other.register.single_3; - } - else if (typeof(T) == typeof(double)) - { - return - this.register.double_0 == other.register.double_0 - && this.register.double_1 == other.register.double_1; - } - else - { - throw new NotSupportedException(SR.Arg_TypeNotSupported); - } - } + return this == other; } /// @@ -1729,7 +1595,7 @@ public Vector(Span values) /// The one's complement vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector operator ~(Vector value) => - s_allOnes ^ value; + AllBitsSet ^ value; #endregion Bitwise Operators #region Logical Operators @@ -1741,8 +1607,133 @@ public Vector(Span values) /// True if all elements are equal; False otherwise. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Vector left, Vector right) => - left.Equals(right); + public static bool operator ==(Vector left, Vector right) + { + if (Vector.IsHardwareAccelerated) + { + for (int g = 0; g < Count; g++) + { + if (!ScalarEquals(left[g], right[g])) + { + return false; + } + } + return true; + } + else + { + if (typeof(T) == typeof(byte)) + { + return + left.register.byte_0 == right.register.byte_0 + && left.register.byte_1 == right.register.byte_1 + && left.register.byte_2 == right.register.byte_2 + && left.register.byte_3 == right.register.byte_3 + && left.register.byte_4 == right.register.byte_4 + && left.register.byte_5 == right.register.byte_5 + && left.register.byte_6 == right.register.byte_6 + && left.register.byte_7 == right.register.byte_7 + && left.register.byte_8 == right.register.byte_8 + && left.register.byte_9 == right.register.byte_9 + && left.register.byte_10 == right.register.byte_10 + && left.register.byte_11 == right.register.byte_11 + && left.register.byte_12 == right.register.byte_12 + && left.register.byte_13 == right.register.byte_13 + && left.register.byte_14 == right.register.byte_14 + && left.register.byte_15 == right.register.byte_15; + } + else if (typeof(T) == typeof(sbyte)) + { + return + left.register.sbyte_0 == right.register.sbyte_0 + && left.register.sbyte_1 == right.register.sbyte_1 + && left.register.sbyte_2 == right.register.sbyte_2 + && left.register.sbyte_3 == right.register.sbyte_3 + && left.register.sbyte_4 == right.register.sbyte_4 + && left.register.sbyte_5 == right.register.sbyte_5 + && left.register.sbyte_6 == right.register.sbyte_6 + && left.register.sbyte_7 == right.register.sbyte_7 + && left.register.sbyte_8 == right.register.sbyte_8 + && left.register.sbyte_9 == right.register.sbyte_9 + && left.register.sbyte_10 == right.register.sbyte_10 + && left.register.sbyte_11 == right.register.sbyte_11 + && left.register.sbyte_12 == right.register.sbyte_12 + && left.register.sbyte_13 == right.register.sbyte_13 + && left.register.sbyte_14 == right.register.sbyte_14 + && left.register.sbyte_15 == right.register.sbyte_15; + } + else if (typeof(T) == typeof(ushort)) + { + return + left.register.uint16_0 == right.register.uint16_0 + && left.register.uint16_1 == right.register.uint16_1 + && left.register.uint16_2 == right.register.uint16_2 + && left.register.uint16_3 == right.register.uint16_3 + && left.register.uint16_4 == right.register.uint16_4 + && left.register.uint16_5 == right.register.uint16_5 + && left.register.uint16_6 == right.register.uint16_6 + && left.register.uint16_7 == right.register.uint16_7; + } + else if (typeof(T) == typeof(short)) + { + return + left.register.int16_0 == right.register.int16_0 + && left.register.int16_1 == right.register.int16_1 + && left.register.int16_2 == right.register.int16_2 + && left.register.int16_3 == right.register.int16_3 + && left.register.int16_4 == right.register.int16_4 + && left.register.int16_5 == right.register.int16_5 + && left.register.int16_6 == right.register.int16_6 + && left.register.int16_7 == right.register.int16_7; + } + else if (typeof(T) == typeof(uint)) + { + return + left.register.uint32_0 == right.register.uint32_0 + && left.register.uint32_1 == right.register.uint32_1 + && left.register.uint32_2 == right.register.uint32_2 + && left.register.uint32_3 == right.register.uint32_3; + } + else if (typeof(T) == typeof(int)) + { + return + left.register.int32_0 == right.register.int32_0 + && left.register.int32_1 == right.register.int32_1 + && left.register.int32_2 == right.register.int32_2 + && left.register.int32_3 == right.register.int32_3; + } + else if (typeof(T) == typeof(ulong)) + { + return + left.register.uint64_0 == right.register.uint64_0 + && left.register.uint64_1 == right.register.uint64_1; + } + else if (typeof(T) == typeof(long)) + { + return + left.register.int64_0 == right.register.int64_0 + && left.register.int64_1 == right.register.int64_1; + } + else if (typeof(T) == typeof(float)) + { + return + left.register.single_0 == right.register.single_0 + && left.register.single_1 == right.register.single_1 + && left.register.single_2 == right.register.single_2 + && left.register.single_3 == right.register.single_3; + } + else if (typeof(T) == typeof(double)) + { + return + left.register.double_0 == right.register.double_0 + && left.register.double_1 == right.register.double_1; + } + else + { + throw new NotSupportedException(SR.Arg_TypeNotSupported); + } + } + } /// /// Returns a boolean indicating whether any single pair of elements in the given vectors are not equal. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.tt b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.tt index 3c02ba2bebac0..b556656e918c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.tt +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.tt @@ -15,13 +15,6 @@ using System.Text; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nint = System.Int64; -#else -using nint = System.Int32; -#endif - namespace System.Numerics { /* Note: The following patterns are used throughout the code here and are described here @@ -96,12 +89,12 @@ namespace System.Numerics } private static readonly Vector s_one = new Vector(GetOneValue()); - internal static Vector AllOnes + internal static Vector AllBitsSet { [Intrinsic] - get => s_allOnes; + get => s_allBitsSet; } - private static readonly Vector s_allOnes = new Vector(GetAllBitsSetValue()); + private static readonly Vector s_allBitsSet = new Vector(GetAllBitsSetValue()); #endregion Static Members #region Constructors @@ -329,11 +322,7 @@ namespace System.Numerics [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) { - if (!(obj is Vector)) - { - return false; - } - return Equals((Vector)obj); + return (obj is Vector other) && Equals(other); } /// @@ -344,56 +333,7 @@ namespace System.Numerics [Intrinsic] public readonly bool Equals(Vector other) { - if (Vector.IsHardwareAccelerated) - { - for (int g = 0; g < Count; g++) - { - if (!ScalarEquals(this[g], other[g])) - { - return false; - } - } - return true; - } - else - { -<# - foreach (Type type in supportedTypes) - { -#> - <#=GenerateIfStatementHeader(type)#> - { - return -<# - for (int g = 0; g < GetNumFields(type, totalSize); g++) - { -#> -<# - if (g == 0) - { -#> - this.<#=GetRegisterFieldName(type, g)#> == other.<#=GetRegisterFieldName(type, g)#> -<# - } - else - { -#> - && this.<#=GetRegisterFieldName(type, g)#> == other.<#=GetRegisterFieldName(type, g)#><#=(g == (GetNumFields(type, totalSize) -1)) ? ";" : ""#> -<# - } -#> -<# - } -#> - } -<# - } -#> - else - { - throw new NotSupportedException(SR.Arg_TypeNotSupported); - } - } + return this == other; } /// @@ -891,7 +831,7 @@ namespace System.Numerics /// The one's complement vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector operator ~(Vector value) => - s_allOnes ^ value; + AllBitsSet ^ value; #endregion Bitwise Operators #region Logical Operators @@ -903,8 +843,59 @@ namespace System.Numerics /// True if all elements are equal; False otherwise. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Vector left, Vector right) => - left.Equals(right); + public static bool operator ==(Vector left, Vector right) + { + if (Vector.IsHardwareAccelerated) + { + for (int g = 0; g < Count; g++) + { + if (!ScalarEquals(left[g], right[g])) + { + return false; + } + } + return true; + } + else + { +<# + foreach (Type type in supportedTypes) + { +#> + <#=GenerateIfStatementHeader(type)#> + { + return +<# + for (int g = 0; g < GetNumFields(type, totalSize); g++) + { +#> +<# + if (g == 0) + { +#> + left.<#=GetRegisterFieldName(type, g)#> == right.<#=GetRegisterFieldName(type, g)#> +<# + } + else + { +#> + && left.<#=GetRegisterFieldName(type, g)#> == right.<#=GetRegisterFieldName(type, g)#><#=(g == (GetNumFields(type, totalSize) -1)) ? ";" : ""#> +<# + } +#> +<# + } +#> + } +<# + } +#> + else + { + throw new NotSupportedException(SR.Arg_TypeNotSupported); + } + } + } /// /// Returns a boolean indicating whether any single pair of elements in the given vectors are not equal. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 38b572207d916..cee4a0e4ca66a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -65,9 +65,7 @@ public static Vector2 One [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) { - if (!(obj is Vector2)) - return false; - return Equals((Vector2)obj); + return (obj is Vector2 other) && Equals(other); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2_Intrinsics.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2_Intrinsics.cs index 27d3469bfb92c..b776c5d0a3cad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2_Intrinsics.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2_Intrinsics.cs @@ -91,7 +91,7 @@ public Vector2(float x, float y) [Intrinsic] public readonly bool Equals(Vector2 other) { - return this.X == other.X && this.Y == other.Y; + return this == other; } #endregion Public Instance Methods @@ -275,7 +275,8 @@ public static Vector2 SquareRoot(Vector2 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector2 left, Vector2 right) { - return left.Equals(right); + return left.X == right.X && + left.Y == right.Y; } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index af110ffcc56d5..1ca945caa5bf5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -70,9 +70,7 @@ public static Vector3 One [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) { - if (!(obj is Vector3)) - return false; - return Equals((Vector3)obj); + return (obj is Vector3 other) && Equals(other); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3_Intrinsics.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3_Intrinsics.cs index df32e8331d70c..3ff9a8aa6525a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3_Intrinsics.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3_Intrinsics.cs @@ -106,9 +106,7 @@ public Vector3(float x, float y, float z) [Intrinsic] public readonly bool Equals(Vector3 other) { - return X == other.X && - Y == other.Y && - Z == other.Z; + return this == other; } #endregion Public Instance Methods @@ -294,9 +292,9 @@ public static Vector3 SquareRoot(Vector3 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector3 left, Vector3 right) { - return (left.X == right.X && - left.Y == right.Y && - left.Z == right.Z); + return left.X == right.X && + left.Y == right.Y && + left.Z == right.Z; } /// @@ -309,9 +307,7 @@ public static Vector3 SquareRoot(Vector3 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(Vector3 left, Vector3 right) { - return (left.X != right.X || - left.Y != right.Y || - left.Z != right.Z); + return !(left == right); } #endregion Public Static Operators } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 45a9f42264b5e..c6dc6a8de8c4f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -73,9 +73,7 @@ public static Vector4 One [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) { - if (!(obj is Vector4)) - return false; - return Equals((Vector4)obj); + return (obj is Vector4 other) && Equals(other); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4_Intrinsics.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4_Intrinsics.cs index 70d692457e1a5..4e95120c244c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4_Intrinsics.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4_Intrinsics.cs @@ -136,10 +136,7 @@ public Vector4(Vector3 value, float w) [Intrinsic] public readonly bool Equals(Vector4 other) { - return this.X == other.X - && this.Y == other.Y - && this.Z == other.Z - && this.W == other.W; + return this == other; } #endregion Public Instance Methods @@ -329,7 +326,10 @@ public static Vector4 SquareRoot(Vector4 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector4 left, Vector4 right) { - return left.Equals(right); + return left.X == right.X + && left.Y == right.Y + && left.Z == right.Z + && left.W == right.W; } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_Operations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_Operations.cs index f16d1c4fc5777..4d97d1ad70caa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_Operations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_Operations.cs @@ -230,7 +230,7 @@ public static Vector LessThan(Vector left, Vector right) public static bool LessThanAll(Vector left, Vector right) where T : struct { Vector cond = (Vector)Vector.LessThan(left, right); - return cond.Equals(Vector.AllOnes); + return cond.Equals(Vector.AllBitsSet); } /// @@ -328,7 +328,7 @@ public static Vector LessThanOrEqual(Vector left, Vector r public static bool LessThanOrEqualAll(Vector left, Vector right) where T : struct { Vector cond = (Vector)Vector.LessThanOrEqual(left, right); - return cond.Equals(Vector.AllOnes); + return cond.Equals(Vector.AllBitsSet); } /// @@ -427,7 +427,7 @@ public static Vector GreaterThan(Vector left, Vector right) public static bool GreaterThanAll(Vector left, Vector right) where T : struct { Vector cond = (Vector)Vector.GreaterThan(left, right); - return cond.Equals(Vector.AllOnes); + return cond.Equals(Vector.AllBitsSet); } /// @@ -526,7 +526,7 @@ public static Vector GreaterThanOrEqual(Vector left, Vector(Vector left, Vector right) where T : struct { Vector cond = (Vector)Vector.GreaterThanOrEqual(left, right); - return cond.Equals(Vector.AllOnes); + return cond.Equals(Vector.AllBitsSet); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs index 77552dea34750..c66cd3b699a56 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs @@ -12,13 +12,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else // TARGET_64BIT -using nuint = System.UInt32; -#endif // TARGET_64BIT - namespace System { /// @@ -286,7 +279,7 @@ public unsafe ReadOnlySpan Span ThrowHelper.ThrowArgumentOutOfRangeException(); } #else - if ((uint)desiredStartIndex > (uint)lengthOfUnderlyingSpan || (uint)desiredLength > (uint)(lengthOfUnderlyingSpan - desiredStartIndex)) + if ((uint)desiredStartIndex > (uint)lengthOfUnderlyingSpan || (uint)desiredLength > (uint)lengthOfUnderlyingSpan - (uint)desiredStartIndex) { ThrowHelper.ThrowArgumentOutOfRangeException(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs index a765967f5f87a..7ce5284ad2d33 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @@ -13,13 +13,6 @@ #pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs index 09585f8d58f19..3ead4ce8e87f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs @@ -54,7 +54,7 @@ public static string ComputeDisplayName(string? name, Version? version, string? if (cultureName != null) { - if (cultureName == string.Empty) + if (cultureName.Length == 0) cultureName = "neutral"; sb.Append(", Culture="); sb.AppendQuoted(cultureName); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInfo.cs index 622ba56e44fe6..12412fe536eeb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInfo.cs @@ -26,6 +26,12 @@ public abstract partial class MethodInfo : MethodBase public virtual Delegate CreateDelegate(Type delegateType) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } public virtual Delegate CreateDelegate(Type delegateType, object? target) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); } + /// Creates a delegate of the given type 'T' from this method. + public T CreateDelegate() where T : Delegate => (T)CreateDelegate(typeof(T)); + + /// Creates a delegate of the given type 'T' with the specified target from this method. + public T CreateDelegate(object? target) where T : Delegate => (T)CreateDelegate(typeof(T), target); + public override bool Equals(object? obj) => base.Equals(obj); public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs index 4ab1ecf19efc8..8e3dbf95fcf30 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs @@ -2,11 +2,12 @@ // 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.IO; -using System.Globalization; -using System.Reflection; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Reflection; namespace System.Resources { @@ -120,7 +121,7 @@ internal class CultureNameResourceSetPair private Version? _satelliteContractVersion; private bool _lookedForSatelliteContractVersion; - private IResourceGroveler _resourceGroveler = null!; + private IResourceGroveler _resourceGroveler; public static readonly int MagicNumber = unchecked((int)0xBEEFCACE); // If only hex had a K... @@ -234,6 +235,7 @@ public ResourceManager(Type resourceSource) // Trying to unify code as much as possible, even though having to do a // security check in each constructor prevents it. + [MemberNotNull(nameof(_resourceGroveler))] private void CommonAssemblyInit() { #if FEATURE_APPX diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs index 78d70e7703c64..bf5edf4774c9e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs @@ -105,7 +105,7 @@ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox b } else if (obj != null) { - Unsafe.As(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token, + Unsafe.As(obj).OnCompleted(ThreadPool.s_invokeAsyncStateMachineBox, box, _value._token, _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None); } else @@ -210,7 +210,7 @@ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox b } else if (obj != null) { - Unsafe.As>(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token, + Unsafe.As>(obj).OnCompleted(ThreadPool.s_invokeAsyncStateMachineBox, box, _value._token, _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None); } else diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs index 07f9441518584..ca7a0a0ca742e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs @@ -95,7 +95,7 @@ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox b } else if (obj != null) { - Unsafe.As(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext); + Unsafe.As(obj).OnCompleted(ThreadPool.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext); } else { @@ -177,7 +177,7 @@ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox b } else if (obj != null) { - Unsafe.As>(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext); + Unsafe.As>(obj).OnCompleted(ThreadPool.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext); } else { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs index 2413cacd01d02..736259d2334f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs @@ -4,13 +4,6 @@ using System.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System.Runtime.InteropServices { public struct ArrayWithOffset diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs index b7bd0361d53cc..c163c364771d4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs @@ -7,13 +7,6 @@ using System.Threading; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nint = System.Int64; -#else -using nint = System.Int32; -#endif - namespace System.Runtime.InteropServices { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs index 227e84e71c2fa..76aab4ab2c4b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs @@ -10,13 +10,6 @@ using Internal.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System.Runtime.InteropServices { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs index 9bae02e39f7ee..080c7b1f5d1fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs @@ -640,6 +640,42 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector128 Divide(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + /// + /// float64x2_t vdupq_laneq_f64 (float64x2_t vec, const int lane) + /// A64: DUP Vd.2D, Vn.D[index] + /// + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vdupq_laneq_s64 (int64x2_t vec, const int lane) + /// A64: DUP Vd.2D, Vn.D[index] + /// + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vdupq_laneq_u64 (uint64x2_t vec, const int lane) + /// A64: DUP Vd.2D, Vn.D[index] + /// + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// float64x2_t vdupq_n_f64 (float64_t value) + /// A64: DUP Vd.2D, Vn.D[0] + /// + public static Vector128 DuplicateToVector128(double value) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vdupq_n_s64 (int64_t value) + /// A64: DUP Vd.2D, Rn + /// + public static Vector128 DuplicateToVector128(long value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vdupq_n_s64 (uint64_t value) + /// A64: DUP Vd.2D, Rn + /// + public static Vector128 DuplicateToVector128(ulong value) { throw new PlatformNotSupportedException(); } + /// /// float64x2_t vfmaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) /// A64: FMLA Vd.2D, Vn.2D, Vm.2D @@ -1164,6 +1200,312 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector64 ReciprocalStepScalar(Vector64 left, Vector64 right) { throw new PlatformNotSupportedException(); } + /// + /// int16_t vqrshlh_s16 (int16_t a, int16_t b) + /// A64: SQRSHL Hd, Hn, Hm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t vqrshls_s32 (int32_t a, int32_t b) + /// A64: SQRSHL Sd, Sn, Sm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t vqrshlb_s8 (int8_t a, int8_t b) + /// A64: SQRSHL Bd, Bn, Bm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t vqshlh_s16 (int16_t a, int16_t b) + /// A64: SQSHL Hd, Hn, Hm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t vqshls_s32 (int32_t a, int32_t b) + /// A64: SQSHL Sd, Sn, Sm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t vqshlb_s8 (int8_t a, int8_t b) + /// A64: SQSHL Bd, Bn, Bm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshlb_n_u8 (uint8_t a, const int n) + /// A64: UQSHL Bd, Bn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t vqshlh_n_s16 (int16_t a, const int n) + /// A64: SQSHL Hd, Hn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t vqshls_n_s32 (int32_t a, const int n) + /// A64: SQSHL Sd, Sn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t vqshlb_n_s8 (int8_t a, const int n) + /// A64: SQSHL Bd, Bn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshlh_n_u16 (uint16_t a, const int n) + /// A64: UQSHL Hd, Hn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshls_n_u32 (uint32_t a, const int n) + /// A64: UQSHL Sd, Sn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshluh_n_s16 (int16_t a, const int n) + /// A64: SQSHLU Hd, Hn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshlus_n_s32 (int32_t a, const int n) + /// A64: SQSHLU Sd, Sn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshlub_n_s8 (int8_t a, const int n) + /// A64: SQSHLU Bd, Bn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqrshlb_u8 (uint8_t a, int8_t b) + /// A64: UQRSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqrshlh_u16 (uint16_t a, int16_t b) + /// A64: UQRSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqrshls_u32 (uint32_t a, int32_t b) + /// A64: UQRSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqrshlb_u8 (uint8_t a, int8_t b) + /// A64: UQRSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqrshlh_u16 (uint16_t a, int16_t b) + /// A64: UQRSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqrshls_u32 (uint32_t a, int32_t b) + /// A64: UQRSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshlb_u8 (uint8_t a, int8_t b) + /// A64: UQSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshlh_u16 (uint16_t a, int16_t b) + /// A64: UQSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshls_u32 (uint32_t a, int32_t b) + /// A64: UQSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshlb_u8 (uint8_t a, int8_t b) + /// A64: UQSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshlh_u16 (uint16_t a, int16_t b) + /// A64: UQSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshls_u32 (uint32_t a, int32_t b) + /// A64: UQSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t vqshrns_n_s32 (int32_t a, const int n) + /// A64: SQSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t vqshrnd_n_s64 (int64_t a, const int n) + /// A64: SQSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t vqshrnh_n_s16 (int16_t a, const int n) + /// A64: SQSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshrunh_n_s16 (int16_t a, const int n) + /// A64: SQSHRUN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshruns_n_s32 (int32_t a, const int n) + /// A64: SQSHRUN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshrund_n_s64 (int64_t a, const int n) + /// A64: SQSHRUN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t vqrshrns_n_s32 (int32_t a, const int n) + /// A64: SQRSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t vqrshrnd_n_s64 (int64_t a, const int n) + /// A64: SQRSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t vqrshrnh_n_s16 (int16_t a, const int n) + /// A64: SQRSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqrshrunh_n_s16 (int16_t a, const int n) + /// A64: SQRSHRUN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqrshruns_n_s32 (int32_t a, const int n) + /// A64: SQRSHRUN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqrshrund_n_s64 (int64_t a, const int n) + /// A64: SQRSHRUN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshrns_n_u32 (uint32_t a, const int n) + /// A64: UQSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqshrns_n_u32 (uint32_t a, const int n) + /// A64: UQSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqrshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQRSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqrshrns_n_u32 (uint32_t a, const int n) + /// A64: UQRSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqrshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQRSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8_t vqrshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQRSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t vqrshrns_n_u32 (uint32_t a, const int n) + /// A64: UQRSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t vqrshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQRSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + /// /// float32x2_t vsqrt_f32 (float32x2_t a) /// A64: FSQRT Vd.2S, Vn.2S @@ -2474,6 +2816,90 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector128 Add(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + /// + /// uint8x8_t vaddhn_u16 (uint16x8_t a, uint16x8_t b) + /// A32: VADDHN.I16 Dd, Qn, Qm + /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vaddhn_s32 (int32x4_t a, int32x4_t b) + /// A32: VADDHN.I32 Dd, Qn, Qm + /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vaddhn_s64 (int64x2_t a, int64x2_t b) + /// A32: VADDHN.I64 Dd, Qn, Qm + /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vaddhn_s16 (int16x8_t a, int16x8_t b) + /// A32: VADDHN.I16 Dd, Qn, Qm + /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vaddhn_u32 (uint32x4_t a, uint32x4_t b) + /// A32: VADDHN.I32 Dd, Qn, Qm + /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vaddhn_u64 (uint64x2_t a, uint64x2_t b) + /// A32: VADDHN.I64 Dd, Qn, Qm + /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vaddhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) + /// A32: VADDHN.I16 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.16B, Vn.8H, Vm.8H + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vaddhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) + /// A32: VADDHN.I32 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.8H, Vn.4S, Vm.4S + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vaddhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) + /// A32: VADDHN.I64 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.4S, Vn.2D, Vm.2D + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vaddhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) + /// A32: VADDHN.I16 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.16B, Vn.8H, Vm.8H + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vaddhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) + /// A32: VADDHN.I32 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.8H, Vn.4S, Vm.4S + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vaddhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) + /// A32: VADDHN.I64 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.4S, Vn.2D, Vm.2D + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + /// /// uint8x8_t vpadd_u8 (uint8x8_t a, uint8x8_t b) /// A32: VPADD.I8 Dd, Dn, Dm @@ -2692,172 +3118,88 @@ public new abstract class Arm64 : ArmBase.Arm64 public static Vector64 AddPairwiseWideningScalar(Vector64 value) { throw new PlatformNotSupportedException(); } /// - /// uint8x8_t vaddhn_u16 (uint16x8_t a, uint16x8_t b) - /// A32: VADDHN.I16 Dd, Qn, Qm - /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H + /// uint8x8_t vraddhn_u16 (uint16x8_t a, uint16x8_t b) + /// A32: VRADDHN.I16 Dd, Qn, Qm + /// A64: RADDHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// - /// int16x4_t vaddhn_s32 (int32x4_t a, int32x4_t b) - /// A32: VADDHN.I32 Dd, Qn, Qm - /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S + /// int16x4_t vraddhn_s32 (int32x4_t a, int32x4_t b) + /// A32: VRADDHN.I32 Dd, Qn, Qm + /// A64: RADDHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// - /// int32x2_t vaddhn_s64 (int64x2_t a, int64x2_t b) - /// A32: VADDHN.I64 Dd, Qn, Qm - /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D + /// int32x2_t vraddhn_s64 (int64x2_t a, int64x2_t b) + /// A32: VRADDHN.I64 Dd, Qn, Qm + /// A64: RADDHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// int8x8_t vaddhn_s16 (int16x8_t a, int16x8_t b) - /// A32: VADDHN.I16 Dd, Qn, Qm - /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H - /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// uint16x4_t vaddhn_u32 (uint32x4_t a, uint32x4_t b) - /// A32: VADDHN.I32 Dd, Qn, Qm - /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S - /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// uint32x2_t vaddhn_u64 (uint64x2_t a, uint64x2_t b) - /// A32: VADDHN.I64 Dd, Qn, Qm - /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D - /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// uint8x16_t vaddhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) - /// A32: VADDHN.I16 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.16B, Vn.8B, Vm.8H - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// int16x8_t vaddhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) - /// A32: VADDHN.I32 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.8H, Vn.4H, Vm.4S - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// int32x4_t vaddhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) - /// A32: VADDHN.I64 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.4S, Vn.2S, Vm.2D - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// int8x16_t vaddhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) - /// A32: VADDHN.I16 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.16B, Vn.8B, Vm.8H - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// uint16x8_t vaddhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) - /// A32: VADDHN.I32 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.8H, Vn.4H, Vm.4S - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// uint32x4_t vaddhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) - /// A32: VADDHN.I64 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.4S, Vn.2S, Vm.2D - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// uint8x8_t vraddhn_u16 (uint16x8_t a, uint16x8_t b) - /// A32: VRADDHN.I16 Dd, Qn, Qm - /// A64: RADDHN Vd.8B, Vn.8H, Vm.8H - /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// int16x4_t vraddhn_s32 (int32x4_t a, int32x4_t b) - /// A32: VRADDHN.I32 Dd, Qn, Qm - /// A64: RADDHN Vd.4H, Vn.4S, Vm.4S - /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } - - /// - /// int32x2_t vraddhn_s64 (int64x2_t a, int64x2_t b) - /// A32: VRADDHN.I64 Dd, Qn, Qm - /// A64: RADDHN Vd.2S, Vn.2D, Vm.2D - /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int8x8_t vraddhn_s16 (int16x8_t a, int16x8_t b) /// A32: VRADDHN.I16 Dd, Qn, Qm /// A64: RADDHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint16x4_t vraddhn_u32 (uint32x4_t a, uint32x4_t b) /// A32: VRADDHN.I32 Dd, Qn, Qm /// A64: RADDHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint32x2_t vraddhn_u64 (uint64x2_t a, uint64x2_t b) /// A32: VRADDHN.I64 Dd, Qn, Qm /// A64: RADDHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint8x16_t vraddhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) /// A32: VRADDHN.I16 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RADDHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int16x8_t vraddhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) /// A32: VRADDHN.I32 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RADDHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int32x4_t vraddhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) /// A32: VRADDHN.I64 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RADDHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int8x16_t vraddhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) /// A32: VRADDHN.I16 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RADDHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint16x8_t vraddhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) /// A32: VRADDHN.I32 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RADDHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint32x4_t vraddhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) /// A32: VRADDHN.I64 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RADDHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint8x8_t vqadd_u8 (uint8x8_t a, uint8x8_t b) @@ -4201,6 +4543,300 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector64 DivideScalar(Vector64 left, Vector64 right) { throw new PlatformNotSupportedException(); } + /// + /// uint8x8_t vdup_lane_u8 (uint8x8_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vdup_lane_s16 (int16x4_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vdup_lane_s32 (int32x2_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// float32x2_t vdup_lane_f32 (float32x2_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vdup_lane_s8 (int8x8_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vdup_lane_u16 (uint16x4_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vdup_lane_u32 (uint32x2_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vdup_laneq_u8 (uint8x16_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vdup_laneq_s16 (int16x8_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vdup_laneq_s32 (int32x4_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// float32x2_t vdup_laneq_f32 (float32x4_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vdup_laneq_s8 (int8x16_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vdup_laneq_u16 (uint16x8_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vdup_laneq_u32 (uint32x4_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vdupq_lane_u8 (uint8x8_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vdupq_lane_s16 (int16x4_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vdupq_lane_s32 (int32x2_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// float32x4_t vdupq_lane_f32 (float32x2_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vdupq_lane_s8 (int8x8_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vdupq_lane_u16 (uint16x4_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vdupq_lane_u32 (uint32x2_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vdupq_lane_u8 (uint8x16_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vdupq_lane_s16 (int16x8_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vdupq_lane_s32 (int32x4_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// float32x4_t vdupq_lane_f32 (float32x4_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vdupq_lane_s8 (int8x16_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vdupq_lane_u16 (uint16x8_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vdupq_lane_u32 (uint32x4_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vdup_n_u8 (uint8_t value) + /// A32: VDUP.8 Dd, Rt + /// A64: DUP Vd.8B, Rn + /// + public static Vector64 DuplicateToVector64(byte value) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vdup_n_s16 (int16_t value) + /// A32: VDUP.16 Dd, Rt + /// A64: DUP Vd.4H, Rn + /// + public static Vector64 DuplicateToVector64(short value) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vdup_n_s32 (int32_t value) + /// A32: VDUP.32 Dd, Rt + /// A64: DUP Vd.2S, Rn + /// + public static Vector64 DuplicateToVector64(int value) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vdup_n_s8 (int8_t value) + /// A32: VDUP.8 Dd, Rt + /// A64: DUP Vd.8B, Rn + /// + public static Vector64 DuplicateToVector64(sbyte value) { throw new PlatformNotSupportedException(); } + + /// + /// float32x2_t vdup_n_f32 (float32_t value) + /// A32: VDUP Dd, Dm[0] + /// A64: DUP Vd.2S, Vn.S[0] + /// + public static Vector64 DuplicateToVector64(float value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vdup_n_u16 (uint16_t value) + /// A32: VDUP.16 Dd, Rt + /// A64: DUP Vd.4H, Rn + /// + public static Vector64 DuplicateToVector64(ushort value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vdup_n_u32 (uint32_t value) + /// A32: VDUP.32 Dd, Rt + /// A64: DUP Vd.2S, Rn + /// + public static Vector64 DuplicateToVector64(uint value) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vdupq_n_u8 (uint8_t value) + /// A32: VDUP.8 Qd, Rt + /// A64: DUP Vd.16B, Rn + /// + public static Vector128 DuplicateToVector128(byte value) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vdupq_n_s16 (int16_t value) + /// A32: VDUP.16 Qd, Rt + /// A64: DUP Vd.8H, Rn + /// + public static Vector128 DuplicateToVector128(short value) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vdupq_n_s32 (int32_t value) + /// A32: VDUP.32 Qd, Rt + /// A64: DUP Vd.4S, Rn + /// + public static Vector128 DuplicateToVector128(int value) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vdupq_n_s8 (int8_t value) + /// A32: VDUP.8 Qd, Rt + /// A64: DUP Vd.16B, Rn + /// + public static Vector128 DuplicateToVector128(sbyte value) { throw new PlatformNotSupportedException(); } + + /// + /// float32x4_t vdupq_n_f32 (float32_t value) + /// A32: VDUP Qd, Dm[0] + /// A64: DUP Vd.4S, Vn.S[0] + /// + public static Vector128 DuplicateToVector128(float value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vdupq_n_u16 (uint16_t value) + /// A32: VDUP.16 Qd, Rt + /// A64: DUP Vd.8H, Rn + /// + public static Vector128 DuplicateToVector128(ushort value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vdupq_n_u32 (uint32_t value) + /// A32: VDUP.32 Qd, Rt + /// A64: DUP Vd.4S, Rn + /// + public static Vector128 DuplicateToVector128(uint value) { throw new PlatformNotSupportedException(); } + /// /// uint8_t vget_lane_u8 (uint8x8_t v, const int lane) /// A32: VMOV.U8 Rt, Dn[lane] @@ -4325,84 +4961,84 @@ public new abstract class Arm64 : ArmBase.Arm64 /// A32: VMOVN.I16 Dd+1, Qm /// A64: XTN2 Vd.16B, Vn.8H /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } /// /// int16x8_t vmovn_high_s32 (int16x4_t r, int32x4_t a) /// A32: VMOVN.I32 Dd+1, Qm /// A64: XTN2 Vd.8H, Vn.4S /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } /// /// int32x4_t vmovn_high_s64 (int32x2_t r, int64x2_t a) /// A32: VMOVN.I64 Dd+1, Qm /// A64: XTN2 Vd.4S, Vn.2D /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint8x16_t vmovn_high_u16 (uint8x8_t r, uint16x8_t a) /// A32: VMOVN.I16 Dd+1, Qm /// A64: XTN2 Vd.16B, Vn.8H /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint16x8_t vmovn_high_u32 (uint16x4_t r, uint32x4_t a) /// A32: VMOVN.I32 Dd+1, Qm /// A64: XTN2 Vd.8H, Vn.4S /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint32x4_t vmovn_high_u64 (uint32x2_t r, uint64x2_t a) /// A32: VMOVN.I64 Dd+1, Qm /// A64: XTN2 Vd.4S, Vn.2D /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) { throw new PlatformNotSupportedException(); } /// /// int8x8_t vmovn_s16 (int16x8_t a) /// A32: VMOVN.I16 Dd, Qm /// A64: XTN Vd.8B, Vn.8H /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ExtractNarrowingLower(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// int16x4_t vmovn_s32 (int32x4_t a) /// A32: VMOVN.I32 Dd, Qm /// A64: XTN Vd.4H, Vn.4S /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ExtractNarrowingLower(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// int32x2_t vmovn_s64 (int64x2_t a) /// A32: VMOVN.I64 Dd, Qm /// A64: XTN Vd.2S, Vn.2D /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ExtractNarrowingLower(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint8x8_t vmovn_u16 (uint16x8_t a) /// A32: VMOVN.I16 Dd, Qm /// A64: XTN Vd.8B, Vn.8H /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ExtractNarrowingLower(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint16x4_t vmovn_u32 (uint32x4_t a) /// A32: VMOVN.I32 Dd, Qm /// A64: XTN Vd.4H, Vn.4S /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ExtractNarrowingLower(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint32x2_t vmovn_u64 (uint64x2_t a) /// A32: VMOVN.I64 Dd, Qm /// A64: XTN Vd.2S, Vn.2D /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ExtractNarrowingLower(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// uint8x8_t vext_s8 (uint8x8_t a, uint8x8_t b, const int n) @@ -6664,6 +7300,34 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector128 PolynomialMultiply(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + /// + /// poly16x8_t vmull_p8 (poly8x8_t a, poly8x8_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.16B, Vn.8B, Vm.8B + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) { throw new PlatformNotSupportedException(); } + + /// + /// poly16x8_t vmull_p8 (poly8x8_t a, poly8x8_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.16B, Vn.8B, Vm.8B + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) { throw new PlatformNotSupportedException(); } + + /// + /// poly16x8_t vmull_high_p8 (poly8x16_t a, poly8x16_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// poly16x8_t vmull_high_p8 (poly8x16_t a, poly8x16_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + /// /// uint8x8_t vcnt_u8 (uint8x8_t a) /// A32: VCNT.I8 Dd, Dm @@ -6777,96 +7441,2343 @@ public new abstract class Arm64 : ArmBase.Arm64 public static Vector128 ReciprocalStep(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// - /// float64x1_t vsqrt_f64 (float64x1_t a) - /// A32: VSQRT.F64 Dd, Dm - /// A64: FSQRT Dd, Dn + /// int16x4_t vshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VSHL.S16 Dd, Dn, Dm + /// A64: SSHL Vd.4H, Vn.4H, Vm.4H /// - public static Vector64 SqrtScalar(Vector64 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ShiftArithmetic(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } /// - /// float32_t vsqrts_f32 (float32_t a) - /// A32: VSQRT.F32 Sd, Sm - /// A64: FSQRT Sd, Sn - /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs. + /// int32x2_t vshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VSHL.S32 Dd, Dn, Dm + /// A64: SSHL Vd.2S, Vn.2S, Vm.2S /// - public static Vector64 SqrtScalar(Vector64 value) { throw new PlatformNotSupportedException(); } + public static Vector64 ShiftArithmetic(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_u8 (uint8_t * ptr, uint8x8_t val) - /// A32: VST1.8 { Dd }, [Rn] - /// A64: ST1 { Vt.8B }, [Xn] + /// int8x8_t vshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VSHL.S8 Dd, Dn, Dm + /// A64: SSHL Vd.8B, Vn.8B, Vm.8B /// - public static unsafe void Store(byte* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector64 ShiftArithmetic(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_f64 (float64_t * ptr, float64x1_t val) - /// A32: VST1.64 { Dd }, [Rn] - /// A64: ST1 { Vt.1D }, [Xn] + /// int16x8_t vshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VSHL.S16 Qd, Qn, Qm + /// A64: SSHL Vd.8H, Vn.8H, Vm.8H /// - public static unsafe void Store(double* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_s16 (int16_t * ptr, int16x4_t val) - /// A32: VST1.16 { Dd }, [Rn] - /// A64: ST1 {Vt.4H }, [Xn] + /// int32x4_t vshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VSHL.S32 Qd, Qn, Qm + /// A64: SSHL Vd.4S, Vn.4S, Vm.4S /// - public static unsafe void Store(short* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_s32 (int32_t * ptr, int32x2_t val) - /// A32: VST1.32 { Dd }, [Rn] - /// A64: ST1 { Vt.2S }, [Xn] + /// int64x2_t vshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VSHL.S64 Qd, Qn, Qm + /// A64: SSHL Vd.2D, Vn.2D, Vm.2D /// - public static unsafe void Store(int* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_s64 (int64_t * ptr, int64x1_t val) - /// A32: VST1.64 { Dd }, [Rn] - /// A64: ST1 { Vt.1D }, [Xn] + /// int8x16_t vshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VSHL.S8 Qd, Qn, Qm + /// A64: SSHL Vd.16B, Vn.16B, Vm.16B /// - public static unsafe void Store(long* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_s8 (int8_t * ptr, int8x8_t val) - /// A32: VST1.8 { Dd }, [Rn] - /// A64: ST1 { Vt.8B }, [Xn] + /// int16x4_t vrshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VRSHL.S16 Dd, Dn, Dm + /// A64: SRSHL Vd.4H, Vn.4H, Vm.4H /// - public static unsafe void Store(sbyte* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector64 ShiftArithmeticRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_f32 (float32_t * ptr, float32x2_t val) - /// A32: VST1.32 { Dd }, [Rn] - /// A64: ST1 { Vt.2S }, [Xn] + /// int32x2_t vrshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VRSHL.S32 Dd, Dn, Dm + /// A64: SRSHL Vd.2S, Vn.2S, Vm.2S /// - public static unsafe void Store(float* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector64 ShiftArithmeticRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_u16 (uint16_t * ptr, uint16x4_t val) - /// A32: VST1.16 { Dd }, [Rn] - /// A64: ST1 { Vt.4H }, [Xn] + /// int8x8_t vrshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VRSHL.S8 Dd, Dn, Dm + /// A64: SRSHL Vd.8B, Vn.8B, Vm.8B /// - public static unsafe void Store(ushort* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector64 ShiftArithmeticRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_u32 (uint32_t * ptr, uint32x2_t val) - /// A32: VST1.32 { Dd }, [Rn] - /// A64: ST1 { Vt.2S }, [Xn] + /// int16x8_t vrshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VRSHL.S16 Qd, Qn, Qm + /// A64: SRSHL Vd.8H, Vn.8H, Vm.8H /// - public static unsafe void Store(uint* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1_u64 (uint64_t * ptr, uint64x1_t val) - /// A32: VST1.64 { Dd }, [Rn] - /// A64: ST1 { Vt.1D }, [Xn] + /// int32x4_t vrshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VRSHL.S32 Qd, Qn, Qm + /// A64: SRSHL Vd.4S, Vn.4S, Vm.4S /// - public static unsafe void Store(ulong* address, Vector64 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } /// - /// void vst1q_u8 (uint8_t * ptr, uint8x16_t val) - /// A32: VST1.8 { Dd, Dd+1 }, [Rn] - /// A64: ST1 { Vt.16B }, [Xn] + /// int64x2_t vrshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VRSHL.S64 Qd, Qn, Qm + /// A64: SRSHL Vd.2D, Vn.2D, Vm.2D /// - public static unsafe void Store(byte* address, Vector128 source) { throw new PlatformNotSupportedException(); } + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vrshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VRSHL.S8 Qd, Qn, Qm + /// A64: SRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vqrshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VQRSHL.S16 Dd, Dn, Dm + /// A64: SQRSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftArithmeticRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vqrshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VQRSHL.S32 Dd, Dn, Dm + /// A64: SQRSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftArithmeticRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vqrshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VQRSHL.S8 Dd, Dn, Dm + /// A64: SQRSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftArithmeticRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vqrshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VQRSHL.S16 Qd, Qn, Qm + /// A64: SQRSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vqrshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VQRSHL.S32 Qd, Qn, Qm + /// A64: SQRSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vqrshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VQRSHL.S64 Qd, Qn, Qm + /// A64: SQRSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vqrshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VQRSHL.S8 Qd, Qn, Qm + /// A64: SQRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vqrshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VQRSHL.S64 Dd, Dn, Dm + /// A64: SQRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vrshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VRSHL.S64 Dd, Dn, Dm + /// A64: SRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticRoundedScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vqshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VQSHL.S16 Dd, Dn, Dm + /// A64: SQSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftArithmeticSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vqshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VQSHL.S32 Dd, Dn, Dm + /// A64: SQSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftArithmeticSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vqshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VQSHL.S8 Dd, Dn, Dm + /// A64: SQSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftArithmeticSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vqshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VQSHL.S16 Qd, Qn, Qm + /// A64: SQSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vqshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VQSHL.S32 Qd, Qn, Qm + /// A64: SQSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vqshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VQSHL.S64 Qd, Qn, Qm + /// A64: SQSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vqshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VQSHL.S8 Qd, Qn, Qm + /// A64: SQSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vqshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VQSHL.S64 Dd, Dn, Dm + /// A64: SQSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VSHL.S64 Dd, Dn, Dm + /// A64: SSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vshl_n_u8 (uint8x8_t a, const int n) + /// A32: VSHL.I8 Dd, Dm, #n + /// A64: SHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vshl_n_s16 (int16x4_t a, const int n) + /// A32: VSHL.I16 Dd, Dm, #n + /// A64: SHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vshl_n_s32 (int32x2_t a, const int n) + /// A32: VSHL.I32 Dd, Dm, #n + /// A64: SHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vshl_n_s8 (int8x8_t a, const int n) + /// A32: VSHL.I8 Dd, Dm, #n + /// A64: SHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vshl_n_u16 (uint16x4_t a, const int n) + /// A32: VSHL.I16 Dd, Dm, #n + /// A64: SHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vshl_n_u32 (uint32x2_t a, const int n) + /// A32: VSHL.I32 Dd, Dm, #n + /// A64: SHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vshlq_n_u8 (uint8x16_t a, const int n) + /// A32: VSHL.I8 Qd, Qm, #n + /// A64: SHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vshlq_n_s16 (int16x8_t a, const int n) + /// A32: VSHL.I16 Qd, Qm, #n + /// A64: SHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vshlq_n_s64 (int64x2_t a, const int n) + /// A32: VSHL.I64 Qd, Qm, #n + /// A64: SHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vshlq_n_s8 (int8x16_t a, const int n) + /// A32: VSHL.I8 Qd, Qm, #n + /// A64: SHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshlq_n_u16 (uint16x8_t a, const int n) + /// A32: VSHL.I16 Qd, Qm, #n + /// A64: SHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshlq_n_u32 (uint32x4_t a, const int n) + /// A32: VSHL.I32 Qd, Qm, #n + /// A64: SHL Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshlq_n_u64 (uint64x2_t a, const int n) + /// A32: VSHL.I64 Qd, Qm, #n + /// A64: SHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshl_n_u8 (uint8x8_t a, const int n) + /// A32: VQSHL.U8 Dd, Dm, #n + /// A64: UQSHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vqshl_n_s16 (int16x4_t a, const int n) + /// A32: VQSHL.S16 Dd, Dm, #n + /// A64: SQSHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vqshl_n_s32 (int32x2_t a, const int n) + /// A32: VQSHL.S32 Dd, Dm, #n + /// A64: SQSHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vqshl_n_s8 (int8x8_t a, const int n) + /// A32: VQSHL.S8 Dd, Dm, #n + /// A64: SQSHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshl_n_u16 (uint16x4_t a, const int n) + /// A32: VQSHL.U16 Dd, Dm, #n + /// A64: UQSHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshl_n_u32 (uint32x2_t a, const int n) + /// A32: VQSHL.U32 Dd, Dm, #n + /// A64: UQSHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshlq_n_u8 (uint8x16_t a, const int n) + /// A32: VQSHL.U8 Qd, Qm, #n + /// A64: UQSHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vqshlq_n_s16 (int16x8_t a, const int n) + /// A32: VQSHL.S16 Qd, Qm, #n + /// A64: SQSHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vqshlq_n_s32 (int32x4_t a, const int n) + /// A32: VQSHL.S32 Qd, Qm, #n + /// A64: SQSHL Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vqshlq_n_s64 (int64x2_t a, const int n) + /// A32: VQSHL.S64 Qd, Qm, #n + /// A64: SQSHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vqshlq_n_s8 (int8x16_t a, const int n) + /// A32: VQSHL.S8 Qd, Qm, #n + /// A64: SQSHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshlq_n_u16 (uint16x8_t a, const int n) + /// A32: VQSHL.U16 Qd, Qm, #n + /// A64: UQSHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshlq_n_u32 (uint32x4_t a, const int n) + /// A32: VQSHL.U32 Qd, Qm, #n + /// A64: UQSHL Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vqshlq_n_u64 (uint64x2_t a, const int n) + /// A32: VQSHL.U64 Qd, Qm, #n + /// A64: UQSHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vqshl_n_s64 (int64x1_t a, const int n) + /// A32: VQSHL.S64 Dd, Dm, #n + /// A64: SQSHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vqshl_n_u64 (uint64x1_t a, const int n) + /// A32: VQSHL.U64 Dd, Dm, #n + /// A64: UQSHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshlu_n_s16 (int16x4_t a, const int n) + /// A32: VQSHLU.S16 Dd, Dm, #n + /// A64: SQSHLU Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsigned(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshlu_n_s32 (int32x2_t a, const int n) + /// A32: VQSHLU.S32 Dd, Dm, #n + /// A64: SQSHLU Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsigned(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshlu_n_s8 (int8x8_t a, const int n) + /// A32: VQSHLU.S8 Dd, Dm, #n + /// A64: SQSHLU Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsigned(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshluq_n_s16 (int16x8_t a, const int n) + /// A32: VQSHLU.S16 Qd, Qm, #n + /// A64: SQSHLU Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshluq_n_s32 (int32x4_t a, const int n) + /// A32: VQSHLU.S32 Qd, Qm, #n + /// A64: SQSHLU Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vqshluq_n_s64 (int64x2_t a, const int n) + /// A32: VQSHLU.S64 Qd, Qm, #n + /// A64: SQSHLU Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshluq_n_s8 (int8x16_t a, const int n) + /// A32: VQSHLU.S8 Qd, Qm, #n + /// A64: SQSHLU Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vqshlu_n_s64 (int64x1_t a, const int n) + /// A32: VQSHLU.S64 Dd, Dm, #n + /// A64: SQSHLU Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vshl_n_s64 (int64x1_t a, const int n) + /// A32: VSHL.I64 Dd, Dm, #n + /// A64: SHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vshl_n_u64 (uint64x1_t a, const int n) + /// A32: VSHL.I64 Dd, Dm, #n + /// A64: SHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshll_n_u8 (uint8x8_t a, const int n) + /// A32: VSHLL.U8 Qd, Dm, #n + /// A64: USHLL Vd.8H, Vn.8B, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vshll_n_s16 (int16x4_t a, const int n) + /// A32: VSHLL.S16 Qd, Dm, #n + /// A64: SSHLL Vd.4S, Vn.4H, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vshll_n_s32 (int32x2_t a, const int n) + /// A32: VSHLL.S32 Qd, Dm, #n + /// A64: SSHLL Vd.2D, Vn.2S, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vshll_n_s8 (int8x8_t a, const int n) + /// A32: VSHLL.S8 Qd, Dm, #n + /// A64: SSHLL Vd.8H, Vn.8B, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshll_n_u16 (uint16x4_t a, const int n) + /// A32: VSHLL.U16 Qd, Dm, #n + /// A64: USHLL Vd.4S, Vn.4H, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshll_n_u32 (uint32x2_t a, const int n) + /// A32: VSHLL.U32 Qd, Dm, #n + /// A64: USHLL Vd.2D, Vn.2S, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshll_high_n_u8 (uint8x16_t a, const int n) + /// A32: VSHLL.U8 Qd, Dm+1, #n + /// A64: USHLL2 Vd.8H, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vshll_high_n_s16 (int16x8_t a, const int n) + /// A32: VSHLL.S16 Qd, Dm+1, #n + /// A64: SSHLL2 Vd.4S, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vshll_high_n_s32 (int32x4_t a, const int n) + /// A32: VSHLL.S32 Qd, Dm+1, #n + /// A64: SSHLL2 Vd.2D, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vshll_high_n_s8 (int8x16_t a, const int n) + /// A32: VSHLL.S8 Qd, Dm+1, #n + /// A64: SSHLL2 Vd.8H, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshll_high_n_u16 (uint16x8_t a, const int n) + /// A32: VSHLL.U16 Qd, Dm+1, #n + /// A64: USHLL2 Vd.4S, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshll_high_n_u32 (uint32x4_t a, const int n) + /// A32: VSHLL.U32 Qd, Dm+1, #n + /// A64: USHLL2 Vd.2D, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VSHL.U8 Dd, Dn, Dm + /// A64: USHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VSHL.U16 Dd, Dn, Dm + /// A64: USHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VSHL.U32 Dd, Dn, Dm + /// A64: USHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VSHL.U8 Dd, Dn, Dm + /// A64: USHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VSHL.U16 Dd, Dn, Dm + /// A64: USHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VSHL.U32 Dd, Dn, Dm + /// A64: USHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VSHL.U8 Qd, Qn, Qm + /// A64: USHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VSHL.U16 Qd, Qn, Qm + /// A64: USHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VSHL.U32 Qd, Qn, Qm + /// A64: USHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VSHL.U64 Qd, Qn, Qm + /// A64: USHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VSHL.U8 Qd, Qn, Qm + /// A64: USHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VSHL.U16 Qd, Qn, Qm + /// A64: USHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VSHL.U32 Qd, Qn, Qm + /// A64: USHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VSHL.U64 Qd, Qn, Qm + /// A64: USHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VRSHL.U8 Dd, Dn, Dm + /// A64: URSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VRSHL.U16 Dd, Dn, Dm + /// A64: URSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VRSHL.U32 Dd, Dn, Dm + /// A64: URSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VRSHL.U8 Dd, Dn, Dm + /// A64: URSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VRSHL.U16 Dd, Dn, Dm + /// A64: URSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VRSHL.U32 Dd, Dn, Dm + /// A64: URSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VRSHL.U8 Qd, Qn, Qm + /// A64: URSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VRSHL.U16 Qd, Qn, Qm + /// A64: URSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VRSHL.U32 Qd, Qn, Qm + /// A64: URSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VRSHL.U64 Qd, Qn, Qm + /// A64: URSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VRSHL.U8 Qd, Qn, Qm + /// A64: URSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VRSHL.U16 Qd, Qn, Qm + /// A64: URSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VRSHL.U32 Qd, Qn, Qm + /// A64: URSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VRSHL.U64 Qd, Qn, Qm + /// A64: URSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQRSHL.U8 Dd, Dn, Dm + /// A64: UQRSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQRSHL.U16 Dd, Dn, Dm + /// A64: UQRSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQRSHL.U32 Dd, Dn, Dm + /// A64: UQRSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQRSHL.U8 Dd, Dn, Dm + /// A64: UQRSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQRSHL.U16 Dd, Dn, Dm + /// A64: UQRSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQRSHL.U32 Dd, Dn, Dm + /// A64: UQRSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQRSHL.U8 Qd, Qn, Qm + /// A64: UQRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQRSHL.U16 Qd, Qn, Qm + /// A64: UQRSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQRSHL.U32 Qd, Qn, Qm + /// A64: UQRSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vqrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQRSHL.U64 Qd, Qn, Qm + /// A64: UQRSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQRSHL.U8 Qd, Qn, Qm + /// A64: UQRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQRSHL.U16 Qd, Qn, Qm + /// A64: UQRSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQRSHL.U32 Qd, Qn, Qm + /// A64: UQRSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vqrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQRSHL.U64 Qd, Qn, Qm + /// A64: UQRSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vqrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQRSHL.U64 Dd, Dn, Dm + /// A64: UQRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vqrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQRSHL.U64 Dd, Dn, Dm + /// A64: UQRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VRSHL.U64 Dd, Dn, Dm + /// A64: URSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VRSHL.U64 Dd, Dn, Dm + /// A64: URSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQSHL.U8 Dd, Dn, Dm + /// A64: UQSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQSHL.U16 Dd, Dn, Dm + /// A64: UQSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQSHL.U32 Dd, Dn, Dm + /// A64: UQSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQSHL.U8 Dd, Dn, Dm + /// A64: UQSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQSHL.U16 Dd, Dn, Dm + /// A64: UQSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQSHL.U32 Dd, Dn, Dm + /// A64: UQSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQSHL.U8 Qd, Qn, Qm + /// A64: UQSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQSHL.U16 Qd, Qn, Qm + /// A64: UQSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQSHL.U32 Qd, Qn, Qm + /// A64: UQSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vqshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQSHL.U64 Qd, Qn, Qm + /// A64: UQSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQSHL.U8 Qd, Qn, Qm + /// A64: UQSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQSHL.U16 Qd, Qn, Qm + /// A64: UQSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQSHL.U32 Qd, Qn, Qm + /// A64: UQSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vqshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQSHL.U64 Qd, Qn, Qm + /// A64: UQSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vqshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQSHL.U64 Dd, Dn, Dm + /// A64: UQSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vqshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQSHL.U64 Dd, Dn, Dm + /// A64: UQSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VSHL.U64 Dd, Dn, Dm + /// A64: USHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VSHL.U64 Dd, Dn, Dm + /// A64: USHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalScalar(Vector64 value, Vector64 count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vshr_n_s16 (int16x4_t a, const int n) + /// A32: VSHR.S16 Dd, Dm, #n + /// A64: SSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmetic(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vshr_n_s32 (int32x2_t a, const int n) + /// A32: VSHR.S32 Dd, Dm, #n + /// A64: SSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmetic(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vshr_n_s8 (int8x8_t a, const int n) + /// A32: VSHR.S8 Dd, Dm, #n + /// A64: SSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmetic(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vshrq_n_s16 (int16x8_t a, const int n) + /// A32: VSHR.S16 Qd, Qm, #n + /// A64: SSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vshrq_n_s32 (int32x4_t a, const int n) + /// A32: VSHR.S32 Qd, Qm, #n + /// A64: SSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vshrq_n_s64 (int64x2_t a, const int n) + /// A32: VSHR.S64 Qd, Qm, #n + /// A64: SSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vshrq_n_s8 (int8x16_t a, const int n) + /// A32: VSHR.S8 Qd, Qm, #n + /// A64: SSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vsra_n_s16 (int16x4_t a, int16x4_t b, const int n) + /// A32: VSRA.S16 Dd, Dm, #n + /// A64: SSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmeticAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vsra_n_s32 (int32x2_t a, int32x2_t b, const int n) + /// A32: VSRA.S32 Dd, Dm, #n + /// A64: SSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmeticAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vsra_n_s8 (int8x8_t a, int8x8_t b, const int n) + /// A32: VSRA.S8 Dd, Dm, #n + /// A64: SSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmeticAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vsraq_n_s16 (int16x8_t a, int16x8_t b, const int n) + /// A32: VSRA.S16 Qd, Qm, #n + /// A64: SSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vsraq_n_s32 (int32x4_t a, int32x4_t b, const int n) + /// A32: VSRA.S32 Qd, Qm, #n + /// A64: SSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vsraq_n_s64 (int64x2_t a, int64x2_t b, const int n) + /// A32: VSRA.S64 Qd, Qm, #n + /// A64: SSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vsraq_n_s8 (int8x16_t a, int8x16_t b, const int n) + /// A32: VSRA.S8 Qd, Qm, #n + /// A64: SSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vsra_n_s64 (int64x1_t a, int64x1_t b, const int n) + /// A32: VSRA.S64 Dd, Dm, #n + /// A64: SSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticAddScalar(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vqshrn_n_s32 (int32x4_t a, const int n) + /// A32: VQSHRN.S32 Dd, Qm, #n + /// A64: SQSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vqshrn_n_s64 (int64x2_t a, const int n) + /// A32: VQSHRN.S64 Dd, Qm, #n + /// A64: SQSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vqshrn_n_s16 (int16x8_t a, const int n) + /// A32: VQSHRN.S16 Dd, Qm, #n + /// A64: SQSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshrun_n_s16 (int16x8_t a, const int n) + /// A32: VQSHRUN.S16 Dd, Qm, #n + /// A64: SQSHRUN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshrun_n_s32 (int32x4_t a, const int n) + /// A32: VQSHRUN.S32 Dd, Qm, #n + /// A64: SQSHRUN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshrun_n_s64 (int64x2_t a, const int n) + /// A32: VQSHRUN.S64 Dd, Qm, #n + /// A64: SQSHRUN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshrun_high_n_s16 (uint8x8_t r, int16x8_t a, const int n) + /// A32: VQSHRUN.S16 Dd+1, Dn, #n + /// A64: SQSHRUN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshrun_high_n_s32 (uint16x4_t r, int32x4_t a, const int n) + /// A32: VQSHRUN.S32 Dd+1, Dn, #n + /// A64: SQSHRUN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshrun_high_n_s64 (uint32x2_t r, int64x2_t a, const int n) + /// A32: VQSHRUN.S64 Dd+1, Dn, #n + /// A64: SQSHRUN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vqshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VQSHRN.S32 Dd+1, Qm, #n + /// A64: SQSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vqshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VQSHRN.S64 Dd+1, Qm, #n + /// A64: SQSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vqshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VQSHRN.S16 Dd+1, Qm, #n + /// A64: SQSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vrshr_n_s16 (int16x4_t a, const int n) + /// A32: VRSHR.S16 Dd, Dm, #n + /// A64: SRSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmeticRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vrshr_n_s32 (int32x2_t a, const int n) + /// A32: VRSHR.S32 Dd, Dm, #n + /// A64: SRSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmeticRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vrshr_n_s8 (int8x8_t a, const int n) + /// A32: VRSHR.S8 Dd, Dm, #n + /// A64: SRSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmeticRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vrshrq_n_s16 (int16x8_t a, const int n) + /// A32: VRSHR.S16 Qd, Qm, #n + /// A64: SRSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vrshrq_n_s32 (int32x4_t a, const int n) + /// A32: VRSHR.S32 Qd, Qm, #n + /// A64: SRSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vrshrq_n_s64 (int64x2_t a, const int n) + /// A32: VRSHR.S64 Qd, Qm, #n + /// A64: SRSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vrshrq_n_s8 (int8x16_t a, const int n) + /// A32: VRSHR.S8 Qd, Qm, #n + /// A64: SRSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vrsra_n_s16 (int16x4_t a, int16x4_t b, const int n) + /// A32: VRSRA.S16 Dd, Dm, #n + /// A64: SRSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vrsra_n_s32 (int32x2_t a, int32x2_t b, const int n) + /// A32: VRSRA.S32 Dd, Dm, #n + /// A64: SRSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vrsra_n_s8 (int8x8_t a, int8x8_t b, const int n) + /// A32: VRSRA.S8 Dd, Dm, #n + /// A64: SRSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vrsraq_n_s16 (int16x8_t a, int16x8_t b, const int n) + /// A32: VRSRA.S16 Qd, Qm, #n + /// A64: SRSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vrsraq_n_s32 (int32x4_t a, int32x4_t b, const int n) + /// A32: VRSRA.S32 Qd, Qm, #n + /// A64: SRSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vrsraq_n_s64 (int64x2_t a, int64x2_t b, const int n) + /// A32: VRSRA.S64 Qd, Qm, #n + /// A64: SRSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vrsraq_n_s8 (int8x16_t a, int8x16_t b, const int n) + /// A32: VRSRA.S8 Qd, Qm, #n + /// A64: SRSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vrsra_n_s64 (int64x1_t a, int64x1_t b, const int n) + /// A32: VRSRA.S64 Dd, Dm, #n + /// A64: SRSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAddScalar(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vqrshrn_n_s32 (int32x4_t a, const int n) + /// A32: VQRSHRN.S32 Dd, Qm, #n + /// A64: SQRSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vqrshrn_n_s64 (int64x2_t a, const int n) + /// A32: VQRSHRN.S64 Dd, Qm, #n + /// A64: SQRSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vqrshrn_n_s16 (int16x8_t a, const int n) + /// A32: VQRSHRN.S16 Dd, Qm, #n + /// A64: SQRSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqrshrun_n_s16 (int16x8_t a, const int n) + /// A32: VQRSHRUN.S16 Dd, Qm, #n + /// A64: SQRSHRUN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqrshrun_n_s32 (int32x4_t a, const int n) + /// A32: VQRSHRUN.S32 Dd, Qm, #n + /// A64: SQRSHRUN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqrshrun_n_s64 (int64x2_t a, const int n) + /// A32: VQRSHRUN.S64 Dd, Qm, #n + /// A64: SQRSHRUN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqrshrun_high_n_s16 (uint8x8_t r, int16x8_t a, const int n) + /// A32: VQRSHRUN.S16 Dd+1, Dn, #n + /// A64: SQRSHRUN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqrshrun_high_n_s32 (uint16x4_t r, int32x4_t a, const int n) + /// A32: VQRSHRUN.S32 Dd+1, Dn, #n + /// A64: SQRSHRUN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqrshrun_high_n_s64 (uint32x2_t r, int64x2_t a, const int n) + /// A32: VQRSHRUN.S64 Dd+1, Dn, #n + /// A64: SQRSHRUN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vqrshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VQRSHRN.S32 Dd+1, Dn, #n + /// A64: SQRSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vqrshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VQRSHRN.S64 Dd+1, Dn, #n + /// A64: SQRSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vqrshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VQRSHRN.S16 Dd+1, Dn, #n + /// A64: SQRSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vrshr_n_s64 (int64x1_t a, const int n) + /// A32: VRSHR.S64 Dd, Dm, #n + /// A64: SRSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int64x1_t vshr_n_s64 (int64x1_t a, const int n) + /// A32: VSHR.S64 Dd, Dm, #n + /// A64: SSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vshr_n_u8 (uint8x8_t a, const int n) + /// A32: VSHR.U8 Dd, Dm, #n + /// A64: USHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vshr_n_u16 (uint16x4_t a, const int n) + /// A32: VSHR.U16 Dd, Dm, #n + /// A64: USHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vshr_n_u32 (uint32x2_t a, const int n) + /// A32: VSHR.U32 Dd, Dm, #n + /// A64: USHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vshr_n_u8 (uint8x8_t a, const int n) + /// A32: VSHR.U8 Dd, Dm, #n + /// A64: USHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vshr_n_u16 (uint16x4_t a, const int n) + /// A32: VSHR.U16 Dd, Dm, #n + /// A64: USHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vshr_n_u32 (uint32x2_t a, const int n) + /// A32: VSHR.U32 Dd, Dm, #n + /// A64: USHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VSHR.U8 Qd, Qm, #n + /// A64: USHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VSHR.U16 Qd, Qm, #n + /// A64: USHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VSHR.U32 Qd, Qm, #n + /// A64: USHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VSHR.U64 Qd, Qm, #n + /// A64: USHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VSHR.U8 Qd, Qm, #n + /// A64: USHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VSHR.U16 Qd, Qm, #n + /// A64: USHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VSHR.U32 Qd, Qm, #n + /// A64: USHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VSHR.U64 Qd, Qm, #n + /// A64: USHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VSRA.U8 Dd, Dm, #n + /// A64: USRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VSRA.U16 Dd, Dm, #n + /// A64: USRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VSRA.U32 Dd, Dm, #n + /// A64: USRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VSRA.U8 Dd, Dm, #n + /// A64: USRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VSRA.U16 Dd, Dm, #n + /// A64: USRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VSRA.U32 Dd, Dm, #n + /// A64: USRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VSRA.U8 Qd, Qm, #n + /// A64: USRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VSRA.U16 Qd, Qm, #n + /// A64: USRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VSRA.U32 Qd, Qm, #n + /// A64: USRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VSRA.U64 Qd, Qm, #n + /// A64: USRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VSRA.U8 Qd, Qm, #n + /// A64: USRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VSRA.U16 Qd, Qm, #n + /// A64: USRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VSRA.U32 Qd, Qm, #n + /// A64: USRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VSRA.U64 Qd, Qm, #n + /// A64: USRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VSRA.U64 Dd, Dm, #n + /// A64: USRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAddScalar(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VSRA.U64 Dd, Dm, #n + /// A64: USRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAddScalar(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VSHRN.I16 Dd, Qm, #n + /// A64: SHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vshrn_n_s32 (int32x4_t a, const int n) + /// A32: VSHRN.I32 Dd, Qm, #n + /// A64: SHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vshrn_n_s64 (int64x2_t a, const int n) + /// A32: VSHRN.I64 Dd, Qm, #n + /// A64: SHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vshrn_n_s16 (int16x8_t a, const int n) + /// A32: VSHRN.I16 Dd, Qm, #n + /// A64: SHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VSHRN.I32 Dd, Qm, #n + /// A64: SHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VSHRN.I64 Dd, Qm, #n + /// A64: SHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd, Qm, #n + /// A64: UQSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd, Qm, #n + /// A64: UQSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd, Qm, #n + /// A64: UQSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd, Qm, #n + /// A64: UQSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd, Qm, #n + /// A64: UQSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd, Qm, #n + /// A64: UQSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VSHRN.I16 Dd+1, Qm, #n + /// A64: SHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VSHRN.I32 Dd+1, Qm, #n + /// A64: SHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VSHRN.I64 Dd+1, Qm, #n + /// A64: SHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VSHRN.I16 Dd+1, Qm, #n + /// A64: SHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VSHRN.I32 Dd+1, Qm, #n + /// A64: SHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VSHRN.I64 Dd+1, Qm, #n + /// A64: SHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrshr_n_u8 (uint8x8_t a, const int n) + /// A32: VRSHR.U8 Dd, Dm, #n + /// A64: URSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrshr_n_u16 (uint16x4_t a, const int n) + /// A32: VRSHR.U16 Dd, Dm, #n + /// A64: URSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrshr_n_u32 (uint32x2_t a, const int n) + /// A32: VRSHR.U32 Dd, Dm, #n + /// A64: URSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrshr_n_u8 (uint8x8_t a, const int n) + /// A32: VRSHR.U8 Dd, Dm, #n + /// A64: URSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrshr_n_u16 (uint16x4_t a, const int n) + /// A32: VRSHR.U16 Dd, Dm, #n + /// A64: URSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrshr_n_u32 (uint32x2_t a, const int n) + /// A32: VRSHR.U32 Dd, Dm, #n + /// A64: URSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VRSHR.U8 Qd, Qm, #n + /// A64: URSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VRSHR.U16 Qd, Qm, #n + /// A64: URSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VRSHR.U32 Qd, Qm, #n + /// A64: URSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vrshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VRSHR.U64 Qd, Qm, #n + /// A64: URSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VRSHR.U8 Qd, Qm, #n + /// A64: URSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VRSHR.U16 Qd, Qm, #n + /// A64: URSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VRSHR.U32 Qd, Qm, #n + /// A64: URSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vrshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VRSHR.U64 Qd, Qm, #n + /// A64: URSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VRSRA.U8 Dd, Dm, #n + /// A64: URSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VRSRA.U16 Dd, Dm, #n + /// A64: URSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VRSRA.U32 Dd, Dm, #n + /// A64: URSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VRSRA.U8 Dd, Dm, #n + /// A64: URSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VRSRA.U16 Dd, Dm, #n + /// A64: URSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VRSRA.U32 Dd, Dm, #n + /// A64: URSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VRSRA.U8 Qd, Qm, #n + /// A64: URSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VRSRA.U16 Qd, Qm, #n + /// A64: URSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VRSRA.U32 Qd, Qm, #n + /// A64: URSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vrsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VRSRA.U64 Qd, Qm, #n + /// A64: URSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VRSRA.U8 Qd, Qm, #n + /// A64: URSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VRSRA.U16 Qd, Qm, #n + /// A64: URSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VRSRA.U32 Qd, Qm, #n + /// A64: URSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vrsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VRSRA.U64 Qd, Qm, #n + /// A64: URSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vrsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VRSRA.U64 Dd, Dm, #n + /// A64: URSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedAddScalar(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vrsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VRSRA.U64 Dd, Dm, #n + /// A64: URSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedAddScalar(Vector64 addend, Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vrshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd, Qm, #n + /// A64: RSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x4_t vrshrn_n_s32 (int32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd, Qm, #n + /// A64: RSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x2_t vrshrn_n_s64 (int64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd, Qm, #n + /// A64: RSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x8_t vrshrn_n_s16 (int16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd, Qm, #n + /// A64: RSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vrshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd, Qm, #n + /// A64: RSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vrshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd, Qm, #n + /// A64: RSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqrshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd, Qm, #n + /// A64: UQRSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqrshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd, Qm, #n + /// A64: UQRSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqrshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd, Qm, #n + /// A64: UQRSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x8_t vqrshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd, Qm, #n + /// A64: UQRSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x4_t vqrshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd, Qm, #n + /// A64: UQRSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x2_t vqrshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd, Qm, #n + /// A64: UQRSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqrshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqrshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqrshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vqrshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vqrshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vqrshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint8x16_t vrshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vrshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vrshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int8x16_t vrshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vrshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vrshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vrshr_n_u64 (uint64x1_t a, const int n) + /// A32: VRSHR.U64 Dd, Dm, #n + /// A64: URSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vrshr_n_u64 (uint64x1_t a, const int n) + /// A32: VRSHR.U64 Dd, Dm, #n + /// A64: URSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vshr_n_u64 (uint64x1_t a, const int n) + /// A32: VSHR.U64 Dd, Dm, #n + /// A64: USHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x1_t vshr_n_u64 (uint64x1_t a, const int n) + /// A32: VSHR.U64 Dd, Dm, #n + /// A64: USHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalScalar(Vector64 value, byte count) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vmovl_s16 (int16x4_t a) + /// A32: VMOVL.S16 Qd, Dm + /// A64: SXTL Vd.4S, Vn.4H + /// + public static Vector128 SignExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vmovl_s32 (int32x2_t a) + /// A32: VMOVL.S32 Qd, Dm + /// A64: SXTL Vd.2D, Vn.2S + /// + public static Vector128 SignExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vmovl_s8 (int8x8_t a) + /// A32: VMOVL.S8 Qd, Dm + /// A64: SXTL Vd.8H, Vn.8B + /// + public static Vector128 SignExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// int32x4_t vmovl_high_s16 (int16x8_t a) + /// A32: VMOVL.S16 Qd, Dm+1 + /// A64: SXTL2 Vd.4S, Vn.8H + /// + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// int64x2_t vmovl_high_s32 (int32x4_t a) + /// A32: VMOVL.S32 Qd, Dm+1 + /// A64: SXTL2 Vd.2D, Vn.4S + /// + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// int16x8_t vmovl_high_s8 (int8x16_t a) + /// A32: VMOVL.S8 Qd, Dm+1 + /// A64: SXTL2 Vd.8H, Vn.16B + /// + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// float64x1_t vsqrt_f64 (float64x1_t a) + /// A32: VSQRT.F64 Dd, Dm + /// A64: FSQRT Dd, Dn + /// + public static Vector64 SqrtScalar(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t vsqrts_f32 (float32_t a) + /// A32: VSQRT.F32 Sd, Sm + /// A64: FSQRT Sd, Sn + /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs. + /// + public static Vector64 SqrtScalar(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u8 (uint8_t * ptr, uint8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_f64 (float64_t * ptr, float64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(double* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s16 (int16_t * ptr, int16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 {Vt.4H }, [Xn] + /// + public static unsafe void Store(short* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s32 (int32_t * ptr, int32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(int* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s64 (int64_t * ptr, int64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(long* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_s8 (int8_t * ptr, int8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(sbyte* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_f32 (float32_t * ptr, float32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(float* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u16 (uint16_t * ptr, uint16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 { Vt.4H }, [Xn] + /// + public static unsafe void Store(ushort* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u32 (uint32_t * ptr, uint32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(uint* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1_u64 (uint64_t * ptr, uint64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(ulong* address, Vector64 source) { throw new PlatformNotSupportedException(); } + + /// + /// void vst1q_u8 (uint8_t * ptr, uint8x16_t val) + /// A32: VST1.8 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.16B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector128 source) { throw new PlatformNotSupportedException(); } /// /// void vst1q_f64 (float64_t * ptr, float64x2_t val) @@ -7048,168 +9959,168 @@ public new abstract class Arm64 : ArmBase.Arm64 /// A32: VSUBHN.I16 Dd, Qn, Qm /// A64: SUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int16x4_t vsubhn_s32 (int32x4_t a, int32x4_t b) /// A32: VSUBHN.I32 Dd, Qn, Qm /// A64: SUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int32x2_t vsubhn_s64 (int64x2_t a, int64x2_t b) /// A32: VSUBHN.I64 Dd, Qn, Qm /// A64: SUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int8x8_t vsubhn_s16 (int16x8_t a, int16x8_t b) /// A32: VSUBHN.I16 Dd, Qn, Qm /// A64: SUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint16x4_t vsubhn_u32 (uint32x4_t a, uint32x4_t b) /// A32: VSUBHN.I32 Dd, Qn, Qm /// A64: SUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint32x2_t vsubhn_u64 (uint64x2_t a, uint64x2_t b) /// A32: VSUBHN.I64 Dd, Qn, Qm /// A64: SUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint8x16_t vsubhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) /// A32: VSUBHN.I16 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: SUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int16x8_t vsubhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) /// A32: VSUBHN.I32 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: SUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int32x4_t vsubhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) /// A32: VSUBHN.I64 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: SUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int8x16_t vsubhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) /// A32: VSUBHN.I16 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: SUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint16x8_t vsubhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) /// A32: VSUBHN.I32 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: SUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint32x4_t vsubhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) /// A32: VSUBHN.I64 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: SUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint8x8_t vrsubhn_u16 (uint16x8_t a, uint16x8_t b) /// A32: VRSUBHN.I16 Dd, Qn, Qm /// A64: RSUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int16x4_t vrsubhn_s32 (int32x4_t a, int32x4_t b) /// A32: VRSUBHN.I32 Dd, Qn, Qm /// A64: RSUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int32x2_t vrsubhn_s64 (int64x2_t a, int64x2_t b) /// A32: VRSUBHN.I64 Dd, Qn, Qm /// A64: RSUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int8x8_t vrsubhn_s16 (int16x8_t a, int16x8_t b) /// A32: VRSUBHN.I16 Dd, Qn, Qm /// A64: RSUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint16x4_t vrsubhn_u32 (uint32x4_t a, uint32x4_t b) /// A32: VRSUBHN.I32 Dd, Qn, Qm /// A64: RSUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint32x2_t vrsubhn_u64 (uint64x2_t a, uint64x2_t b) /// A32: VRSUBHN.I64 Dd, Qn, Qm /// A64: RSUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint8x16_t vrsubhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) /// A32: VRSUBHN.I16 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RSUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int16x8_t vrsubhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) /// A32: VRSUBHN.I32 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RSUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int32x4_t vrsubhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) /// A32: VRSUBHN.I64 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RSUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int8x16_t vrsubhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) /// A32: VRSUBHN.I16 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RSUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint16x8_t vrsubhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) /// A32: VRSUBHN.I32 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RSUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint32x4_t vrsubhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) /// A32: VRSUBHN.I64 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RSUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// uint8x8_t vqsub_u8 (uint8x8_t a, uint8x8_t b) @@ -7691,5 +10602,89 @@ public new abstract class Arm64 : ArmBase.Arm64 /// A64: EOR Vd.16B, Vn.16B, Vm.16B /// public static Vector128 Xor(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vmovl_u8 (uint8x8_t a) + /// A32: VMOVL.U8 Qd, Dm + /// A64: UXTL Vd.8H, Vn.8B + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vmovl_u16 (uint16x4_t a) + /// A32: VMOVL.U16 Qd, Dm + /// A64: UXTL Vd.4S, Vn.4H + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vmovl_u32 (uint32x2_t a) + /// A32: VMOVL.U32 Qd, Dm + /// A64: UXTL Vd.2D, Vn.2S + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vmovl_u8 (uint8x8_t a) + /// A32: VMOVL.U8 Qd, Dm + /// A64: UXTL Vd.8H, Vn.8B + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vmovl_u16 (uint16x4_t a) + /// A32: VMOVL.U16 Qd, Dm + /// A64: UXTL Vd.4S, Vn.4H + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vmovl_u32 (uint32x2_t a) + /// A32: VMOVL.U32 Qd, Dm + /// A64: UXTL Vd.2D, Vn.2S + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vmovl_high_u8 (uint8x16_t a) + /// A32: VMOVL.U8 Qd, Dm+1 + /// A64: UXTL2 Vd.8H, Vn.16B + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vmovl_high_u16 (uint16x8_t a) + /// A32: VMOVL.U16 Qd, Dm+1 + /// A64: UXTL2 Vd.4S, Vn.8H + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vmovl_high_u32 (uint32x4_t a) + /// A32: VMOVL.U32 Qd, Dm+1 + /// A64: UXTL2 Vd.2D, Vn.4S + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16x8_t vmovl_high_u8 (uint8x16_t a) + /// A32: VMOVL.U8 Qd, Dm+1 + /// A64: UXTL2 Vd.8H, Vn.16B + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32x4_t vmovl_high_u16 (uint16x8_t a) + /// A32: VMOVL.U16 Qd, Dm+1 + /// A64: UXTL2 Vd.4S, Vn.8H + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64x2_t vmovl_high_u32 (uint32x4_t a) + /// A32: VMOVL.U32 Qd, Dm+1 + /// A64: UXTL2 Vd.2D, Vn.4S + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs index fa20a0a87a2f7..72233956e1829 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs @@ -642,6 +642,42 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector128 Divide(Vector128 left, Vector128 right) => Divide(left, right); + /// + /// float64x2_t vdupq_laneq_f64 (float64x2_t vec, const int lane) + /// A64: DUP Vd.2D, Vn.D[index] + /// + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) => DuplicateSelectedScalarToVector128(value, index); + + /// + /// int64x2_t vdupq_laneq_s64 (int64x2_t vec, const int lane) + /// A64: DUP Vd.2D, Vn.D[index] + /// + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) => DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint64x2_t vdupq_laneq_u64 (uint64x2_t vec, const int lane) + /// A64: DUP Vd.2D, Vn.D[index] + /// + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) => DuplicateSelectedScalarToVector128(value, index); + + /// + /// float64x2_t vdupq_n_f64 (float64_t value) + /// A64: DUP Vd.2D, Vn.D[0] + /// + public static Vector128 DuplicateToVector128(double value) => DuplicateToVector128(value); + + /// + /// int64x2_t vdupq_n_s64 (int64_t value) + /// A64: DUP Vd.2D, Rn + /// + public static Vector128 DuplicateToVector128(long value) => DuplicateToVector128(value); + + /// + /// uint64x2_t vdupq_n_s64 (uint64_t value) + /// A64: DUP Vd.2D, Rn + /// + public static Vector128 DuplicateToVector128(ulong value) => DuplicateToVector128(value); + /// /// float64x2_t vfmaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) /// A64: FMLA Vd.2D, Vn.2D, Vm.2D @@ -1166,6 +1202,312 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector64 ReciprocalStepScalar(Vector64 left, Vector64 right) => ReciprocalStepScalar(left, right); + /// + /// int16_t vqrshlh_s16 (int16_t a, int16_t b) + /// A64: SQRSHL Hd, Hn, Hm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturateScalar(value, count); + + /// + /// int32_t vqrshls_s32 (int32_t a, int32_t b) + /// A64: SQRSHL Sd, Sn, Sm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturateScalar(value, count); + + /// + /// int8_t vqrshlb_s8 (int8_t a, int8_t b) + /// A64: SQRSHL Bd, Bn, Bm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturateScalar(value, count); + + /// + /// int16_t vqshlh_s16 (int16_t a, int16_t b) + /// A64: SQSHL Hd, Hn, Hm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticSaturateScalar(value, count); + + /// + /// int32_t vqshls_s32 (int32_t a, int32_t b) + /// A64: SQSHL Sd, Sn, Sm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticSaturateScalar(value, count); + + /// + /// int8_t vqshlb_s8 (int8_t a, int8_t b) + /// A64: SQSHL Bd, Bn, Bm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticSaturateScalar(value, count); + + /// + /// uint8_t vqshlb_n_u8 (uint8_t a, const int n) + /// A64: UQSHL Bd, Bn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// int16_t vqshlh_n_s16 (int16_t a, const int n) + /// A64: SQSHL Hd, Hn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// int32_t vqshls_n_s32 (int32_t a, const int n) + /// A64: SQSHL Sd, Sn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// int8_t vqshlb_n_s8 (int8_t a, const int n) + /// A64: SQSHL Bd, Bn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// uint16_t vqshlh_n_u16 (uint16_t a, const int n) + /// A64: UQSHL Hd, Hn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// uint32_t vqshls_n_u32 (uint32_t a, const int n) + /// A64: UQSHL Sd, Sn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// uint16_t vqshluh_n_s16 (int16_t a, const int n) + /// A64: SQSHLU Hd, Hn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsignedScalar(value, count); + + /// + /// uint32_t vqshlus_n_s32 (int32_t a, const int n) + /// A64: SQSHLU Sd, Sn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsignedScalar(value, count); + + /// + /// uint8_t vqshlub_n_s8 (int8_t a, const int n) + /// A64: SQSHLU Bd, Bn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsignedScalar(value, count); + + /// + /// uint8_t vqrshlb_u8 (uint8_t a, int8_t b) + /// A64: UQRSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint16_t vqrshlh_u16 (uint16_t a, int16_t b) + /// A64: UQRSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint32_t vqrshls_u32 (uint32_t a, int32_t b) + /// A64: UQRSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint8_t vqrshlb_u8 (uint8_t a, int8_t b) + /// A64: UQRSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint16_t vqrshlh_u16 (uint16_t a, int16_t b) + /// A64: UQRSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint32_t vqrshls_u32 (uint32_t a, int32_t b) + /// A64: UQRSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint8_t vqshlb_u8 (uint8_t a, int8_t b) + /// A64: UQSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint16_t vqshlh_u16 (uint16_t a, int16_t b) + /// A64: UQSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint32_t vqshls_u32 (uint32_t a, int32_t b) + /// A64: UQSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint8_t vqshlb_u8 (uint8_t a, int8_t b) + /// A64: UQSHL Bd, Bn, Bm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint16_t vqshlh_u16 (uint16_t a, int16_t b) + /// A64: UQSHL Hd, Hn, Hm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint32_t vqshls_u32 (uint32_t a, int32_t b) + /// A64: UQSHL Sd, Sn, Sm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// int16_t vqshrns_n_s32 (int32_t a, const int n) + /// A64: SQSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightArithmeticNarrowingSaturateScalar(value, count); + + /// + /// int32_t vqshrnd_n_s64 (int64_t a, const int n) + /// A64: SQSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightArithmeticNarrowingSaturateScalar(value, count); + + /// + /// int8_t vqshrnh_n_s16 (int16_t a, const int n) + /// A64: SQSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightArithmeticNarrowingSaturateScalar(value, count); + + /// + /// uint8_t vqshrunh_n_s16 (int16_t a, const int n) + /// A64: SQSHRUN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(Vector64 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedScalar(value, count); + + /// + /// uint16_t vqshruns_n_s32 (int32_t a, const int n) + /// A64: SQSHRUN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(Vector64 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedScalar(value, count); + + /// + /// uint32_t vqshrund_n_s64 (int64_t a, const int n) + /// A64: SQSHRUN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(Vector64 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedScalar(value, count); + + /// + /// int16_t vqrshrns_n_s32 (int32_t a, const int n) + /// A64: SQRSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateScalar(value, count); + + /// + /// int32_t vqrshrnd_n_s64 (int64_t a, const int n) + /// A64: SQRSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateScalar(value, count); + + /// + /// int8_t vqrshrnh_n_s16 (int16_t a, const int n) + /// A64: SQRSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateScalar(value, count); + + /// + /// uint8_t vqrshrunh_n_s16 (int16_t a, const int n) + /// A64: SQRSHRUN Bd, Hn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(value, count); + + /// + /// uint16_t vqrshruns_n_s32 (int32_t a, const int n) + /// A64: SQRSHRUN Hd, Sn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(value, count); + + /// + /// uint32_t vqrshrund_n_s64 (int64_t a, const int n) + /// A64: SQRSHRUN Sd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(value, count); + + /// + /// uint8_t vqshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalNarrowingSaturateScalar(value, count); + + /// + /// uint16_t vqshrns_n_u32 (uint32_t a, const int n) + /// A64: UQSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalNarrowingSaturateScalar(value, count); + + /// + /// uint32_t vqshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalNarrowingSaturateScalar(value, count); + + /// + /// uint8_t vqshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalNarrowingSaturateScalar(value, count); + + /// + /// uint16_t vqshrns_n_u32 (uint32_t a, const int n) + /// A64: UQSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalNarrowingSaturateScalar(value, count); + + /// + /// uint32_t vqshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalNarrowingSaturateScalar(value, count); + + /// + /// uint8_t vqrshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQRSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); + + /// + /// uint16_t vqrshrns_n_u32 (uint32_t a, const int n) + /// A64: UQRSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); + + /// + /// uint32_t vqrshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQRSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); + + /// + /// uint8_t vqrshrnh_n_u16 (uint16_t a, const int n) + /// A64: UQRSHRN Bd, Hn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); + + /// + /// uint16_t vqrshrns_n_u32 (uint32_t a, const int n) + /// A64: UQRSHRN Hd, Sn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); + + /// + /// uint32_t vqrshrnd_n_u64 (uint64_t a, const int n) + /// A64: UQRSHRN Sd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); + /// /// float32x2_t vsqrt_f32 (float32x2_t a) /// A64: FSQRT Vd.2S, Vn.2S @@ -2476,6 +2818,90 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); + /// + /// uint8x8_t vaddhn_u16 (uint16x8_t a, uint16x8_t b) + /// A32: VADDHN.I16 Dd, Qn, Qm + /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) => AddHighNarrowingLower(left, right); + + /// + /// int16x4_t vaddhn_s32 (int32x4_t a, int32x4_t b) + /// A32: VADDHN.I32 Dd, Qn, Qm + /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) => AddHighNarrowingLower(left, right); + + /// + /// int32x2_t vaddhn_s64 (int64x2_t a, int64x2_t b) + /// A32: VADDHN.I64 Dd, Qn, Qm + /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) => AddHighNarrowingLower(left, right); + + /// + /// int8x8_t vaddhn_s16 (int16x8_t a, int16x8_t b) + /// A32: VADDHN.I16 Dd, Qn, Qm + /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) => AddHighNarrowingLower(left, right); + + /// + /// uint16x4_t vaddhn_u32 (uint32x4_t a, uint32x4_t b) + /// A32: VADDHN.I32 Dd, Qn, Qm + /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) => AddHighNarrowingLower(left, right); + + /// + /// uint32x2_t vaddhn_u64 (uint64x2_t a, uint64x2_t b) + /// A32: VADDHN.I64 Dd, Qn, Qm + /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D + /// + public static Vector64 AddHighNarrowingLower(Vector128 left, Vector128 right) => AddHighNarrowingLower(left, right); + + /// + /// uint8x16_t vaddhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) + /// A32: VADDHN.I16 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.16B, Vn.8H, Vm.8H + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddHighNarrowingUpper(lower, left, right); + + /// + /// int16x8_t vaddhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) + /// A32: VADDHN.I32 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.8H, Vn.4S, Vm.4S + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddHighNarrowingUpper(lower, left, right); + + /// + /// int32x4_t vaddhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) + /// A32: VADDHN.I64 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.4S, Vn.2D, Vm.2D + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddHighNarrowingUpper(lower, left, right); + + /// + /// int8x16_t vaddhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) + /// A32: VADDHN.I16 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.16B, Vn.8H, Vm.8H + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddHighNarrowingUpper(lower, left, right); + + /// + /// uint16x8_t vaddhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) + /// A32: VADDHN.I32 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.8H, Vn.4S, Vm.4S + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddHighNarrowingUpper(lower, left, right); + + /// + /// uint32x4_t vaddhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) + /// A32: VADDHN.I64 Dd+1, Qn, Qm + /// A64: ADDHN2 Vd.4S, Vn.2D, Vm.2D + /// + public static Vector128 AddHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddHighNarrowingUpper(lower, left, right); + /// /// uint8x8_t vpadd_u8 (uint8x8_t a, uint8x8_t b) /// A32: VPADD.I8 Dd, Dn, Dm @@ -2694,172 +3120,88 @@ public new abstract class Arm64 : ArmBase.Arm64 public static Vector64 AddPairwiseWideningScalar(Vector64 value) => AddPairwiseWideningScalar(value); /// - /// uint8x8_t vaddhn_u16 (uint16x8_t a, uint16x8_t b) - /// A32: VADDHN.I16 Dd, Qn, Qm - /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H + /// uint8x8_t vraddhn_u16 (uint16x8_t a, uint16x8_t b) + /// A32: VRADDHN.I16 Dd, Qn, Qm + /// A64: RADDHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) => AddReturningHighNarrowLower(left, right); + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) => AddRoundedHighNarrowingLower(left, right); /// - /// int16x4_t vaddhn_s32 (int32x4_t a, int32x4_t b) - /// A32: VADDHN.I32 Dd, Qn, Qm - /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S + /// int16x4_t vraddhn_s32 (int32x4_t a, int32x4_t b) + /// A32: VRADDHN.I32 Dd, Qn, Qm + /// A64: RADDHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) => AddReturningHighNarrowLower(left, right); + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) => AddRoundedHighNarrowingLower(left, right); /// - /// int32x2_t vaddhn_s64 (int64x2_t a, int64x2_t b) - /// A32: VADDHN.I64 Dd, Qn, Qm - /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D + /// int32x2_t vraddhn_s64 (int64x2_t a, int64x2_t b) + /// A32: VRADDHN.I64 Dd, Qn, Qm + /// A64: RADDHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) => AddReturningHighNarrowLower(left, right); - - /// - /// int8x8_t vaddhn_s16 (int16x8_t a, int16x8_t b) - /// A32: VADDHN.I16 Dd, Qn, Qm - /// A64: ADDHN Vd.8B, Vn.8H, Vm.8H - /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) => AddReturningHighNarrowLower(left, right); - - /// - /// uint16x4_t vaddhn_u32 (uint32x4_t a, uint32x4_t b) - /// A32: VADDHN.I32 Dd, Qn, Qm - /// A64: ADDHN Vd.4H, Vn.4S, Vm.4S - /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) => AddReturningHighNarrowLower(left, right); - - /// - /// uint32x2_t vaddhn_u64 (uint64x2_t a, uint64x2_t b) - /// A32: VADDHN.I64 Dd, Qn, Qm - /// A64: ADDHN Vd.2S, Vn.2D, Vm.2D - /// - public static Vector64 AddReturningHighNarrowLower(Vector128 left, Vector128 right) => AddReturningHighNarrowLower(left, right); - - /// - /// uint8x16_t vaddhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) - /// A32: VADDHN.I16 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.16B, Vn.8B, Vm.8H - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningHighNarrowUpper(lower, left, right); - - /// - /// int16x8_t vaddhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) - /// A32: VADDHN.I32 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.8H, Vn.4H, Vm.4S - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningHighNarrowUpper(lower, left, right); - - /// - /// int32x4_t vaddhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) - /// A32: VADDHN.I64 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.4S, Vn.2S, Vm.2D - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningHighNarrowUpper(lower, left, right); - - /// - /// int8x16_t vaddhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) - /// A32: VADDHN.I16 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.16B, Vn.8B, Vm.8H - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningHighNarrowUpper(lower, left, right); - - /// - /// uint16x8_t vaddhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) - /// A32: VADDHN.I32 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.8H, Vn.4H, Vm.4S - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningHighNarrowUpper(lower, left, right); - - /// - /// uint32x4_t vaddhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) - /// A32: VADDHN.I64 Dd+1, Qn, Qm - /// A64: ADDHN2 Vd.4S, Vn.2S, Vm.2D - /// - public static Vector128 AddReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningHighNarrowUpper(lower, left, right); - - /// - /// uint8x8_t vraddhn_u16 (uint16x8_t a, uint16x8_t b) - /// A32: VRADDHN.I16 Dd, Qn, Qm - /// A64: RADDHN Vd.8B, Vn.8H, Vm.8H - /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowLower(left, right); - - /// - /// int16x4_t vraddhn_s32 (int32x4_t a, int32x4_t b) - /// A32: VRADDHN.I32 Dd, Qn, Qm - /// A64: RADDHN Vd.4H, Vn.4S, Vm.4S - /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowLower(left, right); - - /// - /// int32x2_t vraddhn_s64 (int64x2_t a, int64x2_t b) - /// A32: VRADDHN.I64 Dd, Qn, Qm - /// A64: RADDHN Vd.2S, Vn.2D, Vm.2D - /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowLower(left, right); + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) => AddRoundedHighNarrowingLower(left, right); /// /// int8x8_t vraddhn_s16 (int16x8_t a, int16x8_t b) /// A32: VRADDHN.I16 Dd, Qn, Qm /// A64: RADDHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowLower(left, right); + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) => AddRoundedHighNarrowingLower(left, right); /// /// uint16x4_t vraddhn_u32 (uint32x4_t a, uint32x4_t b) /// A32: VRADDHN.I32 Dd, Qn, Qm /// A64: RADDHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowLower(left, right); + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) => AddRoundedHighNarrowingLower(left, right); /// /// uint32x2_t vraddhn_u64 (uint64x2_t a, uint64x2_t b) /// A32: VRADDHN.I64 Dd, Qn, Qm /// A64: RADDHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 AddReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowLower(left, right); + public static Vector64 AddRoundedHighNarrowingLower(Vector128 left, Vector128 right) => AddRoundedHighNarrowingLower(left, right); /// /// uint8x16_t vraddhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) /// A32: VRADDHN.I16 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RADDHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddRoundedHighNarrowingUpper(lower, left, right); /// /// int16x8_t vraddhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) /// A32: VRADDHN.I32 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RADDHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddRoundedHighNarrowingUpper(lower, left, right); /// /// int32x4_t vraddhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) /// A32: VRADDHN.I64 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RADDHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddRoundedHighNarrowingUpper(lower, left, right); /// /// int8x16_t vraddhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) /// A32: VRADDHN.I16 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RADDHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddRoundedHighNarrowingUpper(lower, left, right); /// /// uint16x8_t vraddhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) /// A32: VRADDHN.I32 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RADDHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddRoundedHighNarrowingUpper(lower, left, right); /// /// uint32x4_t vraddhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) /// A32: VRADDHN.I64 Dd+1, Qn, Qm - /// A64: RADDHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RADDHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 AddReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => AddReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 AddRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => AddRoundedHighNarrowingUpper(lower, left, right); /// /// uint8x8_t vqadd_u8 (uint8x8_t a, uint8x8_t b) @@ -4203,6 +4545,300 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector64 DivideScalar(Vector64 left, Vector64 right) => DivideScalar(left, right); + /// + /// uint8x8_t vdup_lane_u8 (uint8x8_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// int16x4_t vdup_lane_s16 (int16x4_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// int32x2_t vdup_lane_s32 (int32x2_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// float32x2_t vdup_lane_f32 (float32x2_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// int8x8_t vdup_lane_s8 (int8x8_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// uint16x4_t vdup_lane_u16 (uint16x4_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// uint32x2_t vdup_lane_u32 (uint32x2_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector64 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// uint8x8_t vdup_laneq_u8 (uint8x16_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// int16x4_t vdup_laneq_s16 (int16x8_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// int32x2_t vdup_laneq_s32 (int32x4_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// float32x2_t vdup_laneq_f32 (float32x4_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// int8x8_t vdup_laneq_s8 (int8x16_t vec, const int lane) + /// A32: VDUP.8 Dd, Dm[index] + /// A64: DUP Vd.8B, Vn.B[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// uint16x4_t vdup_laneq_u16 (uint16x8_t vec, const int lane) + /// A32: VDUP.16 Dd, Dm[index] + /// A64: DUP Vd.4H, Vn.H[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// uint32x2_t vdup_laneq_u32 (uint32x4_t vec, const int lane) + /// A32: VDUP.32 Dd, Dm[index] + /// A64: DUP Vd.2S, Vn.S[index] + /// + public static Vector64 DuplicateSelectedScalarToVector64(Vector128 value, byte index)=> DuplicateSelectedScalarToVector64(value, index); + + /// + /// uint8x16_t vdupq_lane_u8 (uint8x8_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// int16x8_t vdupq_lane_s16 (int16x4_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// int32x4_t vdupq_lane_s32 (int32x2_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// float32x4_t vdupq_lane_f32 (float32x2_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// int8x16_t vdupq_lane_s8 (int8x8_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint16x8_t vdupq_lane_u16 (uint16x4_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint32x4_t vdupq_lane_u32 (uint32x2_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector64 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint8x16_t vdupq_lane_u8 (uint8x16_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// int16x8_t vdupq_lane_s16 (int16x8_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// int32x4_t vdupq_lane_s32 (int32x4_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// float32x4_t vdupq_lane_f32 (float32x4_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// int8x16_t vdupq_lane_s8 (int8x16_t vec, const int lane) + /// A32: VDUP.8 Qd, Dm[index] + /// A64: DUP Vd.16B, Vn.B[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint16x8_t vdupq_lane_u16 (uint16x8_t vec, const int lane) + /// A32: VDUP.16 Qd, Dm[index] + /// A64: DUP Vd.8H, Vn.H[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint32x4_t vdupq_lane_u32 (uint32x4_t vec, const int lane) + /// A32: VDUP.32 Qd, Dm[index] + /// A64: DUP Vd.4S, Vn.S[index] + /// + public static Vector128 DuplicateSelectedScalarToVector128(Vector128 value, byte index)=> DuplicateSelectedScalarToVector128(value, index); + + /// + /// uint8x8_t vdup_n_u8 (uint8_t value) + /// A32: VDUP.8 Dd, Rt + /// A64: DUP Vd.8B, Rn + /// + public static Vector64 DuplicateToVector64(byte value) => DuplicateToVector64(value); + + /// + /// int16x4_t vdup_n_s16 (int16_t value) + /// A32: VDUP.16 Dd, Rt + /// A64: DUP Vd.4H, Rn + /// + public static Vector64 DuplicateToVector64(short value) => DuplicateToVector64(value); + + /// + /// int32x2_t vdup_n_s32 (int32_t value) + /// A32: VDUP.32 Dd, Rt + /// A64: DUP Vd.2S, Rn + /// + public static Vector64 DuplicateToVector64(int value) => DuplicateToVector64(value); + + /// + /// int8x8_t vdup_n_s8 (int8_t value) + /// A32: VDUP.8 Dd, Rt + /// A64: DUP Vd.8B, Rn + /// + public static Vector64 DuplicateToVector64(sbyte value) => DuplicateToVector64(value); + + /// + /// float32x2_t vdup_n_f32 (float32_t value) + /// A32: VDUP Dd, Dm[0] + /// A64: DUP Vd.2S, Vn.S[0] + /// + public static Vector64 DuplicateToVector64(float value) => DuplicateToVector64(value); + + /// + /// uint16x4_t vdup_n_u16 (uint16_t value) + /// A32: VDUP.16 Dd, Rt + /// A64: DUP Vd.4H, Rn + /// + public static Vector64 DuplicateToVector64(ushort value) => DuplicateToVector64(value); + + /// + /// uint32x2_t vdup_n_u32 (uint32_t value) + /// A32: VDUP.32 Dd, Rt + /// A64: DUP Vd.2S, Rn + /// + public static Vector64 DuplicateToVector64(uint value) => DuplicateToVector64(value); + + /// + /// uint8x16_t vdupq_n_u8 (uint8_t value) + /// A32: VDUP.8 Qd, Rt + /// A64: DUP Vd.16B, Rn + /// + public static Vector128 DuplicateToVector128(byte value) => DuplicateToVector128(value); + + /// + /// int16x8_t vdupq_n_s16 (int16_t value) + /// A32: VDUP.16 Qd, Rt + /// A64: DUP Vd.8H, Rn + /// + public static Vector128 DuplicateToVector128(short value) => DuplicateToVector128(value); + + /// + /// int32x4_t vdupq_n_s32 (int32_t value) + /// A32: VDUP.32 Qd, Rt + /// A64: DUP Vd.4S, Rn + /// + public static Vector128 DuplicateToVector128(int value) => DuplicateToVector128(value); + + /// + /// int8x16_t vdupq_n_s8 (int8_t value) + /// A32: VDUP.8 Qd, Rt + /// A64: DUP Vd.16B, Rn + /// + public static Vector128 DuplicateToVector128(sbyte value) => DuplicateToVector128(value); + + /// + /// float32x4_t vdupq_n_f32 (float32_t value) + /// A32: VDUP Qd, Dm[0] + /// A64: DUP Vd.4S, Vn.S[0] + /// + public static Vector128 DuplicateToVector128(float value) => DuplicateToVector128(value); + + /// + /// uint16x8_t vdupq_n_u16 (uint16_t value) + /// A32: VDUP.16 Qd, Rt + /// A64: DUP Vd.8H, Rn + /// + public static Vector128 DuplicateToVector128(ushort value) => DuplicateToVector128(value); + + /// + /// uint32x4_t vdupq_n_u32 (uint32_t value) + /// A32: VDUP.32 Qd, Rt + /// A64: DUP Vd.4S, Rn + /// + public static Vector128 DuplicateToVector128(uint value) => DuplicateToVector128(value); + /// /// uint8_t vget_lane_u8 (uint8x8_t v, const int lane) /// A32: VMOV.U8 Rt, Dn[lane] @@ -4327,84 +4963,84 @@ public new abstract class Arm64 : ArmBase.Arm64 /// A32: VMOVN.I16 Dd+1, Qm /// A64: XTN2 Vd.16B, Vn.8H /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) => ExtractAndNarrowHigh (lower, value); + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) => ExtractNarrowingUpper(lower, value); /// /// int16x8_t vmovn_high_s32 (int16x4_t r, int32x4_t a) /// A32: VMOVN.I32 Dd+1, Qm /// A64: XTN2 Vd.8H, Vn.4S /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) => ExtractAndNarrowHigh (lower, value); + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) => ExtractNarrowingUpper(lower, value); /// /// int32x4_t vmovn_high_s64 (int32x2_t r, int64x2_t a) /// A32: VMOVN.I64 Dd+1, Qm /// A64: XTN2 Vd.4S, Vn.2D /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) => ExtractAndNarrowHigh (lower, value); + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) => ExtractNarrowingUpper(lower, value); /// /// uint8x16_t vmovn_high_u16 (uint8x8_t r, uint16x8_t a) /// A32: VMOVN.I16 Dd+1, Qm /// A64: XTN2 Vd.16B, Vn.8H /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) => ExtractAndNarrowHigh (lower, value); + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) => ExtractNarrowingUpper(lower, value); /// /// uint16x8_t vmovn_high_u32 (uint16x4_t r, uint32x4_t a) /// A32: VMOVN.I32 Dd+1, Qm /// A64: XTN2 Vd.8H, Vn.4S /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) => ExtractAndNarrowHigh (lower, value); + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) => ExtractNarrowingUpper(lower, value); /// /// uint32x4_t vmovn_high_u64 (uint32x2_t r, uint64x2_t a) /// A32: VMOVN.I64 Dd+1, Qm /// A64: XTN2 Vd.4S, Vn.2D /// - public static Vector128 ExtractAndNarrowHigh (Vector64 lower, Vector128 value) => ExtractAndNarrowHigh (lower, value); + public static Vector128 ExtractNarrowingUpper(Vector64 lower, Vector128 value) => ExtractNarrowingUpper(lower, value); /// /// int8x8_t vmovn_s16 (int16x8_t a) /// A32: VMOVN.I16 Dd, Qm /// A64: XTN Vd.8B, Vn.8H /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) => ExtractAndNarrowLow (value); + public static Vector64 ExtractNarrowingLower(Vector128 value) => ExtractNarrowingLower(value); /// /// int16x4_t vmovn_s32 (int32x4_t a) /// A32: VMOVN.I32 Dd, Qm /// A64: XTN Vd.4H, Vn.4S /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) => ExtractAndNarrowLow (value); + public static Vector64 ExtractNarrowingLower(Vector128 value) => ExtractNarrowingLower(value); /// /// int32x2_t vmovn_s64 (int64x2_t a) /// A32: VMOVN.I64 Dd, Qm /// A64: XTN Vd.2S, Vn.2D /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) => ExtractAndNarrowLow (value); + public static Vector64 ExtractNarrowingLower(Vector128 value) => ExtractNarrowingLower(value); /// /// uint8x8_t vmovn_u16 (uint16x8_t a) /// A32: VMOVN.I16 Dd, Qm /// A64: XTN Vd.8B, Vn.8H /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) => ExtractAndNarrowLow (value); + public static Vector64 ExtractNarrowingLower(Vector128 value) => ExtractNarrowingLower(value); /// /// uint16x4_t vmovn_u32 (uint32x4_t a) /// A32: VMOVN.I32 Dd, Qm /// A64: XTN Vd.4H, Vn.4S /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) => ExtractAndNarrowLow (value); + public static Vector64 ExtractNarrowingLower(Vector128 value) => ExtractNarrowingLower(value); /// /// uint32x2_t vmovn_u64 (uint64x2_t a) /// A32: VMOVN.I64 Dd, Qm /// A64: XTN Vd.2S, Vn.2D /// - public static Vector64 ExtractAndNarrowLow (Vector128 value) => ExtractAndNarrowLow (value); + public static Vector64 ExtractNarrowingLower(Vector128 value) => ExtractNarrowingLower(value); /// /// uint8x8_t vext_s8 (uint8x8_t a, uint8x8_t b, const int n) @@ -6666,6 +7302,34 @@ public new abstract class Arm64 : ArmBase.Arm64 /// public static Vector128 PolynomialMultiply(Vector128 left, Vector128 right) => PolynomialMultiply(left, right); + /// + /// poly16x8_t vmull_p8 (poly8x8_t a, poly8x8_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.16B, Vn.8B, Vm.8B + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) => PolynomialMultiplyWideningLower(left, right); + + /// + /// poly16x8_t vmull_p8 (poly8x8_t a, poly8x8_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.16B, Vn.8B, Vm.8B + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) => PolynomialMultiplyWideningLower(left, right); + + /// + /// poly16x8_t vmull_high_p8 (poly8x16_t a, poly8x16_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) => PolynomialMultiplyWideningUpper(left, right); + + /// + /// poly16x8_t vmull_high_p8 (poly8x16_t a, poly8x16_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) => PolynomialMultiplyWideningUpper(left, right); + /// /// uint8x8_t vcnt_u8 (uint8x8_t a) /// A32: VCNT.I8 Dd, Dm @@ -6779,96 +7443,2343 @@ public new abstract class Arm64 : ArmBase.Arm64 public static Vector128 ReciprocalStep(Vector128 left, Vector128 right) => ReciprocalStep(left, right); /// - /// float64x1_t vsqrt_f64 (float64x1_t a) - /// A32: VSQRT.F64 Dd, Dm - /// A64: FSQRT Dd, Dn + /// int16x4_t vshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VSHL.S16 Dd, Dn, Dm + /// A64: SSHL Vd.4H, Vn.4H, Vm.4H /// - public static Vector64 SqrtScalar(Vector64 value) => SqrtScalar(value); + public static Vector64 ShiftArithmetic(Vector64 value, Vector64 count) => ShiftArithmetic(value, count); /// - /// float32_t vsqrts_f32 (float32_t a) - /// A32: VSQRT.F32 Sd, Sm - /// A64: FSQRT Sd, Sn - /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs. + /// int32x2_t vshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VSHL.S32 Dd, Dn, Dm + /// A64: SSHL Vd.2S, Vn.2S, Vm.2S /// - public static Vector64 SqrtScalar(Vector64 value) => SqrtScalar(value); + public static Vector64 ShiftArithmetic(Vector64 value, Vector64 count) => ShiftArithmetic(value, count); /// - /// void vst1_u8 (uint8_t * ptr, uint8x8_t val) - /// A32: VST1.8 { Dd }, [Rn] - /// A64: ST1 { Vt.8B }, [Xn] + /// int8x8_t vshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VSHL.S8 Dd, Dn, Dm + /// A64: SSHL Vd.8B, Vn.8B, Vm.8B /// - public static unsafe void Store(byte* address, Vector64 source) => Store(address, source); + public static Vector64 ShiftArithmetic(Vector64 value, Vector64 count) => ShiftArithmetic(value, count); /// - /// void vst1_f64 (float64_t * ptr, float64x1_t val) - /// A32: VST1.64 { Dd }, [Rn] - /// A64: ST1 { Vt.1D }, [Xn] + /// int16x8_t vshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VSHL.S16 Qd, Qn, Qm + /// A64: SSHL Vd.8H, Vn.8H, Vm.8H /// - public static unsafe void Store(double* address, Vector64 source) => Store(address, source); + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) => ShiftArithmetic(value, count); /// - /// void vst1_s16 (int16_t * ptr, int16x4_t val) - /// A32: VST1.16 { Dd }, [Rn] - /// A64: ST1 {Vt.4H }, [Xn] + /// int32x4_t vshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VSHL.S32 Qd, Qn, Qm + /// A64: SSHL Vd.4S, Vn.4S, Vm.4S /// - public static unsafe void Store(short* address, Vector64 source) => Store(address, source); + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) => ShiftArithmetic(value, count); /// - /// void vst1_s32 (int32_t * ptr, int32x2_t val) - /// A32: VST1.32 { Dd }, [Rn] - /// A64: ST1 { Vt.2S }, [Xn] + /// int64x2_t vshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VSHL.S64 Qd, Qn, Qm + /// A64: SSHL Vd.2D, Vn.2D, Vm.2D /// - public static unsafe void Store(int* address, Vector64 source) => Store(address, source); + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) => ShiftArithmetic(value, count); /// - /// void vst1_s64 (int64_t * ptr, int64x1_t val) - /// A32: VST1.64 { Dd }, [Rn] - /// A64: ST1 { Vt.1D }, [Xn] + /// int8x16_t vshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VSHL.S8 Qd, Qn, Qm + /// A64: SSHL Vd.16B, Vn.16B, Vm.16B /// - public static unsafe void Store(long* address, Vector64 source) => Store(address, source); + public static Vector128 ShiftArithmetic(Vector128 value, Vector128 count) => ShiftArithmetic(value, count); /// - /// void vst1_s8 (int8_t * ptr, int8x8_t val) - /// A32: VST1.8 { Dd }, [Rn] - /// A64: ST1 { Vt.8B }, [Xn] + /// int16x4_t vrshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VRSHL.S16 Dd, Dn, Dm + /// A64: SRSHL Vd.4H, Vn.4H, Vm.4H /// - public static unsafe void Store(sbyte* address, Vector64 source) => Store(address, source); + public static Vector64 ShiftArithmeticRounded(Vector64 value, Vector64 count) => ShiftArithmeticRounded(value, count); /// - /// void vst1_f32 (float32_t * ptr, float32x2_t val) - /// A32: VST1.32 { Dd }, [Rn] - /// A64: ST1 { Vt.2S }, [Xn] + /// int32x2_t vrshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VRSHL.S32 Dd, Dn, Dm + /// A64: SRSHL Vd.2S, Vn.2S, Vm.2S /// - public static unsafe void Store(float* address, Vector64 source) => Store(address, source); + public static Vector64 ShiftArithmeticRounded(Vector64 value, Vector64 count) => ShiftArithmeticRounded(value, count); /// - /// void vst1_u16 (uint16_t * ptr, uint16x4_t val) - /// A32: VST1.16 { Dd }, [Rn] - /// A64: ST1 { Vt.4H }, [Xn] + /// int8x8_t vrshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VRSHL.S8 Dd, Dn, Dm + /// A64: SRSHL Vd.8B, Vn.8B, Vm.8B /// - public static unsafe void Store(ushort* address, Vector64 source) => Store(address, source); + public static Vector64 ShiftArithmeticRounded(Vector64 value, Vector64 count) => ShiftArithmeticRounded(value, count); /// - /// void vst1_u32 (uint32_t * ptr, uint32x2_t val) - /// A32: VST1.32 { Dd }, [Rn] - /// A64: ST1 { Vt.2S }, [Xn] + /// int16x8_t vrshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VRSHL.S16 Qd, Qn, Qm + /// A64: SRSHL Vd.8H, Vn.8H, Vm.8H /// - public static unsafe void Store(uint* address, Vector64 source) => Store(address, source); + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) => ShiftArithmeticRounded(value, count); /// - /// void vst1_u64 (uint64_t * ptr, uint64x1_t val) - /// A32: VST1.64 { Dd }, [Rn] - /// A64: ST1 { Vt.1D }, [Xn] + /// int32x4_t vrshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VRSHL.S32 Qd, Qn, Qm + /// A64: SRSHL Vd.4S, Vn.4S, Vm.4S /// - public static unsafe void Store(ulong* address, Vector64 source) => Store(address, source); + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) => ShiftArithmeticRounded(value, count); /// - /// void vst1q_u8 (uint8_t * ptr, uint8x16_t val) - /// A32: VST1.8 { Dd, Dd+1 }, [Rn] - /// A64: ST1 { Vt.16B }, [Xn] + /// int64x2_t vrshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VRSHL.S64 Qd, Qn, Qm + /// A64: SRSHL Vd.2D, Vn.2D, Vm.2D /// - public static unsafe void Store(byte* address, Vector128 source) => Store(address, source); + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) => ShiftArithmeticRounded(value, count); + + /// + /// int8x16_t vrshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VRSHL.S8 Qd, Qn, Qm + /// A64: SRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftArithmeticRounded(Vector128 value, Vector128 count) => ShiftArithmeticRounded(value, count); + + /// + /// int16x4_t vqrshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VQRSHL.S16 Dd, Dn, Dm + /// A64: SQRSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftArithmeticRoundedSaturate(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int32x2_t vqrshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VQRSHL.S32 Dd, Dn, Dm + /// A64: SQRSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftArithmeticRoundedSaturate(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int8x8_t vqrshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VQRSHL.S8 Dd, Dn, Dm + /// A64: SQRSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftArithmeticRoundedSaturate(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int16x8_t vqrshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VQRSHL.S16 Qd, Qn, Qm + /// A64: SQRSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int32x4_t vqrshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VQRSHL.S32 Qd, Qn, Qm + /// A64: SQRSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int64x2_t vqrshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VQRSHL.S64 Qd, Qn, Qm + /// A64: SQRSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int8x16_t vqrshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VQRSHL.S8 Qd, Qn, Qm + /// A64: SQRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftArithmeticRoundedSaturate(Vector128 value, Vector128 count) => ShiftArithmeticRoundedSaturate(value, count); + + /// + /// int64x1_t vqrshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VQRSHL.S64 Dd, Dn, Dm + /// A64: SQRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticRoundedSaturateScalar(value, count); + + /// + /// int64x1_t vrshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VRSHL.S64 Dd, Dn, Dm + /// A64: SRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticRoundedScalar(Vector64 value, Vector64 count) => ShiftArithmeticRoundedScalar(value, count); + + /// + /// int16x4_t vqshl_s16 (int16x4_t a, int16x4_t b) + /// A32: VQSHL.S16 Dd, Dn, Dm + /// A64: SQSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftArithmeticSaturate(Vector64 value, Vector64 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int32x2_t vqshl_s32 (int32x2_t a, int32x2_t b) + /// A32: VQSHL.S32 Dd, Dn, Dm + /// A64: SQSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftArithmeticSaturate(Vector64 value, Vector64 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int8x8_t vqshl_s8 (int8x8_t a, int8x8_t b) + /// A32: VQSHL.S8 Dd, Dn, Dm + /// A64: SQSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftArithmeticSaturate(Vector64 value, Vector64 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int16x8_t vqshlq_s16 (int16x8_t a, int16x8_t b) + /// A32: VQSHL.S16 Qd, Qn, Qm + /// A64: SQSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int32x4_t vqshlq_s32 (int32x4_t a, int32x4_t b) + /// A32: VQSHL.S32 Qd, Qn, Qm + /// A64: SQSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int64x2_t vqshlq_s64 (int64x2_t a, int64x2_t b) + /// A32: VQSHL.S64 Qd, Qn, Qm + /// A64: SQSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int8x16_t vqshlq_s8 (int8x16_t a, int8x16_t b) + /// A32: VQSHL.S8 Qd, Qn, Qm + /// A64: SQSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftArithmeticSaturate(Vector128 value, Vector128 count) => ShiftArithmeticSaturate(value, count); + + /// + /// int64x1_t vqshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VQSHL.S64 Dd, Dn, Dm + /// A64: SQSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticSaturateScalar(Vector64 value, Vector64 count) => ShiftArithmeticSaturateScalar(value, count); + + /// + /// int64x1_t vshl_s64 (int64x1_t a, int64x1_t b) + /// A32: VSHL.S64 Dd, Dn, Dm + /// A64: SSHL Dd, Dn, Dm + /// + public static Vector64 ShiftArithmeticScalar(Vector64 value, Vector64 count) => ShiftArithmeticScalar(value, count); + + /// + /// uint8x8_t vshl_n_u8 (uint8x8_t a, const int n) + /// A32: VSHL.I8 Dd, Dm, #n + /// A64: SHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// int16x4_t vshl_n_s16 (int16x4_t a, const int n) + /// A32: VSHL.I16 Dd, Dm, #n + /// A64: SHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// int32x2_t vshl_n_s32 (int32x2_t a, const int n) + /// A32: VSHL.I32 Dd, Dm, #n + /// A64: SHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// int8x8_t vshl_n_s8 (int8x8_t a, const int n) + /// A32: VSHL.I8 Dd, Dm, #n + /// A64: SHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint16x4_t vshl_n_u16 (uint16x4_t a, const int n) + /// A32: VSHL.I16 Dd, Dm, #n + /// A64: SHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint32x2_t vshl_n_u32 (uint32x2_t a, const int n) + /// A32: VSHL.I32 Dd, Dm, #n + /// A64: SHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogical(Vector64 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint8x16_t vshlq_n_u8 (uint8x16_t a, const int n) + /// A32: VSHL.I8 Qd, Qm, #n + /// A64: SHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// int16x8_t vshlq_n_s16 (int16x8_t a, const int n) + /// A32: VSHL.I16 Qd, Qm, #n + /// A64: SHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// int64x2_t vshlq_n_s64 (int64x2_t a, const int n) + /// A32: VSHL.I64 Qd, Qm, #n + /// A64: SHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// int8x16_t vshlq_n_s8 (int8x16_t a, const int n) + /// A32: VSHL.I8 Qd, Qm, #n + /// A64: SHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint16x8_t vshlq_n_u16 (uint16x8_t a, const int n) + /// A32: VSHL.I16 Qd, Qm, #n + /// A64: SHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint32x4_t vshlq_n_u32 (uint32x4_t a, const int n) + /// A32: VSHL.I32 Qd, Qm, #n + /// A64: SHL Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint64x2_t vshlq_n_u64 (uint64x2_t a, const int n) + /// A32: VSHL.I64 Qd, Qm, #n + /// A64: SHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogical(Vector128 value, byte count) => ShiftLeftLogical(value, count); + + /// + /// uint8x8_t vqshl_n_u8 (uint8x8_t a, const int n) + /// A32: VQSHL.U8 Dd, Dm, #n + /// A64: UQSHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int16x4_t vqshl_n_s16 (int16x4_t a, const int n) + /// A32: VQSHL.S16 Dd, Dm, #n + /// A64: SQSHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int32x2_t vqshl_n_s32 (int32x2_t a, const int n) + /// A32: VQSHL.S32 Dd, Dm, #n + /// A64: SQSHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int8x8_t vqshl_n_s8 (int8x8_t a, const int n) + /// A32: VQSHL.S8 Dd, Dm, #n + /// A64: SQSHL Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// uint16x4_t vqshl_n_u16 (uint16x4_t a, const int n) + /// A32: VQSHL.U16 Dd, Dm, #n + /// A64: UQSHL Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// uint32x2_t vqshl_n_u32 (uint32x2_t a, const int n) + /// A32: VQSHL.U32 Dd, Dm, #n + /// A64: UQSHL Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalSaturate(Vector64 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// uint8x16_t vqshlq_n_u8 (uint8x16_t a, const int n) + /// A32: VQSHL.U8 Qd, Qm, #n + /// A64: UQSHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int16x8_t vqshlq_n_s16 (int16x8_t a, const int n) + /// A32: VQSHL.S16 Qd, Qm, #n + /// A64: SQSHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int32x4_t vqshlq_n_s32 (int32x4_t a, const int n) + /// A32: VQSHL.S32 Qd, Qm, #n + /// A64: SQSHL Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int64x2_t vqshlq_n_s64 (int64x2_t a, const int n) + /// A32: VQSHL.S64 Qd, Qm, #n + /// A64: SQSHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int8x16_t vqshlq_n_s8 (int8x16_t a, const int n) + /// A32: VQSHL.S8 Qd, Qm, #n + /// A64: SQSHL Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// uint16x8_t vqshlq_n_u16 (uint16x8_t a, const int n) + /// A32: VQSHL.U16 Qd, Qm, #n + /// A64: UQSHL Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// uint32x4_t vqshlq_n_u32 (uint32x4_t a, const int n) + /// A32: VQSHL.U32 Qd, Qm, #n + /// A64: UQSHL Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// uint64x2_t vqshlq_n_u64 (uint64x2_t a, const int n) + /// A32: VQSHL.U64 Qd, Qm, #n + /// A64: UQSHL Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalSaturate(Vector128 value, byte count) => ShiftLeftLogicalSaturate(value, count); + + /// + /// int64x1_t vqshl_n_s64 (int64x1_t a, const int n) + /// A32: VQSHL.S64 Dd, Dm, #n + /// A64: SQSHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// uint64x1_t vqshl_n_u64 (uint64x1_t a, const int n) + /// A32: VQSHL.U64 Dd, Dm, #n + /// A64: UQSHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateScalar(value, count); + + /// + /// uint16x4_t vqshlu_n_s16 (int16x4_t a, const int n) + /// A32: VQSHLU.S16 Dd, Dm, #n + /// A64: SQSHLU Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsigned(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint32x2_t vqshlu_n_s32 (int32x2_t a, const int n) + /// A32: VQSHLU.S32 Dd, Dm, #n + /// A64: SQSHLU Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsigned(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint8x8_t vqshlu_n_s8 (int8x8_t a, const int n) + /// A32: VQSHLU.S8 Dd, Dm, #n + /// A64: SQSHLU Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsigned(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint16x8_t vqshluq_n_s16 (int16x8_t a, const int n) + /// A32: VQSHLU.S16 Qd, Qm, #n + /// A64: SQSHLU Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint32x4_t vqshluq_n_s32 (int32x4_t a, const int n) + /// A32: VQSHLU.S32 Qd, Qm, #n + /// A64: SQSHLU Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint64x2_t vqshluq_n_s64 (int64x2_t a, const int n) + /// A32: VQSHLU.S64 Qd, Qm, #n + /// A64: SQSHLU Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint8x16_t vqshluq_n_s8 (int8x16_t a, const int n) + /// A32: VQSHLU.S8 Qd, Qm, #n + /// A64: SQSHLU Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalSaturateUnsigned(Vector128 value, byte count) => ShiftLeftLogicalSaturateUnsigned(value, count); + + /// + /// uint64x1_t vqshlu_n_s64 (int64x1_t a, const int n) + /// A32: VQSHLU.S64 Dd, Dm, #n + /// A64: SQSHLU Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalSaturateUnsignedScalar(Vector64 value, byte count) => ShiftLeftLogicalSaturateUnsignedScalar(value, count); + + /// + /// int64x1_t vshl_n_s64 (int64x1_t a, const int n) + /// A32: VSHL.I64 Dd, Dm, #n + /// A64: SHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalScalar(Vector64 value, byte count) => ShiftLeftLogicalScalar(value, count); + + /// + /// uint64x1_t vshl_n_u64 (uint64x1_t a, const int n) + /// A32: VSHL.I64 Dd, Dm, #n + /// A64: SHL Dd, Dn, #n + /// + public static Vector64 ShiftLeftLogicalScalar(Vector64 value, byte count) => ShiftLeftLogicalScalar(value, count); + + /// + /// uint16x8_t vshll_n_u8 (uint8x8_t a, const int n) + /// A32: VSHLL.U8 Qd, Dm, #n + /// A64: USHLL Vd.8H, Vn.8B, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) => ShiftLeftLogicalWideningLower(value, count); + + /// + /// int32x4_t vshll_n_s16 (int16x4_t a, const int n) + /// A32: VSHLL.S16 Qd, Dm, #n + /// A64: SSHLL Vd.4S, Vn.4H, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) => ShiftLeftLogicalWideningLower(value, count); + + /// + /// int64x2_t vshll_n_s32 (int32x2_t a, const int n) + /// A32: VSHLL.S32 Qd, Dm, #n + /// A64: SSHLL Vd.2D, Vn.2S, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) => ShiftLeftLogicalWideningLower(value, count); + + /// + /// int16x8_t vshll_n_s8 (int8x8_t a, const int n) + /// A32: VSHLL.S8 Qd, Dm, #n + /// A64: SSHLL Vd.8H, Vn.8B, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) => ShiftLeftLogicalWideningLower(value, count); + + /// + /// uint32x4_t vshll_n_u16 (uint16x4_t a, const int n) + /// A32: VSHLL.U16 Qd, Dm, #n + /// A64: USHLL Vd.4S, Vn.4H, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) => ShiftLeftLogicalWideningLower(value, count); + + /// + /// uint64x2_t vshll_n_u32 (uint32x2_t a, const int n) + /// A32: VSHLL.U32 Qd, Dm, #n + /// A64: USHLL Vd.2D, Vn.2S, #n + /// + public static Vector128 ShiftLeftLogicalWideningLower(Vector64 value, byte count) => ShiftLeftLogicalWideningLower(value, count); + + /// + /// uint16x8_t vshll_high_n_u8 (uint8x16_t a, const int n) + /// A32: VSHLL.U8 Qd, Dm+1, #n + /// A64: USHLL2 Vd.8H, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) => ShiftLeftLogicalWideningUpper(value, count); + + /// + /// int32x4_t vshll_high_n_s16 (int16x8_t a, const int n) + /// A32: VSHLL.S16 Qd, Dm+1, #n + /// A64: SSHLL2 Vd.4S, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) => ShiftLeftLogicalWideningUpper(value, count); + + /// + /// int64x2_t vshll_high_n_s32 (int32x4_t a, const int n) + /// A32: VSHLL.S32 Qd, Dm+1, #n + /// A64: SSHLL2 Vd.2D, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) => ShiftLeftLogicalWideningUpper(value, count); + + /// + /// int16x8_t vshll_high_n_s8 (int8x16_t a, const int n) + /// A32: VSHLL.S8 Qd, Dm+1, #n + /// A64: SSHLL2 Vd.8H, Vn.16B, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) => ShiftLeftLogicalWideningUpper(value, count); + + /// + /// uint32x4_t vshll_high_n_u16 (uint16x8_t a, const int n) + /// A32: VSHLL.U16 Qd, Dm+1, #n + /// A64: USHLL2 Vd.4S, Vn.8H, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) => ShiftLeftLogicalWideningUpper(value, count); + + /// + /// uint64x2_t vshll_high_n_u32 (uint32x4_t a, const int n) + /// A32: VSHLL.U32 Qd, Dm+1, #n + /// A64: USHLL2 Vd.2D, Vn.4S, #n + /// + public static Vector128 ShiftLeftLogicalWideningUpper(Vector128 value, byte count) => ShiftLeftLogicalWideningUpper(value, count); + + /// + /// uint8x8_t vshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VSHL.U8 Dd, Dn, Dm + /// A64: USHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) => ShiftLogical(value, count); + + /// + /// uint16x4_t vshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VSHL.U16 Dd, Dn, Dm + /// A64: USHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) => ShiftLogical(value, count); + + /// + /// uint32x2_t vshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VSHL.U32 Dd, Dn, Dm + /// A64: USHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) => ShiftLogical(value, count); + + /// + /// uint8x8_t vshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VSHL.U8 Dd, Dn, Dm + /// A64: USHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) => ShiftLogical(value, count); + + /// + /// uint16x4_t vshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VSHL.U16 Dd, Dn, Dm + /// A64: USHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) => ShiftLogical(value, count); + + /// + /// uint32x2_t vshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VSHL.U32 Dd, Dn, Dm + /// A64: USHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogical(Vector64 value, Vector64 count) => ShiftLogical(value, count); + + /// + /// uint8x16_t vshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VSHL.U8 Qd, Qn, Qm + /// A64: USHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint16x8_t vshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VSHL.U16 Qd, Qn, Qm + /// A64: USHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint32x4_t vshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VSHL.U32 Qd, Qn, Qm + /// A64: USHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint64x2_t vshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VSHL.U64 Qd, Qn, Qm + /// A64: USHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint8x16_t vshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VSHL.U8 Qd, Qn, Qm + /// A64: USHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint16x8_t vshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VSHL.U16 Qd, Qn, Qm + /// A64: USHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint32x4_t vshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VSHL.U32 Qd, Qn, Qm + /// A64: USHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint64x2_t vshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VSHL.U64 Qd, Qn, Qm + /// A64: USHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogical(Vector128 value, Vector128 count) => ShiftLogical(value, count); + + /// + /// uint8x8_t vrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VRSHL.U8 Dd, Dn, Dm + /// A64: URSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) => ShiftLogicalRounded(value, count); + + /// + /// uint16x4_t vrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VRSHL.U16 Dd, Dn, Dm + /// A64: URSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) => ShiftLogicalRounded(value, count); + + /// + /// uint32x2_t vrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VRSHL.U32 Dd, Dn, Dm + /// A64: URSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) => ShiftLogicalRounded(value, count); + + /// + /// uint8x8_t vrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VRSHL.U8 Dd, Dn, Dm + /// A64: URSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) => ShiftLogicalRounded(value, count); + + /// + /// uint16x4_t vrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VRSHL.U16 Dd, Dn, Dm + /// A64: URSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) => ShiftLogicalRounded(value, count); + + /// + /// uint32x2_t vrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VRSHL.U32 Dd, Dn, Dm + /// A64: URSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRounded(Vector64 value, Vector64 count) => ShiftLogicalRounded(value, count); + + /// + /// uint8x16_t vrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VRSHL.U8 Qd, Qn, Qm + /// A64: URSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint16x8_t vrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VRSHL.U16 Qd, Qn, Qm + /// A64: URSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint32x4_t vrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VRSHL.U32 Qd, Qn, Qm + /// A64: URSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint64x2_t vrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VRSHL.U64 Qd, Qn, Qm + /// A64: URSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint8x16_t vrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VRSHL.U8 Qd, Qn, Qm + /// A64: URSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint16x8_t vrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VRSHL.U16 Qd, Qn, Qm + /// A64: URSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint32x4_t vrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VRSHL.U32 Qd, Qn, Qm + /// A64: URSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint64x2_t vrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VRSHL.U64 Qd, Qn, Qm + /// A64: URSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRounded(Vector128 value, Vector128 count) => ShiftLogicalRounded(value, count); + + /// + /// uint8x8_t vqrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQRSHL.U8 Dd, Dn, Dm + /// A64: UQRSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint16x4_t vqrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQRSHL.U16 Dd, Dn, Dm + /// A64: UQRSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint32x2_t vqrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQRSHL.U32 Dd, Dn, Dm + /// A64: UQRSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint8x8_t vqrshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQRSHL.U8 Dd, Dn, Dm + /// A64: UQRSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint16x4_t vqrshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQRSHL.U16 Dd, Dn, Dm + /// A64: UQRSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint32x2_t vqrshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQRSHL.U32 Dd, Dn, Dm + /// A64: UQRSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalRoundedSaturate(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint8x16_t vqrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQRSHL.U8 Qd, Qn, Qm + /// A64: UQRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint16x8_t vqrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQRSHL.U16 Qd, Qn, Qm + /// A64: UQRSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint32x4_t vqrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQRSHL.U32 Qd, Qn, Qm + /// A64: UQRSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint64x2_t vqrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQRSHL.U64 Qd, Qn, Qm + /// A64: UQRSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint8x16_t vqrshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQRSHL.U8 Qd, Qn, Qm + /// A64: UQRSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint16x8_t vqrshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQRSHL.U16 Qd, Qn, Qm + /// A64: UQRSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint32x4_t vqrshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQRSHL.U32 Qd, Qn, Qm + /// A64: UQRSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint64x2_t vqrshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQRSHL.U64 Qd, Qn, Qm + /// A64: UQRSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalRoundedSaturate(Vector128 value, Vector128 count) => ShiftLogicalRoundedSaturate(value, count); + + /// + /// uint64x1_t vqrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQRSHL.U64 Dd, Dn, Dm + /// A64: UQRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint64x1_t vqrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQRSHL.U64 Dd, Dn, Dm + /// A64: UQRSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedSaturateScalar(value, count); + + /// + /// uint64x1_t vrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VRSHL.U64 Dd, Dn, Dm + /// A64: URSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedScalar(value, count); + + /// + /// uint64x1_t vrshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VRSHL.U64 Dd, Dn, Dm + /// A64: URSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalRoundedScalar(Vector64 value, Vector64 count) => ShiftLogicalRoundedScalar(value, count); + + /// + /// uint8x8_t vqshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQSHL.U8 Dd, Dn, Dm + /// A64: UQSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint16x4_t vqshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQSHL.U16 Dd, Dn, Dm + /// A64: UQSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint32x2_t vqshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQSHL.U32 Dd, Dn, Dm + /// A64: UQSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint8x8_t vqshl_u8 (uint8x8_t a, int8x8_t b) + /// A32: VQSHL.U8 Dd, Dn, Dm + /// A64: UQSHL Vd.8B, Vn.8B, Vm.8B + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint16x4_t vqshl_u16 (uint16x4_t a, int16x4_t b) + /// A32: VQSHL.U16 Dd, Dn, Dm + /// A64: UQSHL Vd.4H, Vn.4H, Vm.4H + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint32x2_t vqshl_u32 (uint32x2_t a, int32x2_t b) + /// A32: VQSHL.U32 Dd, Dn, Dm + /// A64: UQSHL Vd.2S, Vn.2S, Vm.2S + /// + public static Vector64 ShiftLogicalSaturate(Vector64 value, Vector64 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint8x16_t vqshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQSHL.U8 Qd, Qn, Qm + /// A64: UQSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint16x8_t vqshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQSHL.U16 Qd, Qn, Qm + /// A64: UQSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint32x4_t vqshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQSHL.U32 Qd, Qn, Qm + /// A64: UQSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint64x2_t vqshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQSHL.U64 Qd, Qn, Qm + /// A64: UQSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint8x16_t vqshlq_u8 (uint8x16_t a, int8x16_t b) + /// A32: VQSHL.U8 Qd, Qn, Qm + /// A64: UQSHL Vd.16B, Vn.16B, Vm.16B + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint16x8_t vqshlq_u16 (uint16x8_t a, int16x8_t b) + /// A32: VQSHL.U16 Qd, Qn, Qm + /// A64: UQSHL Vd.8H, Vn.8H, Vm.8H + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint32x4_t vqshlq_u32 (uint32x4_t a, int32x4_t b) + /// A32: VQSHL.U32 Qd, Qn, Qm + /// A64: UQSHL Vd.4S, Vn.4S, Vm.4S + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint64x2_t vqshlq_u64 (uint64x2_t a, int64x2_t b) + /// A32: VQSHL.U64 Qd, Qn, Qm + /// A64: UQSHL Vd.2D, Vn.2D, Vm.2D + /// + public static Vector128 ShiftLogicalSaturate(Vector128 value, Vector128 count) => ShiftLogicalSaturate(value, count); + + /// + /// uint64x1_t vqshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQSHL.U64 Dd, Dn, Dm + /// A64: UQSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint64x1_t vqshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VQSHL.U64 Dd, Dn, Dm + /// A64: UQSHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalSaturateScalar(Vector64 value, Vector64 count) => ShiftLogicalSaturateScalar(value, count); + + /// + /// uint64x1_t vshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VSHL.U64 Dd, Dn, Dm + /// A64: USHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalScalar(Vector64 value, Vector64 count) => ShiftLogicalScalar(value, count); + + /// + /// uint64x1_t vshl_u64 (uint64x1_t a, int64x1_t b) + /// A32: VSHL.U64 Dd, Dn, Dm + /// A64: USHL Dd, Dn, Dm + /// + public static Vector64 ShiftLogicalScalar(Vector64 value, Vector64 count) => ShiftLogicalScalar(value, count); + + /// + /// int16x4_t vshr_n_s16 (int16x4_t a, const int n) + /// A32: VSHR.S16 Dd, Dm, #n + /// A64: SSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmetic(Vector64 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int32x2_t vshr_n_s32 (int32x2_t a, const int n) + /// A32: VSHR.S32 Dd, Dm, #n + /// A64: SSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmetic(Vector64 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int8x8_t vshr_n_s8 (int8x8_t a, const int n) + /// A32: VSHR.S8 Dd, Dm, #n + /// A64: SSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmetic(Vector64 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int16x8_t vshrq_n_s16 (int16x8_t a, const int n) + /// A32: VSHR.S16 Qd, Qm, #n + /// A64: SSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int32x4_t vshrq_n_s32 (int32x4_t a, const int n) + /// A32: VSHR.S32 Qd, Qm, #n + /// A64: SSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int64x2_t vshrq_n_s64 (int64x2_t a, const int n) + /// A32: VSHR.S64 Qd, Qm, #n + /// A64: SSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int8x16_t vshrq_n_s8 (int8x16_t a, const int n) + /// A32: VSHR.S8 Qd, Qm, #n + /// A64: SSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmetic(Vector128 value, byte count) => ShiftRightArithmetic(value, count); + + /// + /// int16x4_t vsra_n_s16 (int16x4_t a, int16x4_t b, const int n) + /// A32: VSRA.S16 Dd, Dm, #n + /// A64: SSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmeticAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int32x2_t vsra_n_s32 (int32x2_t a, int32x2_t b, const int n) + /// A32: VSRA.S32 Dd, Dm, #n + /// A64: SSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmeticAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int8x8_t vsra_n_s8 (int8x8_t a, int8x8_t b, const int n) + /// A32: VSRA.S8 Dd, Dm, #n + /// A64: SSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmeticAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int16x8_t vsraq_n_s16 (int16x8_t a, int16x8_t b, const int n) + /// A32: VSRA.S16 Qd, Qm, #n + /// A64: SSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int32x4_t vsraq_n_s32 (int32x4_t a, int32x4_t b, const int n) + /// A32: VSRA.S32 Qd, Qm, #n + /// A64: SSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int64x2_t vsraq_n_s64 (int64x2_t a, int64x2_t b, const int n) + /// A32: VSRA.S64 Qd, Qm, #n + /// A64: SSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int8x16_t vsraq_n_s8 (int8x16_t a, int8x16_t b, const int n) + /// A32: VSRA.S8 Qd, Qm, #n + /// A64: SSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmeticAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticAdd(addend, value, count); + + /// + /// int64x1_t vsra_n_s64 (int64x1_t a, int64x1_t b, const int n) + /// A32: VSRA.S64 Dd, Dm, #n + /// A64: SSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticAddScalar(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticAddScalar(addend, value, count); + + /// + /// int16x4_t vqshrn_n_s32 (int32x4_t a, const int n) + /// A32: VQSHRN.S32 Dd, Qm, #n + /// A64: SQSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateLower(value, count); + + /// + /// int32x2_t vqshrn_n_s64 (int64x2_t a, const int n) + /// A32: VQSHRN.S64 Dd, Qm, #n + /// A64: SQSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateLower(value, count); + + /// + /// int8x8_t vqshrn_n_s16 (int16x8_t a, const int n) + /// A32: VQSHRN.S16 Dd, Qm, #n + /// A64: SQSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateLower(value, count); + + /// + /// uint8x8_t vqshrun_n_s16 (int16x8_t a, const int n) + /// A32: VQSHRUN.S16 Dd, Qm, #n + /// A64: SQSHRUN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedLower(value, count); + + /// + /// uint16x4_t vqshrun_n_s32 (int32x4_t a, const int n) + /// A32: VQSHRUN.S32 Dd, Qm, #n + /// A64: SQSHRUN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedLower(value, count); + + /// + /// uint32x2_t vqshrun_n_s64 (int64x2_t a, const int n) + /// A32: VQSHRUN.S64 Dd, Qm, #n + /// A64: SQSHRUN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedLower(value, count); + + /// + /// uint8x16_t vqshrun_high_n_s16 (uint8x8_t r, int16x8_t a, const int n) + /// A32: VQSHRUN.S16 Dd+1, Dn, #n + /// A64: SQSHRUN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedUpper(lower, value, count); + + /// + /// uint16x8_t vqshrun_high_n_s32 (uint16x4_t r, int32x4_t a, const int n) + /// A32: VQSHRUN.S32 Dd+1, Dn, #n + /// A64: SQSHRUN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedUpper(lower, value, count); + + /// + /// uint32x4_t vqshrun_high_n_s64 (uint32x2_t r, int64x2_t a, const int n) + /// A32: VQSHRUN.S64 Dd+1, Dn, #n + /// A64: SQSHRUN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUnsignedUpper(lower, value, count); + + /// + /// int16x8_t vqshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VQSHRN.S32 Dd+1, Qm, #n + /// A64: SQSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUpper(lower, value, count); + + /// + /// int32x4_t vqshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VQSHRN.S64 Dd+1, Qm, #n + /// A64: SQSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUpper(lower, value, count); + + /// + /// int8x16_t vqshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VQSHRN.S16 Dd+1, Qm, #n + /// A64: SQSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticNarrowingSaturateUpper(lower, value, count); + + /// + /// int16x4_t vrshr_n_s16 (int16x4_t a, const int n) + /// A32: VRSHR.S16 Dd, Dm, #n + /// A64: SRSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmeticRounded(Vector64 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int32x2_t vrshr_n_s32 (int32x2_t a, const int n) + /// A32: VRSHR.S32 Dd, Dm, #n + /// A64: SRSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmeticRounded(Vector64 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int8x8_t vrshr_n_s8 (int8x8_t a, const int n) + /// A32: VRSHR.S8 Dd, Dm, #n + /// A64: SRSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmeticRounded(Vector64 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int16x8_t vrshrq_n_s16 (int16x8_t a, const int n) + /// A32: VRSHR.S16 Qd, Qm, #n + /// A64: SRSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int32x4_t vrshrq_n_s32 (int32x4_t a, const int n) + /// A32: VRSHR.S32 Qd, Qm, #n + /// A64: SRSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int64x2_t vrshrq_n_s64 (int64x2_t a, const int n) + /// A32: VRSHR.S64 Qd, Qm, #n + /// A64: SRSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int8x16_t vrshrq_n_s8 (int8x16_t a, const int n) + /// A32: VRSHR.S8 Qd, Qm, #n + /// A64: SRSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmeticRounded(Vector128 value, byte count) => ShiftRightArithmeticRounded(value, count); + + /// + /// int16x4_t vrsra_n_s16 (int16x4_t a, int16x4_t b, const int n) + /// A32: VRSRA.S16 Dd, Dm, #n + /// A64: SRSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int32x2_t vrsra_n_s32 (int32x2_t a, int32x2_t b, const int n) + /// A32: VRSRA.S32 Dd, Dm, #n + /// A64: SRSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int8x8_t vrsra_n_s8 (int8x8_t a, int8x8_t b, const int n) + /// A32: VRSRA.S8 Dd, Dm, #n + /// A64: SRSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int16x8_t vrsraq_n_s16 (int16x8_t a, int16x8_t b, const int n) + /// A32: VRSRA.S16 Qd, Qm, #n + /// A64: SRSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int32x4_t vrsraq_n_s32 (int32x4_t a, int32x4_t b, const int n) + /// A32: VRSRA.S32 Qd, Qm, #n + /// A64: SRSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int64x2_t vrsraq_n_s64 (int64x2_t a, int64x2_t b, const int n) + /// A32: VRSRA.S64 Qd, Qm, #n + /// A64: SRSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int8x16_t vrsraq_n_s8 (int8x16_t a, int8x16_t b, const int n) + /// A32: VRSRA.S8 Qd, Qm, #n + /// A64: SRSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightArithmeticRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightArithmeticRoundedAdd(addend, value, count); + + /// + /// int64x1_t vrsra_n_s64 (int64x1_t a, int64x1_t b, const int n) + /// A32: VRSRA.S64 Dd, Dm, #n + /// A64: SRSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedAddScalar(Vector64 addend, Vector64 value, byte count) => ShiftRightArithmeticRoundedAddScalar(addend, value, count); + + /// + /// int16x4_t vqrshrn_n_s32 (int32x4_t a, const int n) + /// A32: VQRSHRN.S32 Dd, Qm, #n + /// A64: SQRSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateLower(value, count); + + /// + /// int32x2_t vqrshrn_n_s64 (int64x2_t a, const int n) + /// A32: VQRSHRN.S64 Dd, Qm, #n + /// A64: SQRSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateLower(value, count); + + /// + /// int8x8_t vqrshrn_n_s16 (int16x8_t a, const int n) + /// A32: VQRSHRN.S16 Dd, Qm, #n + /// A64: SQRSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateLower(value, count); + + /// + /// uint8x8_t vqrshrun_n_s16 (int16x8_t a, const int n) + /// A32: VQRSHRUN.S16 Dd, Qm, #n + /// A64: SQRSHRUN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(value, count); + + /// + /// uint16x4_t vqrshrun_n_s32 (int32x4_t a, const int n) + /// A32: VQRSHRUN.S32 Dd, Qm, #n + /// A64: SQRSHRUN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(value, count); + + /// + /// uint32x2_t vqrshrun_n_s64 (int64x2_t a, const int n) + /// A32: VQRSHRUN.S64 Dd, Qm, #n + /// A64: SQRSHRUN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(value, count); + + /// + /// uint8x16_t vqrshrun_high_n_s16 (uint8x8_t r, int16x8_t a, const int n) + /// A32: VQRSHRUN.S16 Dd+1, Dn, #n + /// A64: SQRSHRUN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(lower, value, count); + + /// + /// uint16x8_t vqrshrun_high_n_s32 (uint16x4_t r, int32x4_t a, const int n) + /// A32: VQRSHRUN.S32 Dd+1, Dn, #n + /// A64: SQRSHRUN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(lower, value, count); + + /// + /// uint32x4_t vqrshrun_high_n_s64 (uint32x2_t r, int64x2_t a, const int n) + /// A32: VQRSHRUN.S64 Dd+1, Dn, #n + /// A64: SQRSHRUN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(lower, value, count); + + /// + /// int16x8_t vqrshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VQRSHRN.S32 Dd+1, Dn, #n + /// A64: SQRSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// int32x4_t vqrshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VQRSHRN.S64 Dd+1, Dn, #n + /// A64: SQRSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// int8x16_t vqrshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VQRSHRN.S16 Dd+1, Dn, #n + /// A64: SQRSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightArithmeticRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// int64x1_t vrshr_n_s64 (int64x1_t a, const int n) + /// A32: VRSHR.S64 Dd, Dm, #n + /// A64: SRSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticRoundedScalar(Vector64 value, byte count) => ShiftRightArithmeticRoundedScalar(value, count); + + /// + /// int64x1_t vshr_n_s64 (int64x1_t a, const int n) + /// A32: VSHR.S64 Dd, Dm, #n + /// A64: SSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightArithmeticScalar(Vector64 value, byte count) => ShiftRightArithmeticScalar(value, count); + + /// + /// uint8x8_t vshr_n_u8 (uint8x8_t a, const int n) + /// A32: VSHR.U8 Dd, Dm, #n + /// A64: USHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint16x4_t vshr_n_u16 (uint16x4_t a, const int n) + /// A32: VSHR.U16 Dd, Dm, #n + /// A64: USHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint32x2_t vshr_n_u32 (uint32x2_t a, const int n) + /// A32: VSHR.U32 Dd, Dm, #n + /// A64: USHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint8x8_t vshr_n_u8 (uint8x8_t a, const int n) + /// A32: VSHR.U8 Dd, Dm, #n + /// A64: USHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint16x4_t vshr_n_u16 (uint16x4_t a, const int n) + /// A32: VSHR.U16 Dd, Dm, #n + /// A64: USHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint32x2_t vshr_n_u32 (uint32x2_t a, const int n) + /// A32: VSHR.U32 Dd, Dm, #n + /// A64: USHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogical(Vector64 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint8x16_t vshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VSHR.U8 Qd, Qm, #n + /// A64: USHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint16x8_t vshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VSHR.U16 Qd, Qm, #n + /// A64: USHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint32x4_t vshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VSHR.U32 Qd, Qm, #n + /// A64: USHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint64x2_t vshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VSHR.U64 Qd, Qm, #n + /// A64: USHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint8x16_t vshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VSHR.U8 Qd, Qm, #n + /// A64: USHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint16x8_t vshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VSHR.U16 Qd, Qm, #n + /// A64: USHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint32x4_t vshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VSHR.U32 Qd, Qm, #n + /// A64: USHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint64x2_t vshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VSHR.U64 Qd, Qm, #n + /// A64: USHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogical(Vector128 value, byte count) => ShiftRightLogical(value, count); + + /// + /// uint8x8_t vsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VSRA.U8 Dd, Dm, #n + /// A64: USRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint16x4_t vsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VSRA.U16 Dd, Dm, #n + /// A64: USRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint32x2_t vsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VSRA.U32 Dd, Dm, #n + /// A64: USRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint8x8_t vsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VSRA.U8 Dd, Dm, #n + /// A64: USRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint16x4_t vsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VSRA.U16 Dd, Dm, #n + /// A64: USRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint32x2_t vsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VSRA.U32 Dd, Dm, #n + /// A64: USRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint8x16_t vsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VSRA.U8 Qd, Qm, #n + /// A64: USRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint16x8_t vsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VSRA.U16 Qd, Qm, #n + /// A64: USRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint32x4_t vsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VSRA.U32 Qd, Qm, #n + /// A64: USRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint64x2_t vsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VSRA.U64 Qd, Qm, #n + /// A64: USRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint8x16_t vsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VSRA.U8 Qd, Qm, #n + /// A64: USRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint16x8_t vsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VSRA.U16 Qd, Qm, #n + /// A64: USRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint32x4_t vsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VSRA.U32 Qd, Qm, #n + /// A64: USRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint64x2_t vsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VSRA.U64 Qd, Qm, #n + /// A64: USRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalAdd(addend, value, count); + + /// + /// uint64x1_t vsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VSRA.U64 Dd, Dm, #n + /// A64: USRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAddScalar(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAddScalar(addend, value, count); + + /// + /// uint64x1_t vsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VSRA.U64 Dd, Dm, #n + /// A64: USRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalAddScalar(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalAddScalar(addend, value, count); + + /// + /// uint8x8_t vshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VSHRN.I16 Dd, Qm, #n + /// A64: SHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingLower(value, count); + + /// + /// int16x4_t vshrn_n_s32 (int32x4_t a, const int n) + /// A32: VSHRN.I32 Dd, Qm, #n + /// A64: SHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingLower(value, count); + + /// + /// int32x2_t vshrn_n_s64 (int64x2_t a, const int n) + /// A32: VSHRN.I64 Dd, Qm, #n + /// A64: SHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingLower(value, count); + + /// + /// int8x8_t vshrn_n_s16 (int16x8_t a, const int n) + /// A32: VSHRN.I16 Dd, Qm, #n + /// A64: SHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingLower(value, count); + + /// + /// uint16x4_t vshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VSHRN.I32 Dd, Qm, #n + /// A64: SHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingLower(value, count); + + /// + /// uint32x2_t vshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VSHRN.I64 Dd, Qm, #n + /// A64: SHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingLower(value, count); + + /// + /// uint8x8_t vqshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd, Qm, #n + /// A64: UQSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateLower(value, count); + + /// + /// uint16x4_t vqshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd, Qm, #n + /// A64: UQSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateLower(value, count); + + /// + /// uint32x2_t vqshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd, Qm, #n + /// A64: UQSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateLower(value, count); + + /// + /// uint8x8_t vqshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd, Qm, #n + /// A64: UQSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateLower(value, count); + + /// + /// uint16x4_t vqshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd, Qm, #n + /// A64: UQSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateLower(value, count); + + /// + /// uint32x2_t vqshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd, Qm, #n + /// A64: UQSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateLower(value, count); + + /// + /// uint8x16_t vqshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateUpper(lower, value, count); + + /// + /// uint16x8_t vqshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateUpper(lower, value, count); + + /// + /// uint32x4_t vqshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateUpper(lower, value, count); + + /// + /// uint8x16_t vqshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQSHRN.U16 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateUpper(lower, value, count); + + /// + /// uint16x8_t vqshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQSHRN.U32 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateUpper(lower, value, count); + + /// + /// uint32x4_t vqshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQSHRN.U64 Dd+1, Qm, #n + /// A64: UQSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingSaturateUpper(lower, value, count); + + /// + /// uint8x16_t vshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VSHRN.I16 Dd+1, Qm, #n + /// A64: SHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingUpper(lower, value, count); + + /// + /// int16x8_t vshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VSHRN.I32 Dd+1, Qm, #n + /// A64: SHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingUpper(lower, value, count); + + /// + /// int32x4_t vshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VSHRN.I64 Dd+1, Qm, #n + /// A64: SHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingUpper(lower, value, count); + + /// + /// int8x16_t vshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VSHRN.I16 Dd+1, Qm, #n + /// A64: SHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingUpper(lower, value, count); + + /// + /// uint16x8_t vshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VSHRN.I32 Dd+1, Qm, #n + /// A64: SHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingUpper(lower, value, count); + + /// + /// uint32x4_t vshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VSHRN.I64 Dd+1, Qm, #n + /// A64: SHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalNarrowingUpper(lower, value, count); + + /// + /// uint8x8_t vrshr_n_u8 (uint8x8_t a, const int n) + /// A32: VRSHR.U8 Dd, Dm, #n + /// A64: URSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint16x4_t vrshr_n_u16 (uint16x4_t a, const int n) + /// A32: VRSHR.U16 Dd, Dm, #n + /// A64: URSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint32x2_t vrshr_n_u32 (uint32x2_t a, const int n) + /// A32: VRSHR.U32 Dd, Dm, #n + /// A64: URSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint8x8_t vrshr_n_u8 (uint8x8_t a, const int n) + /// A32: VRSHR.U8 Dd, Dm, #n + /// A64: URSHR Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint16x4_t vrshr_n_u16 (uint16x4_t a, const int n) + /// A32: VRSHR.U16 Dd, Dm, #n + /// A64: URSHR Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint32x2_t vrshr_n_u32 (uint32x2_t a, const int n) + /// A32: VRSHR.U32 Dd, Dm, #n + /// A64: URSHR Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRounded(Vector64 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint8x16_t vrshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VRSHR.U8 Qd, Qm, #n + /// A64: URSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint16x8_t vrshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VRSHR.U16 Qd, Qm, #n + /// A64: URSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint32x4_t vrshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VRSHR.U32 Qd, Qm, #n + /// A64: URSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint64x2_t vrshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VRSHR.U64 Qd, Qm, #n + /// A64: URSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint8x16_t vrshrq_n_u8 (uint8x16_t a, const int n) + /// A32: VRSHR.U8 Qd, Qm, #n + /// A64: URSHR Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint16x8_t vrshrq_n_u16 (uint16x8_t a, const int n) + /// A32: VRSHR.U16 Qd, Qm, #n + /// A64: URSHR Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint32x4_t vrshrq_n_u32 (uint32x4_t a, const int n) + /// A32: VRSHR.U32 Qd, Qm, #n + /// A64: URSHR Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint64x2_t vrshrq_n_u64 (uint64x2_t a, const int n) + /// A32: VRSHR.U64 Qd, Qm, #n + /// A64: URSHR Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRounded(Vector128 value, byte count) => ShiftRightLogicalRounded(value, count); + + /// + /// uint8x8_t vrsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VRSRA.U8 Dd, Dm, #n + /// A64: URSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint16x4_t vrsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VRSRA.U16 Dd, Dm, #n + /// A64: URSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint32x2_t vrsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VRSRA.U32 Dd, Dm, #n + /// A64: URSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint8x8_t vrsra_n_u8 (uint8x8_t a, uint8x8_t b, const int n) + /// A32: VRSRA.U8 Dd, Dm, #n + /// A64: URSRA Vd.8B, Vn.8B, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint16x4_t vrsra_n_u16 (uint16x4_t a, uint16x4_t b, const int n) + /// A32: VRSRA.U16 Dd, Dm, #n + /// A64: URSRA Vd.4H, Vn.4H, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint32x2_t vrsra_n_u32 (uint32x2_t a, uint32x2_t b, const int n) + /// A32: VRSRA.U32 Dd, Dm, #n + /// A64: URSRA Vd.2S, Vn.2S, #n + /// + public static Vector64 ShiftRightLogicalRoundedAdd(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint8x16_t vrsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VRSRA.U8 Qd, Qm, #n + /// A64: URSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint16x8_t vrsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VRSRA.U16 Qd, Qm, #n + /// A64: URSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint32x4_t vrsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VRSRA.U32 Qd, Qm, #n + /// A64: URSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint64x2_t vrsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VRSRA.U64 Qd, Qm, #n + /// A64: URSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint8x16_t vrsraq_n_u8 (uint8x16_t a, uint8x16_t b, const int n) + /// A32: VRSRA.U8 Qd, Qm, #n + /// A64: URSRA Vd.16B, Vn.16B, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint16x8_t vrsraq_n_u16 (uint16x8_t a, uint16x8_t b, const int n) + /// A32: VRSRA.U16 Qd, Qm, #n + /// A64: URSRA Vd.8H, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint32x4_t vrsraq_n_u32 (uint32x4_t a, uint32x4_t b, const int n) + /// A32: VRSRA.U32 Qd, Qm, #n + /// A64: URSRA Vd.4S, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint64x2_t vrsraq_n_u64 (uint64x2_t a, uint64x2_t b, const int n) + /// A32: VRSRA.U64 Qd, Qm, #n + /// A64: URSRA Vd.2D, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedAdd(Vector128 addend, Vector128 value, byte count) => ShiftRightLogicalRoundedAdd(addend, value, count); + + /// + /// uint64x1_t vrsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VRSRA.U64 Dd, Dm, #n + /// A64: URSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedAddScalar(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAddScalar(addend, value, count); + + /// + /// uint64x1_t vrsra_n_u64 (uint64x1_t a, uint64x1_t b, const int n) + /// A32: VRSRA.U64 Dd, Dm, #n + /// A64: URSRA Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedAddScalar(Vector64 addend, Vector64 value, byte count) => ShiftRightLogicalRoundedAddScalar(addend, value, count); + + /// + /// uint8x8_t vrshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd, Qm, #n + /// A64: RSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingLower(value, count); + + /// + /// int16x4_t vrshrn_n_s32 (int32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd, Qm, #n + /// A64: RSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingLower(value, count); + + /// + /// int32x2_t vrshrn_n_s64 (int64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd, Qm, #n + /// A64: RSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingLower(value, count); + + /// + /// int8x8_t vrshrn_n_s16 (int16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd, Qm, #n + /// A64: RSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingLower(value, count); + + /// + /// uint16x4_t vrshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd, Qm, #n + /// A64: RSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingLower(value, count); + + /// + /// uint32x2_t vrshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd, Qm, #n + /// A64: RSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingLower(value, count); + + /// + /// uint8x8_t vqrshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd, Qm, #n + /// A64: UQRSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); + + /// + /// uint16x4_t vqrshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd, Qm, #n + /// A64: UQRSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); + + /// + /// uint32x2_t vqrshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd, Qm, #n + /// A64: UQRSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); + + /// + /// uint8x8_t vqrshrn_n_u16 (uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd, Qm, #n + /// A64: UQRSHRN Vd.8B, Vn.8H, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); + + /// + /// uint16x4_t vqrshrn_n_u32 (uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd, Qm, #n + /// A64: UQRSHRN Vd.4H, Vn.4S, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); + + /// + /// uint32x2_t vqrshrn_n_u64 (uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd, Qm, #n + /// A64: UQRSHRN Vd.2S, Vn.2D, #n + /// + public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); + + /// + /// uint8x16_t vqrshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// uint16x8_t vqrshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// uint32x4_t vqrshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// uint8x16_t vqrshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VQRSHRN.U16 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// uint16x8_t vqrshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VQRSHRN.U32 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// uint32x4_t vqrshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VQRSHRN.U64 Dd+1, Dn, #n + /// A64: UQRSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); + + /// + /// uint8x16_t vrshrn_high_n_u16 (uint8x8_t r, uint16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingUpper(lower, value, count); + + /// + /// int16x8_t vrshrn_high_n_s32 (int16x4_t r, int32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingUpper(lower, value, count); + + /// + /// int32x4_t vrshrn_high_n_s64 (int32x2_t r, int64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingUpper(lower, value, count); + + /// + /// int8x16_t vrshrn_high_n_s16 (int8x8_t r, int16x8_t a, const int n) + /// A32: VRSHRN.I16 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.16B, Vn.8H, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingUpper(lower, value, count); + + /// + /// uint16x8_t vrshrn_high_n_u32 (uint16x4_t r, uint32x4_t a, const int n) + /// A32: VRSHRN.I32 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.8H, Vn.4S, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingUpper(lower, value, count); + + /// + /// uint32x4_t vrshrn_high_n_u64 (uint32x2_t r, uint64x2_t a, const int n) + /// A32: VRSHRN.I64 Dd+1, Qm, #n + /// A64: RSHRN2 Vd.4S, Vn.2D, #n + /// + public static Vector128 ShiftRightLogicalRoundedNarrowingUpper(Vector64 lower, Vector128 value, byte count) => ShiftRightLogicalRoundedNarrowingUpper(lower, value, count); + + /// + /// uint64x1_t vrshr_n_u64 (uint64x1_t a, const int n) + /// A32: VRSHR.U64 Dd, Dm, #n + /// A64: URSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedScalar(value, count); + + /// + /// uint64x1_t vrshr_n_u64 (uint64x1_t a, const int n) + /// A32: VRSHR.U64 Dd, Dm, #n + /// A64: URSHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalRoundedScalar(Vector64 value, byte count) => ShiftRightLogicalRoundedScalar(value, count); + + /// + /// uint64x1_t vshr_n_u64 (uint64x1_t a, const int n) + /// A32: VSHR.U64 Dd, Dm, #n + /// A64: USHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalScalar(Vector64 value, byte count) => ShiftRightLogicalScalar(value, count); + + /// + /// uint64x1_t vshr_n_u64 (uint64x1_t a, const int n) + /// A32: VSHR.U64 Dd, Dm, #n + /// A64: USHR Dd, Dn, #n + /// + public static Vector64 ShiftRightLogicalScalar(Vector64 value, byte count) => ShiftRightLogicalScalar(value, count); + + /// + /// int32x4_t vmovl_s16 (int16x4_t a) + /// A32: VMOVL.S16 Qd, Dm + /// A64: SXTL Vd.4S, Vn.4H + /// + public static Vector128 SignExtendWideningLower(Vector64 value) => SignExtendWideningLower(value); + + /// + /// int64x2_t vmovl_s32 (int32x2_t a) + /// A32: VMOVL.S32 Qd, Dm + /// A64: SXTL Vd.2D, Vn.2S + /// + public static Vector128 SignExtendWideningLower(Vector64 value) => SignExtendWideningLower(value); + + /// + /// int16x8_t vmovl_s8 (int8x8_t a) + /// A32: VMOVL.S8 Qd, Dm + /// A64: SXTL Vd.8H, Vn.8B + /// + public static Vector128 SignExtendWideningLower(Vector64 value) => SignExtendWideningLower(value); + + /// + /// int32x4_t vmovl_high_s16 (int16x8_t a) + /// A32: VMOVL.S16 Qd, Dm+1 + /// A64: SXTL2 Vd.4S, Vn.8H + /// + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + + /// + /// int64x2_t vmovl_high_s32 (int32x4_t a) + /// A32: VMOVL.S32 Qd, Dm+1 + /// A64: SXTL2 Vd.2D, Vn.4S + /// + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + + /// + /// int16x8_t vmovl_high_s8 (int8x16_t a) + /// A32: VMOVL.S8 Qd, Dm+1 + /// A64: SXTL2 Vd.8H, Vn.16B + /// + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + + /// + /// float64x1_t vsqrt_f64 (float64x1_t a) + /// A32: VSQRT.F64 Dd, Dm + /// A64: FSQRT Dd, Dn + /// + public static Vector64 SqrtScalar(Vector64 value) => SqrtScalar(value); + + /// + /// float32_t vsqrts_f32 (float32_t a) + /// A32: VSQRT.F32 Sd, Sm + /// A64: FSQRT Sd, Sn + /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs. + /// + public static Vector64 SqrtScalar(Vector64 value) => SqrtScalar(value); + + /// + /// void vst1_u8 (uint8_t * ptr, uint8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_f64 (float64_t * ptr, float64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(double* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s16 (int16_t * ptr, int16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 {Vt.4H }, [Xn] + /// + public static unsafe void Store(short* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s32 (int32_t * ptr, int32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(int* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s64 (int64_t * ptr, int64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(long* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_s8 (int8_t * ptr, int8x8_t val) + /// A32: VST1.8 { Dd }, [Rn] + /// A64: ST1 { Vt.8B }, [Xn] + /// + public static unsafe void Store(sbyte* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_f32 (float32_t * ptr, float32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(float* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_u16 (uint16_t * ptr, uint16x4_t val) + /// A32: VST1.16 { Dd }, [Rn] + /// A64: ST1 { Vt.4H }, [Xn] + /// + public static unsafe void Store(ushort* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_u32 (uint32_t * ptr, uint32x2_t val) + /// A32: VST1.32 { Dd }, [Rn] + /// A64: ST1 { Vt.2S }, [Xn] + /// + public static unsafe void Store(uint* address, Vector64 source) => Store(address, source); + + /// + /// void vst1_u64 (uint64_t * ptr, uint64x1_t val) + /// A32: VST1.64 { Dd }, [Rn] + /// A64: ST1 { Vt.1D }, [Xn] + /// + public static unsafe void Store(ulong* address, Vector64 source) => Store(address, source); + + /// + /// void vst1q_u8 (uint8_t * ptr, uint8x16_t val) + /// A32: VST1.8 { Dd, Dd+1 }, [Rn] + /// A64: ST1 { Vt.16B }, [Xn] + /// + public static unsafe void Store(byte* address, Vector128 source) => Store(address, source); /// /// void vst1q_f64 (float64_t * ptr, float64x2_t val) @@ -7050,168 +9961,168 @@ public new abstract class Arm64 : ArmBase.Arm64 /// A32: VSUBHN.I16 Dd, Qn, Qm /// A64: SUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningHighNarrowLower(left, right); + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) => SubtractHighNarrowingLower(left, right); /// /// int16x4_t vsubhn_s32 (int32x4_t a, int32x4_t b) /// A32: VSUBHN.I32 Dd, Qn, Qm /// A64: SUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningHighNarrowLower(left, right); + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) => SubtractHighNarrowingLower(left, right); /// /// int32x2_t vsubhn_s64 (int64x2_t a, int64x2_t b) /// A32: VSUBHN.I64 Dd, Qn, Qm /// A64: SUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningHighNarrowLower(left, right); + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) => SubtractHighNarrowingLower(left, right); /// /// int8x8_t vsubhn_s16 (int16x8_t a, int16x8_t b) /// A32: VSUBHN.I16 Dd, Qn, Qm /// A64: SUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningHighNarrowLower(left, right); + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) => SubtractHighNarrowingLower(left, right); /// /// uint16x4_t vsubhn_u32 (uint32x4_t a, uint32x4_t b) /// A32: VSUBHN.I32 Dd, Qn, Qm /// A64: SUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningHighNarrowLower(left, right); + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) => SubtractHighNarrowingLower(left, right); /// /// uint32x2_t vsubhn_u64 (uint64x2_t a, uint64x2_t b) /// A32: VSUBHN.I64 Dd, Qn, Qm /// A64: SUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningHighNarrowLower(left, right); + public static Vector64 SubtractHighNarrowingLower(Vector128 left, Vector128 right) => SubtractHighNarrowingLower(left, right); /// /// uint8x16_t vsubhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) /// A32: VSUBHN.I16 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: SUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningHighNarrowUpper(lower, left, right); + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractHighNarrowingUpper(lower, left, right); /// /// int16x8_t vsubhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) /// A32: VSUBHN.I32 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: SUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningHighNarrowUpper(lower, left, right); + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractHighNarrowingUpper(lower, left, right); /// /// int32x4_t vsubhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) /// A32: VSUBHN.I64 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: SUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningHighNarrowUpper(lower, left, right); + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractHighNarrowingUpper(lower, left, right); /// /// int8x16_t vsubhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) /// A32: VSUBHN.I16 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: SUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningHighNarrowUpper(lower, left, right); + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractHighNarrowingUpper(lower, left, right); /// /// uint16x8_t vsubhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) /// A32: VSUBHN.I32 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: SUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningHighNarrowUpper(lower, left, right); + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractHighNarrowingUpper(lower, left, right); /// /// uint32x4_t vsubhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) /// A32: VSUBHN.I64 Dd+1, Qn, Qm - /// A64: SUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: SUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningHighNarrowUpper(lower, left, right); + public static Vector128 SubtractHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractHighNarrowingUpper(lower, left, right); /// /// uint8x8_t vrsubhn_u16 (uint16x8_t a, uint16x8_t b) /// A32: VRSUBHN.I16 Dd, Qn, Qm /// A64: RSUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowLower(left, right); + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingLower(left, right); /// /// int16x4_t vrsubhn_s32 (int32x4_t a, int32x4_t b) /// A32: VRSUBHN.I32 Dd, Qn, Qm /// A64: RSUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowLower(left, right); + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingLower(left, right); /// /// int32x2_t vrsubhn_s64 (int64x2_t a, int64x2_t b) /// A32: VRSUBHN.I64 Dd, Qn, Qm /// A64: RSUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowLower(left, right); + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingLower(left, right); /// /// int8x8_t vrsubhn_s16 (int16x8_t a, int16x8_t b) /// A32: VRSUBHN.I16 Dd, Qn, Qm /// A64: RSUBHN Vd.8B, Vn.8H, Vm.8H /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowLower(left, right); + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingLower(left, right); /// /// uint16x4_t vrsubhn_u32 (uint32x4_t a, uint32x4_t b) /// A32: VRSUBHN.I32 Dd, Qn, Qm /// A64: RSUBHN Vd.4H, Vn.4S, Vm.4S /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowLower(left, right); + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingLower(left, right); /// /// uint32x2_t vrsubhn_u64 (uint64x2_t a, uint64x2_t b) /// A32: VRSUBHN.I64 Dd, Qn, Qm /// A64: RSUBHN Vd.2S, Vn.2D, Vm.2D /// - public static Vector64 SubtractReturningRoundedHighNarrowLower(Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowLower(left, right); + public static Vector64 SubtractRoundedHighNarrowingLower(Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingLower(left, right); /// /// uint8x16_t vrsubhn_high_u16 (uint8x8_t r, uint16x8_t a, uint16x8_t b) /// A32: VRSUBHN.I16 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RSUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingUpper(lower, left, right); /// /// int16x8_t vrsubhn_high_s32 (int16x4_t r, int32x4_t a, int32x4_t b) /// A32: VRSUBHN.I32 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RSUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingUpper(lower, left, right); /// /// int32x4_t vrsubhn_high_s64 (int32x2_t r, int64x2_t a, int64x2_t b) /// A32: VRSUBHN.I64 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RSUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingUpper(lower, left, right); /// /// int8x16_t vrsubhn_high_s16 (int8x8_t r, int16x8_t a, int16x8_t b) /// A32: VRSUBHN.I16 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.16B, Vn.8B, Vm.8H + /// A64: RSUBHN2 Vd.16B, Vn.8H, Vm.8H /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingUpper(lower, left, right); /// /// uint16x8_t vrsubhn_high_u32 (uint16x4_t r, uint32x4_t a, uint32x4_t b) /// A32: VRSUBHN.I32 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.8H, Vn.4H, Vm.4S + /// A64: RSUBHN2 Vd.8H, Vn.4S, Vm.4S /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingUpper(lower, left, right); /// /// uint32x4_t vrsubhn_high_u64 (uint32x2_t r, uint64x2_t a, uint64x2_t b) /// A32: VRSUBHN.I64 Dd+1, Qn, Qm - /// A64: RSUBHN2 Vd.4S, Vn.2S, Vm.2D + /// A64: RSUBHN2 Vd.4S, Vn.2D, Vm.2D /// - public static Vector128 SubtractReturningRoundedHighNarrowUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractReturningRoundedHighNarrowUpper(lower, left, right); + public static Vector128 SubtractRoundedHighNarrowingUpper(Vector64 lower, Vector128 left, Vector128 right) => SubtractRoundedHighNarrowingUpper(lower, left, right); /// /// uint8x8_t vqsub_u8 (uint8x8_t a, uint8x8_t b) @@ -7693,5 +10604,89 @@ public new abstract class Arm64 : ArmBase.Arm64 /// A64: EOR Vd.16B, Vn.16B, Vm.16B /// public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); + + /// + /// uint16x8_t vmovl_u8 (uint8x8_t a) + /// A32: VMOVL.U8 Qd, Dm + /// A64: UXTL Vd.8H, Vn.8B + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) => ZeroExtendWideningLower(value); + + /// + /// uint32x4_t vmovl_u16 (uint16x4_t a) + /// A32: VMOVL.U16 Qd, Dm + /// A64: UXTL Vd.4S, Vn.4H + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) => ZeroExtendWideningLower(value); + + /// + /// uint64x2_t vmovl_u32 (uint32x2_t a) + /// A32: VMOVL.U32 Qd, Dm + /// A64: UXTL Vd.2D, Vn.2S + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) => ZeroExtendWideningLower(value); + + /// + /// uint16x8_t vmovl_u8 (uint8x8_t a) + /// A32: VMOVL.U8 Qd, Dm + /// A64: UXTL Vd.8H, Vn.8B + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) => ZeroExtendWideningLower(value); + + /// + /// uint32x4_t vmovl_u16 (uint16x4_t a) + /// A32: VMOVL.U16 Qd, Dm + /// A64: UXTL Vd.4S, Vn.4H + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) => ZeroExtendWideningLower(value); + + /// + /// uint64x2_t vmovl_u32 (uint32x2_t a) + /// A32: VMOVL.U32 Qd, Dm + /// A64: UXTL Vd.2D, Vn.2S + /// + public static Vector128 ZeroExtendWideningLower(Vector64 value) => ZeroExtendWideningLower(value); + + /// + /// uint16x8_t vmovl_high_u8 (uint8x16_t a) + /// A32: VMOVL.U8 Qd, Dm+1 + /// A64: UXTL2 Vd.8H, Vn.16B + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + + /// + /// uint32x4_t vmovl_high_u16 (uint16x8_t a) + /// A32: VMOVL.U16 Qd, Dm+1 + /// A64: UXTL2 Vd.4S, Vn.8H + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + + /// + /// uint64x2_t vmovl_high_u32 (uint32x4_t a) + /// A32: VMOVL.U32 Qd, Dm+1 + /// A64: UXTL2 Vd.2D, Vn.4S + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + + /// + /// uint16x8_t vmovl_high_u8 (uint8x16_t a) + /// A32: VMOVL.U8 Qd, Dm+1 + /// A64: UXTL2 Vd.8H, Vn.16B + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + + /// + /// uint32x4_t vmovl_high_u16 (uint16x8_t a) + /// A32: VMOVL.U16 Qd, Dm+1 + /// A64: UXTL2 Vd.4S, Vn.8H + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + + /// + /// uint64x2_t vmovl_high_u32 (uint32x4_t a) + /// A32: VMOVL.U32 Qd, Dm+1 + /// A64: UXTL2 Vd.2D, Vn.4S + /// + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.PlatformNotSupported.cs index 8f62ae5fcbc94..de081c7e6e728 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.PlatformNotSupported.cs @@ -44,5 +44,34 @@ public abstract class Aes : ArmBase /// A64: AESMC V>.16B, Vn.16B /// public static Vector128 MixColumns(Vector128 value) { throw new PlatformNotSupportedException(); } + + /// + /// poly128_t vmull_p64 (poly64_t a, poly64_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.1Q, Vn.1D, Vm.1D + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) { throw new PlatformNotSupportedException(); } + + /// + /// poly128_t vmull_p64 (poly64_t a, poly64_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.1Q, Vn.1D, Vm.1D + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) { throw new PlatformNotSupportedException(); } + + /// + /// poly128_t vmull_high_p64 (poly64x2_t a, poly64x2_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.1Q, Vn.2D, Vm.2D + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + /// + /// poly128_t vmull_high_p64 (poly64x2_t a, poly64x2_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.1Q, Vn.2D, Vm.2D + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.cs index fb0a1c63975c3..97253b888eedc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Aes.cs @@ -44,5 +44,33 @@ public abstract class Aes : ArmBase /// A64: AESMC V>.16B, Vn.16B /// public static Vector128 MixColumns(Vector128 value) => MixColumns(value); + + /// + /// poly128_t vmull_p64 (poly64_t a, poly64_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.1Q, Vn.1D, Vm.1D + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) => PolynomialMultiplyWideningLower(left, right); + + /// + /// poly128_t vmull_p64 (poly64_t a, poly64_t b) + /// A32: VMULL.P8 Qd, Dn, Dm + /// A64: PMULL Vd.1Q, Vn.1D, Vm.1D + /// + public static Vector128 PolynomialMultiplyWideningLower(Vector64 left, Vector64 right) => PolynomialMultiplyWideningLower(left, right); + + /// + /// poly128_t vmull_high_p64 (poly64x2_t a, poly64x2_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.1Q, Vn.2D, Vm.2D + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) => PolynomialMultiplyWideningUpper(left, right); + + /// + /// poly128_t vmull_high_p64 (poly64x2_t a, poly64x2_t b) + /// A32: VMULL.P8 Qd, Dn+1, Dm+1 + /// A64: PMULL2 Vd.1Q, Vn.2D, Vm.2D + /// + public static Vector128 PolynomialMultiplyWideningUpper(Vector128 left, Vector128 right) => PolynomialMultiplyWideningUpper(left, right); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 5d55d00f11b8a..f2b4fe0ae6d9d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -259,31 +259,12 @@ public static Vector AsVector(this Vector128 value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi8 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] public static unsafe Vector128 Create(byte value) { - if (Avx2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - - if (Ssse3.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Ssse3.Shuffle(result, Vector128.Zero); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - - if (Sse2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - // We first unpack as bytes to duplicate value into the lower 2 bytes, then we treat it as a ushort and unpack again to duplicate those - // bits into the lower 2 words, we can finally treat it as a uint and shuffle the lower dword to duplicate value across the entire result - - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.UnpackLow(result, result); // < v, v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.UnpackLow(result.AsUInt16(), result.AsUInt16()).AsByte(); // < v, v, v, v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Sse2.Shuffle(result.AsUInt32(), 0x00).AsByte(); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -318,23 +299,12 @@ static Vector128 SoftwareFallback(byte value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128d _mm_set1_pd /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] public static unsafe Vector128 Create(double value) { - if (Sse3.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(value); // < v, ? > - return Sse3.MoveAndDuplicate(result); // < v, v > - } - - if (Sse2.IsSupported) - { - // Treating the value as a set of singles and emitting MoveLowToHigh is more efficient than dealing with the elements directly as double - // However, we still need to check if Sse2 is supported since CreateScalarUnsafe needs it to for movsd, when value is not already in register - - Vector128 result = CreateScalarUnsafe(value); // < v, ? > - return Sse.MoveLowToHigh(result.AsSingle(), result.AsSingle()).AsDouble(); // < v, v > + return Create(value); } return SoftwareFallback(value); @@ -355,24 +325,12 @@ static Vector128 SoftwareFallback(double value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi16 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] public static unsafe Vector128 Create(short value) { - if (Avx2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v, v, v, v, v > - } - - if (Sse2.IsSupported) - { - // We first unpack as ushort to duplicate value into the lower 2 words, then we can treat it as a uint and shuffle the lower dword to - // duplicate value across the entire result - - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.UnpackLow(result, result); // < v, v, ?, ?, ?, ?, ?, ? > - return Sse2.Shuffle(result.AsInt32(), 0x00).AsInt16(); // < v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -399,20 +357,12 @@ static Vector128 SoftwareFallback(short value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi32 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] public static unsafe Vector128 Create(int value) { - if (Avx2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v > - } - - if (Sse2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Sse2.Shuffle(result, 0x00); // < v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -435,22 +385,12 @@ static Vector128 SoftwareFallback(int value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi64x /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] public static unsafe Vector128 Create(long value) { - if (Sse2.X64.IsSupported) + if (Sse2.X64.IsSupported || AdvSimd.Arm64.IsSupported) { - if (Avx2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v > - } - else - { - Vector128 result = CreateScalarUnsafe(value); // < v, ? > - return Sse2.UnpackLow(result, result); // < v, v > - } + return Create(value); } return SoftwareFallback(value); @@ -471,32 +411,13 @@ static Vector128 SoftwareFallback(long value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi8 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector128 Create(sbyte value) { - if (Avx2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - - if (Ssse3.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Ssse3.Shuffle(result, Vector128.Zero); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - - if (Sse2.IsSupported) - { - // We first unpack as bytes to duplicate value into the lower 2 bytes, then we treat it as a ushort and unpack again to duplicate those - // bits into the lower 2 words, we can finally treat it as a uint and shuffle the lower dword to duplicate value across the entire result - - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.UnpackLow(result, result); // < v, v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.UnpackLow(result.AsInt16(), result.AsInt16()).AsSByte(); // < v, v, v, v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Sse2.Shuffle(result.AsInt32(), 0x00).AsSByte(); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -531,26 +452,12 @@ static Vector128 SoftwareFallback(sbyte value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128 _mm_set1_ps /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] public static unsafe Vector128 Create(float value) { - if (Avx2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v > - } - - if (Avx.IsSupported) + if (Sse.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx.Permute(result, 0x00); // < v, v, v, v > - } - - if (Sse.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Sse.Shuffle(result, result, 0x00); // < v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -573,25 +480,13 @@ static Vector128 SoftwareFallback(float value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi16 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector128 Create(ushort value) { - if (Avx2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v, v, v, v, v > - } - - if (Sse2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - // We first unpack as ushort to duplicate value into the lower 2 words, then we can treat it as a uint and shuffle the lower dword to - // duplicate value across the entire result - - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.UnpackLow(result, result); // < v, v, ?, ?, ?, ?, ?, ? > - return Sse2.Shuffle(result.AsUInt32(), 0x00).AsUInt16(); // < v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -618,21 +513,13 @@ static Vector128 SoftwareFallback(ushort value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi32 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector128 Create(uint value) { - if (Avx2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v, v, v > - } - - if (Sse2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Sse2.Shuffle(result, 0x00); // < v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -655,23 +542,13 @@ static Vector128 SoftwareFallback(uint value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m128i _mm_set1_epi64x /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector128 Create(ulong value) { - if (Sse2.X64.IsSupported) + if (Sse2.X64.IsSupported || AdvSimd.Arm64.IsSupported) { - if (Avx2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(value); // < v, ? > - return Avx2.BroadcastScalarToVector128(result); // < v, v > - } - else - { - Vector128 result = CreateScalarUnsafe(value); // < v, ? > - return Sse2.UnpackLow(result, result); // < v, v > - } + return Create(value); } return SoftwareFallback(value); @@ -707,80 +584,12 @@ static Vector128 SoftwareFallback(ulong value) /// The value that element 15 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi8 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector128 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15) { - if (Sse41.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e1, 1); // < 0, 1, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e2, 2); // < 0, 1, 2, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e3, 3); // < 0, 1, 2, 3, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e4, 4); // < 0, 1, 2, 3, 4, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e5, 5); // < 0, 1, 2, 3, 4, 5, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e6, 6); // < 0, 1, 2, 3, 4, 5, 6, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e7, 7); // < 0, 1, 2, 3, 4, 5, 6, 7, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e8, 8); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e9, 9); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e10, 10); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e11, 11); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ??, ??, ??, ?? > - result = Sse41.Insert(result, e12, 12); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ??, ??, ?? > - result = Sse41.Insert(result, e13, 13); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ??, ?? > - result = Sse41.Insert(result, e14, 14); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ?? > - return Sse41.Insert(result, e15, 15); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 > - } - - if (Sse2.IsSupported) - { - // We deal with the elements in order, unpacking the ordered pairs of bytes into vectors. We then treat those vectors as ushort and - // unpack them again, then again treating those results as uint, and a final time treating them as ulong. This efficiently gets all - // bytes ordered into the result. - - Vector128 lo16, hi16; - Vector128 lo32, hi32; - Vector128 lo64, hi64; - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)).AsUInt16(); // < 0, 1, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e2), CreateScalarUnsafe(e3)).AsUInt16(); // < 2, 3, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - lo32 = Sse2.UnpackLow(lo16, hi16).AsUInt32(); // < 0, 1, 2, 3, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e4), CreateScalarUnsafe(e5)).AsUInt16(); // < 4, 5, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e6), CreateScalarUnsafe(e7)).AsUInt16(); // < 6, 7, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi32 = Sse2.UnpackLow(lo16, hi16).AsUInt32(); // < 4, 5, 6, 7, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo64 = Sse2.UnpackLow(lo32, hi32).AsUInt64(); // < 0, 1, 2, 3, 4, 5, 6, 7, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e8), CreateScalarUnsafe(e9)).AsUInt16(); // < 8, 9, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e10), CreateScalarUnsafe(e11)).AsUInt16(); // < 10, 11, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - lo32 = Sse2.UnpackLow(lo16, hi16).AsUInt32(); // < 8, 9, 10, 11, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e12), CreateScalarUnsafe(e13)).AsUInt16(); // < 12, 13, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e14), CreateScalarUnsafe(e15)).AsUInt16(); // < 14, 15, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi32 = Sse2.UnpackLow(lo16, hi16).AsUInt32(); // < 12, 13, 14, 15, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - hi64 = Sse2.UnpackLow(lo32, hi32).AsUInt64(); // < 8, 9, 10, 11, 12, 13, 14, 15, ??, ??, ??, ??, ??, ??, ??, ?? > - - return Sse2.UnpackLow(lo64, hi64).AsByte(); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 > - } - - if (AdvSimd.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - result = AdvSimd.Insert(result, 3, e3); - result = AdvSimd.Insert(result, 4, e4); - result = AdvSimd.Insert(result, 5, e5); - result = AdvSimd.Insert(result, 6, e6); - result = AdvSimd.Insert(result, 7, e7); - result = AdvSimd.Insert(result, 8, e8); - result = AdvSimd.Insert(result, 9, e9); - result = AdvSimd.Insert(result, 10, e10); - result = AdvSimd.Insert(result, 11, e11); - result = AdvSimd.Insert(result, 12, e12); - result = AdvSimd.Insert(result, 13, e13); - result = AdvSimd.Insert(result, 14, e14); - return AdvSimd.Insert(result, 15, e15); + return Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); @@ -816,21 +625,12 @@ static Vector128 SoftwareFallback(byte e0, byte e1, byte e2, byte e3, byte /// The value that element 1 will be initialized to. /// On x86, this method corresponds to __m128d _mm_setr_pd /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector128 Create(double e0, double e1) { - if (Sse2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - // Treating the value as a set of singles and emitting MoveLowToHigh is more efficient than dealing with the elements directly as double - // However, we still need to check if Sse2 is supported since CreateScalarUnsafe needs it to for movsd, when value is not already in register - - return Sse.MoveLowToHigh(CreateScalarUnsafe(e0).AsSingle(), CreateScalarUnsafe(e1).AsSingle()).AsDouble(); - } - - if (AdvSimd.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); - return AdvSimd.Insert(result, 1, e1); + return Create(e0, e1); } return SoftwareFallback(e0, e1); @@ -858,31 +658,12 @@ static Vector128 SoftwareFallback(double e0, double e1) /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi16 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector128 Create(short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7) { - if (Sse2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.Insert(result, e1, 1); // < 0, 1, ?, ?, ?, ?, ?, ? > - result = Sse2.Insert(result, e2, 2); // < 0, 1, 2, ?, ?, ?, ?, ? > - result = Sse2.Insert(result, e3, 3); // < 0, 1, 2, 3, ?, ?, ?, ? > - result = Sse2.Insert(result, e4, 4); // < 0, 1, 2, 3, 4, ?, ?, ? > - result = Sse2.Insert(result, e5, 5); // < 0, 1, 2, 3, 4, 5, ?, ? > - result = Sse2.Insert(result, e6, 6); // < 0, 1, 2, 3, 4, 5, 6, ? > - return Sse2.Insert(result, e7, 7); // < 0, 1, 2, 3, 4, 5, 6, 7 > - } - - if (AdvSimd.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - result = AdvSimd.Insert(result, 3, e3); - result = AdvSimd.Insert(result, 4, e4); - result = AdvSimd.Insert(result, 5, e5); - result = AdvSimd.Insert(result, 6, e6); - return AdvSimd.Insert(result, 7, e7); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); @@ -912,34 +693,12 @@ static Vector128 SoftwareFallback(short e0, short e1, short e2, short e3, /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi32 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector128 Create(int e0, int e1, int e2, int e3) { - if (Sse41.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ?, ?, ? > - result = Sse41.Insert(result, e1, 1); // < 0, 1, ?, ? > - result = Sse41.Insert(result, e2, 2); // < 0, 1, 2, ? > - return Sse41.Insert(result, e3, 3); // < 0, 1, 2, 3 > - } - - if (Sse2.IsSupported) - { - // We deal with the elements in order, unpacking the ordered pairs of int into vectors. We then treat those vectors as ulong and - // unpack them again. This efficiently gets all ints ordered into the result. - - Vector128 lo64, hi64; - lo64 = Sse2.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)).AsInt64(); // < 0, 1, ?, ? > - hi64 = Sse2.UnpackLow(CreateScalarUnsafe(e2), CreateScalarUnsafe(e3)).AsInt64(); // < 2, 3, ?, ? > - return Sse2.UnpackLow(lo64, hi64).AsInt32(); // < 0, 1, 2, 3 > - } - - if (AdvSimd.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - return AdvSimd.Insert(result, 3, e3); + return Create(e0, e1, e2, e3); } return SoftwareFallback(e0, e1, e2, e3); @@ -963,24 +722,12 @@ static Vector128 SoftwareFallback(int e0, int e1, int e2, int e3) /// The value that element 1 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi64x /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector128 Create(long e0, long e1) { - if (Sse41.X64.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ? > - return Sse41.X64.Insert(result, e1, 1); // < 0, 1 > - } - - if (Sse2.X64.IsSupported) + if (Sse2.X64.IsSupported || AdvSimd.Arm64.IsSupported) { - return Sse2.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)); // < 0, 1 > - } - - if (AdvSimd.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); - return AdvSimd.Insert(result, 1, e1); + return Create(e0, e1); } return SoftwareFallback(e0, e1); @@ -1016,81 +763,13 @@ static Vector128 SoftwareFallback(long e0, long e1) /// The value that element 15 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi8 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector128 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7, sbyte e8, sbyte e9, sbyte e10, sbyte e11, sbyte e12, sbyte e13, sbyte e14, sbyte e15) { - if (Sse41.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e1, 1); // < 0, 1, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e2, 2); // < 0, 1, 2, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e3, 3); // < 0, 1, 2, 3, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e4, 4); // < 0, 1, 2, 3, 4, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e5, 5); // < 0, 1, 2, 3, 4, 5, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e6, 6); // < 0, 1, 2, 3, 4, 5, 6, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e7, 7); // < 0, 1, 2, 3, 4, 5, 6, 7, ??, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e8, 8); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, ??, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e9, 9); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ??, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e10, 10); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ??, ??, ??, ??, ?? > - result = Sse41.Insert(result, e11, 11); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ??, ??, ??, ?? > - result = Sse41.Insert(result, e12, 12); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ??, ??, ?? > - result = Sse41.Insert(result, e13, 13); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ??, ?? > - result = Sse41.Insert(result, e14, 14); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ?? > - return Sse41.Insert(result, e15, 15); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 > - } - - if (Sse2.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - // We deal with the elements in order, unpacking the ordered pairs of bytes into vectors. We then treat those vectors as ushort and - // unpack them again, then again treating those results as uint, and a final time treating them as ulong. This efficiently gets all - // bytes ordered into the result. - - Vector128 lo16, hi16; - Vector128 lo32, hi32; - Vector128 lo64, hi64; - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)).AsInt16(); // < 0, 1, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e2), CreateScalarUnsafe(e3)).AsInt16(); // < 2, 3, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - lo32 = Sse2.UnpackLow(lo16, hi16).AsInt32(); // < 0, 1, 2, 3, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e4), CreateScalarUnsafe(e5)).AsInt16(); // < 4, 5, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e6), CreateScalarUnsafe(e7)).AsInt16(); // < 6, 7, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi32 = Sse2.UnpackLow(lo16, hi16).AsInt32(); // < 4, 5, 6, 7, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo64 = Sse2.UnpackLow(lo32, hi32).AsInt64(); // < 0, 1, 2, 3, 4, 5, 6, 7, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e8), CreateScalarUnsafe(e9)).AsInt16(); // < 8, 9, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e10), CreateScalarUnsafe(e11)).AsInt16(); // < 10, 11, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - lo32 = Sse2.UnpackLow(lo16, hi16).AsInt32(); // < 8, 9, 10, 11, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - lo16 = Sse2.UnpackLow(CreateScalarUnsafe(e12), CreateScalarUnsafe(e13)).AsInt16(); // < 12, 13, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi16 = Sse2.UnpackLow(CreateScalarUnsafe(e14), CreateScalarUnsafe(e15)).AsInt16(); // < 14, 15, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - hi32 = Sse2.UnpackLow(lo16, hi16).AsInt32(); // < 12, 13, 14, 15, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ??, ?? > - - hi64 = Sse2.UnpackLow(lo32, hi32).AsInt64(); // < 8, 9, 10, 11, 12, 13, 14, 15, ??, ??, ??, ??, ??, ??, ??, ?? > - - return Sse2.UnpackLow(lo64, hi64).AsSByte(); // < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 > - } - - if (AdvSimd.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - result = AdvSimd.Insert(result, 3, e3); - result = AdvSimd.Insert(result, 4, e4); - result = AdvSimd.Insert(result, 5, e5); - result = AdvSimd.Insert(result, 6, e6); - result = AdvSimd.Insert(result, 7, e7); - result = AdvSimd.Insert(result, 8, e8); - result = AdvSimd.Insert(result, 9, e9); - result = AdvSimd.Insert(result, 10, e10); - result = AdvSimd.Insert(result, 11, e11); - result = AdvSimd.Insert(result, 12, e12); - result = AdvSimd.Insert(result, 13, e13); - result = AdvSimd.Insert(result, 14, e14); - return AdvSimd.Insert(result, 15, e15); + return Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); @@ -1128,31 +807,12 @@ static Vector128 SoftwareFallback(sbyte e0, sbyte e1, sbyte e2, sbyte e3, /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m128 _mm_setr_ps /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector128 Create(float e0, float e1, float e2, float e3) { - if (Sse41.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ?, ?, ? > - result = Sse41.Insert(result, CreateScalarUnsafe(e1), 0x10); // < 0, 1, ?, ? > - result = Sse41.Insert(result, CreateScalarUnsafe(e2), 0x20); // < 0, 1, 2, ? > - return Sse41.Insert(result, CreateScalarUnsafe(e3), 0x30); // < 0, 1, 2, 3 > - } - - if (Sse.IsSupported) + if (Sse.IsSupported || AdvSimd.IsSupported) { - Vector128 lo64, hi64; - lo64 = Sse.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)); // < 0, 1, ?, ? > - hi64 = Sse.UnpackLow(CreateScalarUnsafe(e2), CreateScalarUnsafe(e3)); // < 2, 3, ?, ? > - return Sse.MoveLowToHigh(lo64, hi64); // < 0, 1, 2, 3 > - } - - if (AdvSimd.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - return AdvSimd.Insert(result, 3, e3); + return Create(e0, e1, e2, e3); } return SoftwareFallback(e0, e1, e2, e3); @@ -1182,32 +842,13 @@ static Vector128 SoftwareFallback(float e0, float e1, float e2, float e3) /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi16 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector128 Create(ushort e0, ushort e1, ushort e2, ushort e3, ushort e4, ushort e5, ushort e6, ushort e7) { - if (Sse2.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ?, ?, ?, ?, ?, ?, ? > - result = Sse2.Insert(result, e1, 1); // < 0, 1, ?, ?, ?, ?, ?, ? > - result = Sse2.Insert(result, e2, 2); // < 0, 1, 2, ?, ?, ?, ?, ? > - result = Sse2.Insert(result, e3, 3); // < 0, 1, 2, 3, ?, ?, ?, ? > - result = Sse2.Insert(result, e4, 4); // < 0, 1, 2, 3, 4, ?, ?, ? > - result = Sse2.Insert(result, e5, 5); // < 0, 1, 2, 3, 4, 5, ?, ? > - result = Sse2.Insert(result, e6, 6); // < 0, 1, 2, 3, 4, 5, 6, ? > - return Sse2.Insert(result, e7, 7); // < 0, 1, 2, 3, 4, 5, 6, 7 > - } - - if (AdvSimd.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - result = AdvSimd.Insert(result, 3, e3); - result = AdvSimd.Insert(result, 4, e4); - result = AdvSimd.Insert(result, 5, e5); - result = AdvSimd.Insert(result, 6, e6); - return AdvSimd.Insert(result, 7, e7); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); @@ -1237,35 +878,13 @@ static Vector128 SoftwareFallback(ushort e0, ushort e1, ushort e2, ushor /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi32 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector128 Create(uint e0, uint e1, uint e2, uint e3) { - if (Sse41.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ?, ?, ? > - result = Sse41.Insert(result, e1, 1); // < 0, 1, ?, ? > - result = Sse41.Insert(result, e2, 2); // < 0, 1, 2, ? > - return Sse41.Insert(result, e3, 3); // < 0, 1, 2, 3 > - } - - if (Sse2.IsSupported) - { - // We deal with the elements in order, unpacking the ordered pairs of int into vectors. We then treat those vectors as ulong and - // unpack them again. This efficiently gets all ints ordered into the result. - - Vector128 lo64, hi64; - lo64 = Sse2.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)).AsUInt64(); // < 0, 1, ?, ? > - hi64 = Sse2.UnpackLow(CreateScalarUnsafe(e2), CreateScalarUnsafe(e3)).AsUInt64(); // < 2, 3, ?, ? > - return Sse2.UnpackLow(lo64, hi64).AsUInt32(); // < 0, 1, 2, 3 > - } - - if (AdvSimd.IsSupported) + if (Sse2.IsSupported || AdvSimd.IsSupported) { - Vector128 result = CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - return AdvSimd.Insert(result, 3, e3); + return Create(e0, e1, e2, e3); } return SoftwareFallback(e0, e1, e2, e3); @@ -1289,25 +908,13 @@ static Vector128 SoftwareFallback(uint e0, uint e1, uint e2, uint e3) /// The value that element 1 will be initialized to. /// On x86, this method corresponds to __m128i _mm_setr_epi64x /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector128 Create(ulong e0, ulong e1) { - if (Sse41.X64.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); // < 0, ? > - return Sse41.X64.Insert(result, e1, 1); // < 0, 1 > - } - - if (Sse2.X64.IsSupported) + if (Sse2.X64.IsSupported || AdvSimd.Arm64.IsSupported) { - return Sse2.UnpackLow(CreateScalarUnsafe(e0), CreateScalarUnsafe(e1)); // < 0, 1 > - } - - if (AdvSimd.IsSupported) - { - Vector128 result = CreateScalarUnsafe(e0); - return AdvSimd.Insert(result, 1, e1); + return Create(e0, e1); } return SoftwareFallback(e0, e1); @@ -1947,6 +1554,7 @@ public static Vector128 WithElement(this Vector128 vector, int index, T /// The vector to get the lower 64-bits from. /// The value of the lower 64-bits as a new . /// The type of () is not supported. + [Intrinsic] public static Vector64 GetLower(this Vector128 vector) where T : struct { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 2a123ab52099c..ae4e95608b033 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -208,19 +208,12 @@ public static Vector AsVector(this Vector256 value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi8 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(byte value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -271,19 +264,12 @@ static Vector256 SoftwareFallback(byte value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256d _mm256_set1_pd /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(double value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -306,19 +292,12 @@ static Vector256 SoftwareFallback(double value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi16 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(short value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, v, v, v, v, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -353,19 +332,12 @@ static Vector256 SoftwareFallback(short value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi32 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(int value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -392,21 +364,12 @@ static Vector256 SoftwareFallback(int value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi64x /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(long value) { - if (Sse2.X64.IsSupported) + if (Sse2.X64.IsSupported && Avx.IsSupported) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v > - } - else if (Avx.IsSupported) - { - Vector128 result = Vector128.Create(value); // < v, v, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v > - } + return Create(value); } return SoftwareFallback(value); @@ -429,20 +392,13 @@ static Vector256 SoftwareFallback(long value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi8 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(sbyte value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -493,19 +449,12 @@ static Vector256 SoftwareFallback(sbyte value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256 _mm256_set1_ps /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(float value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -532,20 +481,13 @@ static Vector256 SoftwareFallback(float value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi16 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(ushort value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, v, v, v, v, ?, ?, ?, ?, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -580,20 +522,13 @@ static Vector256 SoftwareFallback(ushort value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi32 /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(uint value) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ?, ?, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v, v, v, v, v > - } - if (Avx.IsSupported) { - Vector128 result = Vector128.Create(value); // < v, v, v, v, ?, ?, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v > + return Create(value); } return SoftwareFallback(value); @@ -620,22 +555,13 @@ static Vector256 SoftwareFallback(uint value) /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m256i _mm256_set1_epi64x /// A new with all elements initialized to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(ulong value) { - if (Sse2.X64.IsSupported) + if (Sse2.X64.IsSupported && Avx.IsSupported) { - if (Avx2.IsSupported) - { - Vector128 result = Vector128.CreateScalarUnsafe(value); // < v, ?, ?, ? > - return Avx2.BroadcastScalarToVector256(result); // < v, v, v, v > - } - else if (Avx.IsSupported) - { - Vector128 result = Vector128.Create(value); // < v, v, ?, ? > - return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v > - } + return Create(value); } return SoftwareFallback(value); @@ -689,14 +615,12 @@ static Vector256 SoftwareFallback(ulong value) /// The value that element 31 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi8 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15, byte e16, byte e17, byte e18, byte e19, byte e20, byte e21, byte e22, byte e23, byte e24, byte e25, byte e26, byte e27, byte e28, byte e29, byte e30, byte e31) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); - Vector128 hi128 = Vector128.Create(e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31); @@ -750,14 +674,12 @@ static Vector256 SoftwareFallback(byte e0, byte e1, byte e2, byte e3, byte /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m256d _mm256_setr_pd /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(double e0, double e1, double e2, double e3) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1); - Vector128 hi128 = Vector128.Create(e2, e3); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3); } return SoftwareFallback(e0, e1, e2, e3); @@ -795,14 +717,12 @@ static Vector256 SoftwareFallback(double e0, double e1, double e2, doubl /// The value that element 15 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi16 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7, short e8, short e9, short e10, short e11, short e12, short e13, short e14, short e15) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3, e4, e5, e6, e7); - Vector128 hi128 = Vector128.Create(e8, e9, e10, e11, e12, e13, e14, e15); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); @@ -844,14 +764,12 @@ static Vector256 SoftwareFallback(short e0, short e1, short e2, short e3, /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi32 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(int e0, int e1, int e2, int e3, int e4, int e5, int e6, int e7) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3); - Vector128 hi128 = Vector128.Create(e4, e5, e6, e7); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); @@ -881,14 +799,12 @@ static Vector256 SoftwareFallback(int e0, int e1, int e2, int e3, int e4, i /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi64x /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(long e0, long e1, long e2, long e3) { if (Sse2.X64.IsSupported && Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1); - Vector128 hi128 = Vector128.Create(e2, e3); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3); } return SoftwareFallback(e0, e1, e2, e3); @@ -942,15 +858,13 @@ static Vector256 SoftwareFallback(long e0, long e1, long e2, long e3) /// The value that element 31 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi8 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7, sbyte e8, sbyte e9, sbyte e10, sbyte e11, sbyte e12, sbyte e13, sbyte e14, sbyte e15, sbyte e16, sbyte e17, sbyte e18, sbyte e19, sbyte e20, sbyte e21, sbyte e22, sbyte e23, sbyte e24, sbyte e25, sbyte e26, sbyte e27, sbyte e28, sbyte e29, sbyte e30, sbyte e31) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); - Vector128 hi128 = Vector128.Create(e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31); @@ -1008,14 +922,12 @@ static Vector256 SoftwareFallback(sbyte e0, sbyte e1, sbyte e2, sbyte e3, /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m256 _mm256_setr_ps /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static unsafe Vector256 Create(float e0, float e1, float e2, float e3, float e4, float e5, float e6, float e7) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3); - Vector128 hi128 = Vector128.Create(e4, e5, e6, e7); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); @@ -1057,15 +969,13 @@ static Vector256 SoftwareFallback(float e0, float e1, float e2, float e3, /// The value that element 15 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi16 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(ushort e0, ushort e1, ushort e2, ushort e3, ushort e4, ushort e5, ushort e6, ushort e7, ushort e8, ushort e9, ushort e10, ushort e11, ushort e12, ushort e13, ushort e14, ushort e15) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3, e4, e5, e6, e7); - Vector128 hi128 = Vector128.Create(e8, e9, e10, e11, e12, e13, e14, e15); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15); @@ -1107,15 +1017,13 @@ static Vector256 SoftwareFallback(ushort e0, ushort e1, ushort e2, ushor /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi32 /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(uint e0, uint e1, uint e2, uint e3, uint e4, uint e5, uint e6, uint e7) { if (Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1, e2, e3); - Vector128 hi128 = Vector128.Create(e4, e5, e6, e7); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); @@ -1145,15 +1053,13 @@ static Vector256 SoftwareFallback(uint e0, uint e1, uint e2, uint e3, uint /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m256i _mm256_setr_epi64x /// A new with each element initialized to corresponding specified value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector256 Create(ulong e0, ulong e1, ulong e2, ulong e3) { if (Sse2.X64.IsSupported && Avx.IsSupported) { - Vector128 lo128 = Vector128.Create(e0, e1); - Vector128 hi128 = Vector128.Create(e2, e3); - return Create(lo128, hi128); + return Create(e0, e1, e2, e3); } return SoftwareFallback(e0, e1, e2, e3); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 56cf62d2f8805..d370a622ae001 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -160,19 +160,29 @@ public static Vector64 AsUInt64(this Vector64 vector) [Intrinsic] public static unsafe Vector64 Create(byte value) { - byte* pResult = stackalloc byte[8] - { - value, - value, - value, - value, - value, - value, - value, - value, - }; + if (AdvSimd.IsSupported) + { + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(byte value) + { + byte* pResult = stackalloc byte[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. @@ -181,7 +191,17 @@ public static unsafe Vector64 Create(byte value) [Intrinsic] public static unsafe Vector64 Create(double value) { - return Unsafe.As>(ref value); + if (AdvSimd.IsSupported) + { + return Create(value); + } + + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(double value) + { + return Unsafe.As>(ref value); + } } /// Creates a new instance with all elements initialized to the specified value. @@ -191,15 +211,25 @@ public static unsafe Vector64 Create(double value) [Intrinsic] public static unsafe Vector64 Create(short value) { - short* pResult = stackalloc short[4] + if (AdvSimd.IsSupported) { - value, - value, - value, - value, - }; + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(short value) + { + short* pResult = stackalloc short[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. @@ -209,13 +239,23 @@ public static unsafe Vector64 Create(short value) [Intrinsic] public static unsafe Vector64 Create(int value) { - int* pResult = stackalloc int[2] + if (AdvSimd.IsSupported) { - value, - value, - }; + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(int value) + { + int* pResult = stackalloc int[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. @@ -224,30 +264,50 @@ public static unsafe Vector64 Create(int value) [Intrinsic] public static unsafe Vector64 Create(long value) { - return Unsafe.As>(ref value); + if (AdvSimd.Arm64.IsSupported) + { + return Create(value); + } + + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(long value) + { + return Unsafe.As>(ref value); + } } /// Creates a new instance with all elements initialized to the specified value. /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m64 _mm_set1_pi8 /// A new with all elements initialized to . - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector64 Create(sbyte value) { - sbyte* pResult = stackalloc sbyte[8] + if (AdvSimd.IsSupported) { - value, - value, - value, - value, - value, - value, - value, - value, - }; + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(sbyte value) + { + sbyte* pResult = stackalloc sbyte[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. @@ -256,59 +316,99 @@ public static unsafe Vector64 Create(sbyte value) [Intrinsic] public static unsafe Vector64 Create(float value) { - float* pResult = stackalloc float[2] + if (AdvSimd.IsSupported) { - value, - value, - }; + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(float value) + { + float* pResult = stackalloc float[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m64 _mm_set1_pi16 /// A new with all elements initialized to . - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector64 Create(ushort value) { - ushort* pResult = stackalloc ushort[4] + if (AdvSimd.IsSupported) { - value, - value, - value, - value, - }; + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(ushort value) + { + ushort* pResult = stackalloc ushort[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. /// The value that all elements will be initialized to. /// On x86, this method corresponds to __m64 _mm_set1_pi32 /// A new with all elements initialized to . - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector64 Create(uint value) { - uint* pResult = stackalloc uint[2] + if (AdvSimd.IsSupported) { - value, - value, - }; + return Create(value); + } - return Unsafe.AsRef>(pResult); + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(uint value) + { + uint* pResult = stackalloc uint[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with all elements initialized to the specified value. /// The value that all elements will be initialized to. /// A new with all elements initialized to . - [CLSCompliant(false)] [Intrinsic] + [CLSCompliant(false)] public static unsafe Vector64 Create(ulong value) { - return Unsafe.As>(ref value); + if (AdvSimd.Arm64.IsSupported) + { + return Create(value); + } + + return SoftwareFallback(value); + + static Vector64 SoftwareFallback(ulong value) + { + return Unsafe.As>(ref value); + } } /// Creates a new instance with each element initialized to the corresponding specified value. @@ -322,33 +422,32 @@ public static unsafe Vector64 Create(ulong value) /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m64 _mm_setr_pi8 /// A new with each element initialized to corresponding specified value. + [Intrinsic] public static unsafe Vector64 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - result = AdvSimd.Insert(result, 3, e3); - result = AdvSimd.Insert(result, 4, e4); - result = AdvSimd.Insert(result, 5, e5); - result = AdvSimd.Insert(result, 6, e6); - return AdvSimd.Insert(result, 7, e7); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } - byte* pResult = stackalloc byte[8] + return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); + + static Vector64 SoftwareFallback(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7) { - e0, - e1, - e2, - e3, - e4, - e5, - e6, - e7, - }; + byte* pResult = stackalloc byte[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with each element initialized to the corresponding specified value. @@ -358,25 +457,28 @@ public static unsafe Vector64 Create(byte e0, byte e1, byte e2, byte e3, b /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m64 _mm_setr_pi16 /// A new with each element initialized to corresponding specified value. + [Intrinsic] public static unsafe Vector64 Create(short e0, short e1, short e2, short e3) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - return AdvSimd.Insert(result, 3, e3); + return Create(e0, e1, e2, e3); } - short* pResult = stackalloc short[4] + return SoftwareFallback(e0, e1, e2, e3); + + static Vector64 SoftwareFallback(short e0, short e1, short e2, short e3) { - e0, - e1, - e2, - e3, - }; + short* pResult = stackalloc short[4] + { + e0, + e1, + e2, + e3, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with each element initialized to the corresponding specified value. @@ -384,21 +486,26 @@ public static unsafe Vector64 Create(short e0, short e1, short e2, short /// The value that element 1 will be initialized to. /// On x86, this method corresponds to __m64 _mm_setr_pi32 /// A new with each element initialized to corresponding specified value. + [Intrinsic] public static unsafe Vector64 Create(int e0, int e1) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - return AdvSimd.Insert(result, 1, e1); + return Create(e0, e1); } - int* pResult = stackalloc int[2] + return SoftwareFallback(e0, e1); + + static Vector64 SoftwareFallback(int e0, int e1) { - e0, - e1, - }; + int* pResult = stackalloc int[2] + { + e0, + e1, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with each element initialized to the corresponding specified value. @@ -412,55 +519,59 @@ public static unsafe Vector64 Create(int e0, int e1) /// The value that element 7 will be initialized to. /// On x86, this method corresponds to __m64 _mm_setr_pi8 /// A new with each element initialized to corresponding specified value. + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector64 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - result = AdvSimd.Insert(result, 3, e3); - result = AdvSimd.Insert(result, 4, e4); - result = AdvSimd.Insert(result, 5, e5); - result = AdvSimd.Insert(result, 6, e6); - return AdvSimd.Insert(result, 7, e7); + return Create(e0, e1, e2, e3, e4, e5, e6, e7); } - sbyte* pResult = stackalloc sbyte[8] + return SoftwareFallback(e0, e1, e2, e3, e4, e5, e6, e7); + + static Vector64 SoftwareFallback(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7) { - e0, - e1, - e2, - e3, - e4, - e5, - e6, - e7, - }; + sbyte* pResult = stackalloc sbyte[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with each element initialized to the corresponding specified value. /// The value that element 0 will be initialized to. /// The value that element 1 will be initialized to. /// A new with each element initialized to corresponding specified value. + [Intrinsic] public static unsafe Vector64 Create(float e0, float e1) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - return AdvSimd.Insert(result, 1, e1); + return Create(e0, e1); } - float* pResult = stackalloc float[2] + return SoftwareFallback(e0, e1); + + static Vector64 SoftwareFallback(float e0, float e1) { - e0, - e1, - }; + float* pResult = stackalloc float[2] + { + e0, + e1, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with each element initialized to the corresponding specified value. @@ -470,26 +581,29 @@ public static unsafe Vector64 Create(float e0, float e1) /// The value that element 3 will be initialized to. /// On x86, this method corresponds to __m64 _mm_setr_pi16 /// A new with each element initialized to corresponding specified value. + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector64 Create(ushort e0, ushort e1, ushort e2, ushort e3) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - result = AdvSimd.Insert(result, 1, e1); - result = AdvSimd.Insert(result, 2, e2); - return AdvSimd.Insert(result, 3, e3); + return Create(e0, e1, e2, e3); } - ushort* pResult = stackalloc ushort[4] + return SoftwareFallback(e0, e1, e2, e3); + + static Vector64 SoftwareFallback(ushort e0, ushort e1, ushort e2, ushort e3) { - e0, - e1, - e2, - e3, - }; + ushort* pResult = stackalloc ushort[4] + { + e0, + e1, + e2, + e3, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with each element initialized to the corresponding specified value. @@ -497,22 +611,27 @@ public static unsafe Vector64 Create(ushort e0, ushort e1, ushort e2, us /// The value that element 1 will be initialized to. /// On x86, this method corresponds to __m64 _mm_setr_pi32 /// A new with each element initialized to corresponding specified value. + [Intrinsic] [CLSCompliant(false)] public static unsafe Vector64 Create(uint e0, uint e1) { if (AdvSimd.IsSupported) { - Vector64 result = Vector64.CreateScalarUnsafe(e0); - return AdvSimd.Insert(result, 1, e1); + return Create(e0, e1); } - uint* pResult = stackalloc uint[2] + return SoftwareFallback(e0, e1); + + static Vector64 SoftwareFallback(uint e0, uint e1) { - e0, - e1, - }; + uint* pResult = stackalloc uint[2] + { + e0, + e1, + }; - return Unsafe.AsRef>(pResult); + return Unsafe.AsRef>(pResult); + } } /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. @@ -766,6 +885,7 @@ public static unsafe Vector64 CreateScalarUnsafe(uint value) /// The value of the element at . /// The type of () is not supported. /// was less than zero or greater than the number of elements. + [Intrinsic] public static T GetElement(this Vector64 vector, int index) where T : struct { @@ -809,6 +929,7 @@ public static Vector64 WithElement(this Vector64 vector, int index, T v /// The vector to get the first element from. /// A scalar containing the value of the first element. /// The type of () is not supported. + [Intrinsic] public static T ToScalar(this Vector64 vector) where T : struct { @@ -821,6 +942,7 @@ public static T ToScalar(this Vector64 vector) /// The vector to extend. /// A new with the lower 64-bits set to the value of and the upper 64-bits initialized to zero. /// The type of () is not supported. + [Intrinsic] public static Vector128 ToVector128(this Vector64 vector) where T : struct { @@ -836,6 +958,7 @@ public static Vector128 ToVector128(this Vector64 vector) /// The vector to extend. /// A new with the lower 64-bits set to the value of and the upper 64-bits left uninitialized. /// The type of () is not supported. + [Intrinsic] public static unsafe Vector128 ToVector128Unsafe(this Vector64 vector) where T : struct { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index c958169fe579d..80d7c00ea8d54 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -564,16 +564,6 @@ public void Dispose() return context.ResolveUsingLoad(assemblyName); } - // This method is invoked by the VM to resolve a satellite assembly reference - // after trying assembly resolution via Load override without success. - private static Assembly? ResolveSatelliteAssembly(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) - { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; - - // Invoke the ResolveSatelliteAssembly method - return context.ResolveSatelliteAssembly(assemblyName); - } - private Assembly? GetFirstResolvedAssemblyFromResolvingEvent(AssemblyName assemblyName) { Assembly? resolvedAssembly = null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs index 92346d5e9ba53..a9a2225e206b0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/FrameworkName.cs @@ -19,8 +19,6 @@ public sealed class FrameworkName : IEquatable private const string VersionKey = "Version"; private const string ProfileKey = "Profile"; - private static readonly char[] s_componentSplitSeparator = { ComponentSeparator }; - public string Identifier { get @@ -146,7 +144,7 @@ public FrameworkName(string frameworkName) throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(frameworkName)), nameof(frameworkName)); } - string[] components = frameworkName.Split(s_componentSplitSeparator); + string[] components = frameworkName.Split(ComponentSeparator); // Identifier and Version are required, Profile is optional. if (components.Length < 2 || components.Length > 3) diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index 010ca6c2ce34f..c74821918b165 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -75,7 +75,7 @@ public override IList GetCustomAttributesData() public override MemberInfo[] GetDefaultMembers() { // See if we have cached the default member name - MemberInfo[] members = null!; + MemberInfo[]? members = null; string? defaultMemberName = GetDefaultMemberName(); if (defaultMemberName != null) @@ -237,6 +237,9 @@ public override bool IsEnumDefined(object value) if (value == null) throw new ArgumentNullException(nameof(value)); + if (!IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + // Check if both of them are of the same type RuntimeType valueType = (RuntimeType)value.GetType(); diff --git a/src/libraries/System.Private.CoreLib/src/System/SR.cs b/src/libraries/System.Private.CoreLib/src/System/SR.cs index e70d6187507a7..73e7e0015526b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SR.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SR.cs @@ -13,53 +13,23 @@ namespace System { internal static partial class SR { - // This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format. - // by default it returns false. - // Native code generators can replace the value this returns based on user input at the time of native code generation. - // Marked as NoInlining because if this is used in an AoT compiled app that is not compiled into a single file, the user - // could compile each module with a different setting for this. We want to make sure there's a consistent behavior - // that doesn't depend on which native module this method got inlined into. - [MethodImpl(MethodImplOptions.NoInlining)] - private static bool UsingResourceKeys() - { - return false; - } + private static readonly object _lock = new object(); + private static List? _currentlyLoading; + private static int _infinitelyRecursingCount; + private static bool _resourceManagerInited; // Needed for debugger integration - internal static string? GetResourceString(string resourceKey) + internal static string GetResourceString(string resourceKey) { return GetResourceString(resourceKey, string.Empty); } - internal static string GetResourceString(string resourceKey, string? defaultString) - { - if (UsingResourceKeys()) - return defaultString ?? resourceKey; - - string? resourceString = null; - try { resourceString = InternalGetResourceString(resourceKey); } - catch (MissingManifestResourceException) { } - - if (defaultString != null && resourceKey.Equals(resourceString, StringComparison.Ordinal)) - { - return defaultString; - } - - return resourceString!; // only null if missing resource - } - - private static readonly object _lock = new object(); - private static List? _currentlyLoading; - private static int _infinitelyRecursingCount; - private static bool _resourceManagerInited = false; - - [PreserveDependency(".cctor()", "System.Resources.ResourceManager")] - private static string? InternalGetResourceString(string? key) + private static string InternalGetResourceString(string key) { - if (string.IsNullOrEmpty(key)) + if (key.Length == 0) { - Debug.Fail("SR::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); - return key!; + Debug.Fail("SR::GetResourceString with empty resourceKey. Bug in caller, or weird recursive loading problem?"); + return key; } // We have a somewhat common potential for infinite @@ -146,64 +116,5 @@ internal static string GetResourceString(string resourceKey, string? defaultStri } } } - - internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) - { - if (args != null) - { - if (UsingResourceKeys()) - { - return resourceFormat + ", " + string.Join(", ", args); - } - - return string.Format(provider, resourceFormat, args); - } - - return resourceFormat; - } - - internal static string Format(string resourceFormat, params object?[]? args) - { - if (args != null) - { - if (UsingResourceKeys()) - { - return resourceFormat + ", " + string.Join(", ", args); - } - - return string.Format(resourceFormat, args); - } - - return resourceFormat; - } - - internal static string Format(string resourceFormat, object? p1) - { - if (UsingResourceKeys()) - { - return string.Join(", ", resourceFormat, p1); - } - - return string.Format(resourceFormat, p1); - } - - internal static string Format(string resourceFormat, object? p1, object? p2) - { - if (UsingResourceKeys()) - { - return string.Join(", ", resourceFormat, p1, p2); - } - - return string.Format(resourceFormat, p1, p2); - } - - internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) - { - if (UsingResourceKeys()) - { - return string.Join(", ", resourceFormat, p1, p2, p3); - } - return string.Format(resourceFormat, p1, p2, p3); - } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs index 541f22dccdcb9..ef0f7bbc00d07 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs @@ -10,7 +10,7 @@ namespace System.Security { public sealed class SecurityElement { - internal string _tag = null!; + internal string _tag; internal string? _text; private ArrayList? _children; internal ArrayList? _attributes; @@ -34,10 +34,6 @@ public sealed class SecurityElement //-------------------------- Constructors --------------------------- - internal SecurityElement() - { - } - public SecurityElement(string tag) { if (tag == null) diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index 25bab98c88991..6016674dcdfdf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -13,13 +13,6 @@ #pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { /// @@ -273,7 +266,7 @@ public bool MoveNext() /// Clears the contents of this span. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() + public unsafe void Clear() { if (RuntimeHelpers.IsReferenceOrContainsReferences()) { diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs index f965f98ac7f5e..5132148ae5832 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs @@ -10,15 +10,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -using nint = System.Int64; -#else -using nuint = System.UInt32; -using nint = System.Int32; -#endif // TARGET_64BIT - namespace System { internal static partial class SpanHelpers // .Byte @@ -1311,11 +1302,11 @@ public static int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, // Optimized byte-based SequenceEquals. The "length" parameter for this one is declared a nuint rather than int as we also use it for types other than byte // where the length can exceed 2Gb once scaled by sizeof(T). - public static bool SequenceEqual(ref byte first, ref byte second, nuint length) + public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint length) { bool result; // Use nint for arithmetic to avoid unnecessary 64->32->64 truncations - if (length >= sizeof(nuint)) + if (length >= (nuint)sizeof(nuint)) { // Conditional jmp foward to favor shorter lengths. (See comment at "Equal:" label) // The longer lengths can make back the time due to branch misprediction @@ -1473,9 +1464,9 @@ public static bool SequenceEqual(ref byte first, ref byte second, nuint length) #if TARGET_64BIT if (Sse2.IsSupported) { - Debug.Assert(length <= sizeof(nuint) * 2); + Debug.Assert(length <= (nuint)sizeof(nuint) * 2); - nuint offset = length - sizeof(nuint); + nuint offset = length - (nuint)sizeof(nuint); nuint differentBits = LoadNUInt(ref first) - LoadNUInt(ref second); differentBits |= LoadNUInt(ref first, offset) - LoadNUInt(ref second, offset); result = (differentBits == 0); @@ -1484,10 +1475,10 @@ public static bool SequenceEqual(ref byte first, ref byte second, nuint length) else #endif { - Debug.Assert(length >= sizeof(nuint)); + Debug.Assert(length >= (nuint)sizeof(nuint)); { nuint offset = 0; - nuint lengthToExamine = length - sizeof(nuint); + nuint lengthToExamine = length - (nuint)sizeof(nuint); // Unsigned, so it shouldn't have overflowed larger than length (rather than negative) Debug.Assert(lengthToExamine < length); if (lengthToExamine > 0) @@ -1499,7 +1490,7 @@ public static bool SequenceEqual(ref byte first, ref byte second, nuint length) { goto NotEqual; } - offset += sizeof(nuint); + offset += (nuint)sizeof(nuint); } while (lengthToExamine > offset); } @@ -1540,7 +1531,7 @@ private static int LocateFirstFoundByte(Vector match) } [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength) + public static unsafe int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength) { Debug.Assert(firstLength >= 0); Debug.Assert(secondLength >= 0); @@ -1693,16 +1684,16 @@ public static int SequenceCompareTo(ref byte first, int firstLength, ref byte se } } - if (lengthToExamine > sizeof(nuint)) + if (lengthToExamine > (nuint)sizeof(nuint)) { - lengthToExamine -= sizeof(nuint); + lengthToExamine -= (nuint)sizeof(nuint); while (lengthToExamine > offset) { if (LoadNUInt(ref first, offset) != LoadNUInt(ref second, offset)) { goto BytewiseCheck; } - offset += sizeof(nuint); + offset += (nuint)sizeof(nuint); } } @@ -1742,33 +1733,11 @@ private static int LocateLastFoundByte(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundByte(ulong match) - { - if (Bmi1.X64.IsSupported) - { - return (int)(Bmi1.X64.TrailingZeroCount(match) >> 3); - } - else - { - // Flag least significant power of two bit - ulong powerOfTwoFlag = match ^ (match - 1); - // Shift all powers of two into the high byte and extract - return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57); - } - } + => BitOperations.TrailingZeroCount(match) >> 3; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateLastFoundByte(ulong match) - { - return 7 - (BitOperations.LeadingZeroCount(match) >> 3); - } - - private const ulong XorPowerOfTwoToHighByte = (0x07ul | - 0x06ul << 8 | - 0x05ul << 16 | - 0x04ul << 24 | - 0x03ul << 32 | - 0x02ul << 40 | - 0x01ul << 48) + 1; + => BitOperations.Log2(match) >> 3; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ushort LoadUShort(ref byte start) diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs index 0f21d07c107c0..02f0ba9920724 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Char.cs @@ -10,15 +10,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -using nint = System.Int64; -#else -using nuint = System.UInt32; -using nint = System.Int32; -#endif - namespace System { internal static partial class SpanHelpers // .Char @@ -66,7 +57,7 @@ public static int IndexOf(ref char searchSpace, int searchSpaceLength, ref char } [MethodImpl(MethodImplOptions.AggressiveOptimization)] - public static int SequenceCompareTo(ref char first, int firstLength, ref char second, int secondLength) + public static unsafe int SequenceCompareTo(ref char first, int firstLength, ref char second, int secondLength) { Debug.Assert(firstLength >= 0); Debug.Assert(secondLength >= 0); @@ -79,7 +70,7 @@ public static int SequenceCompareTo(ref char first, int firstLength, ref char se nuint minLength = (nuint)(((uint)firstLength < (uint)secondLength) ? (uint)firstLength : (uint)secondLength); nuint i = 0; // Use nuint for arithmetic to avoid unnecessary 64->32->64 truncations - if (minLength >= (sizeof(nuint) / sizeof(char))) + if (minLength >= (nuint)(sizeof(nuint) / sizeof(char))) { if (Vector.IsHardwareAccelerated && minLength >= (nuint)Vector.Count) { @@ -96,14 +87,14 @@ public static int SequenceCompareTo(ref char first, int firstLength, ref char se while (nLength >= i); } - while (minLength >= (i + sizeof(nuint) / sizeof(char))) + while (minLength >= (i + (nuint)(sizeof(nuint) / sizeof(char)))) { if (Unsafe.ReadUnaligned (ref Unsafe.As(ref Unsafe.Add(ref first, (nint)i))) != Unsafe.ReadUnaligned(ref Unsafe.As(ref Unsafe.Add(ref second, (nint)i)))) { break; } - i += sizeof(nuint) / sizeof(char); + i += (nuint)(sizeof(nuint) / sizeof(char)); } } @@ -984,27 +975,7 @@ private static int LocateFirstFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundChar(ulong match) - { - // TODO: Arm variants - if (Bmi1.X64.IsSupported) - { - return (int)(Bmi1.X64.TrailingZeroCount(match) >> 4); - } - else - { - unchecked - { - // Flag least significant power of two bit - ulong powerOfTwoFlag = match ^ (match - 1); - // Shift all powers of two into the high byte and extract - return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49); - } - } - } - - private const ulong XorPowerOfTwoToHighChar = (0x03ul | - 0x02ul << 16 | - 0x01ul << 32) + 1; + => BitOperations.TrailingZeroCount(match) >> 4; // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138 [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1029,9 +1000,7 @@ private static int LocateLastFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateLastFoundChar(ulong match) - { - return 3 - (BitOperations.LeadingZeroCount(match) >> 4); - } + => BitOperations.Log2(match) >> 4; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector LoadVector(ref char start, nint offset) diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs index ddd2416eceaea..24e82c21a8267 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs @@ -6,13 +6,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { internal static partial class SpanHelpers @@ -348,14 +341,14 @@ public static unsafe void ClearWithReferences(ref IntPtr ip, nuint pointerSizeLe for (; pointerSizeLength >= 8; pointerSizeLength -= 8) { - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -1) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -2) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -3) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -4) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -5) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -6) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -7) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -8) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -1) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -2) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -3) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -4) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -5) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -6) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -7) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -8) = default; } Debug.Assert(pointerSizeLength <= 7); @@ -396,15 +389,15 @@ public static unsafe void ClearWithReferences(ref IntPtr ip, nuint pointerSizeLe // Write first four and last three. Unsafe.Add(ref ip, 2) = default; Unsafe.Add(ref ip, 3) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -3) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -2) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -3) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -2) = default; Write2To3: Debug.Assert(pointerSizeLength >= 2); // Write first two and last one. Unsafe.Add(ref ip, 1) = default; - Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -1) = default; + Unsafe.Add(ref Unsafe.Add(ref ip, (nint)pointerSizeLength), -1) = default; Write1: Debug.Assert(pointerSizeLength >= 1); diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index 5ceed67a563a9..1708b2cb1e328 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -10,13 +10,6 @@ using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { public partial class String diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.Helpers.cs b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.Helpers.cs index 731d52ab822cc..71f984bbd4cfd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.Helpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.Helpers.cs @@ -44,44 +44,19 @@ internal static uint CountNumberOfLeadingAsciiBytesFromUInt32WithSomeNonAsciiDat { Debug.Assert(!AllBytesInUInt32AreAscii(value), "Caller shouldn't provide an all-ASCII value."); - // Use BMI1 directly rather than going through BitOperations. We only see a perf gain here - // if we're able to emit a real tzcnt instruction; the software fallback used by BitOperations - // is too slow for our purposes since we can provide our own faster, specialized software fallback. - - if (Bmi1.IsSupported) - { - Debug.Assert(BitConverter.IsLittleEndian); - return Bmi1.TrailingZeroCount(value & UInt32HighBitsOnlyMask) >> 3; - } - - // Couldn't emit tzcnt, use specialized software fallback. - // The 'allBytesUpToNowAreAscii' DWORD uses bit twiddling to hold a 1 or a 0 depending - // on whether all processed bytes were ASCII. Then we accumulate all of the - // results to calculate how many consecutive ASCII bytes are present. - - value = ~value; - if (BitConverter.IsLittleEndian) { - // Read first byte - value >>= 7; - uint allBytesUpToNowAreAscii = value & 1; - uint numAsciiBytes = allBytesUpToNowAreAscii; - - // Read second byte - value >>= 8; - allBytesUpToNowAreAscii &= value; - numAsciiBytes += allBytesUpToNowAreAscii; - - // Read third byte - value >>= 8; - allBytesUpToNowAreAscii &= value; - numAsciiBytes += allBytesUpToNowAreAscii; - - return numAsciiBytes; + return (uint)BitOperations.TrailingZeroCount(value & UInt32HighBitsOnlyMask) >> 3; } else { + // Couldn't use tzcnt, use specialized software fallback. + // The 'allBytesUpToNowAreAscii' DWORD uses bit twiddling to hold a 1 or a 0 depending + // on whether all processed bytes were ASCII. Then we accumulate all of the + // results to calculate how many consecutive ASCII bytes are present. + + value = ~value; + // BinaryPrimitives.ReverseEndianness is only implemented as an intrinsic on // little-endian platforms, so using it in this big-endian path would be too // expensive. Instead we'll just change how we perform the shifts. diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs index c0bdbf03f7059..57492533d199a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs @@ -12,32 +12,10 @@ using Internal.Runtime.CompilerServices; #endif -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if SYSTEM_PRIVATE_CORELIB -#if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; -#else // TARGET_64BIT -using nint = System.Int32; -using nuint = System.UInt32; -#endif // TARGET_64BIT -#else -using nint = System.Int64; // https://github.com/dotnet/runtime/issues/33575 - use long/ulong outside of corelib until the compiler supports it -using nuint = System.UInt64; -#endif - namespace System.Text { internal static partial class ASCIIUtility { -#if DEBUG && SYSTEM_PRIVATE_CORELIB - static ASCIIUtility() - { - Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); - Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); - } -#endif // DEBUG && SYSTEM_PRIVATE_CORELIB - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool AllBytesInUInt64AreAscii(ulong value) { @@ -410,7 +388,7 @@ private static unsafe nuint GetIndexOfFirstNonAsciiByte_Sse2(byte* pBuffer, nuin if ((bufferLength & 8) != 0) { - if (Bmi1.X64.IsSupported) + if (UIntPtr.Size == sizeof(ulong)) { // If we can use 64-bit tzcnt to count the number of leading ASCII bytes, prefer it. @@ -418,10 +396,10 @@ private static unsafe nuint GetIndexOfFirstNonAsciiByte_Sse2(byte* pBuffer, nuin if (!AllBytesInUInt64AreAscii(candidateUInt64)) { // Clear everything but the high bit of each byte, then tzcnt. - // Remember the / 8 at the end to convert bit count to byte count. + // Remember to divide by 8 at the end to convert bit count to byte count. candidateUInt64 &= UInt64HighBitsOnlyMask; - pBuffer += (nuint)(Bmi1.X64.TrailingZeroCount(candidateUInt64) / 8); + pBuffer += (nuint)(BitOperations.TrailingZeroCount(candidateUInt64) >> 3); goto Finish; } } @@ -524,7 +502,9 @@ private static unsafe nuint GetIndexOfFirstNonAsciiChar_Default(char* pBuffer, n char* pOriginalBuffer = pBuffer; +#if SYSTEM_PRIVATE_CORELIB Debug.Assert(bufferLength <= nuint.MaxValue / sizeof(char)); +#endif // Before we drain off char-by-char, try a generic vectorized loop. // Only run the loop if we have at least two vectors we can pull out. @@ -687,7 +667,9 @@ private static unsafe nuint GetIndexOfFirstNonAsciiChar_Sse2(char* pBuffer, nuin Vector128 asciiMaskForPADDUSW = Vector128.Create((ushort)0x7F80); // used for PADDUSW const uint NonAsciiDataSeenMask = 0b_1010_1010_1010_1010; // used for determining whether 'currentMask' contains non-ASCII data +#if SYSTEM_PRIVATE_CORELIB Debug.Assert(bufferLength <= nuint.MaxValue / sizeof(char)); +#endif // Read the first vector unaligned. @@ -932,7 +914,7 @@ private static unsafe nuint GetIndexOfFirstNonAsciiChar_Sse2(char* pBuffer, nuin if ((bufferLength & 4) != 0) { - if (Bmi1.X64.IsSupported) + if (UIntPtr.Size == sizeof(ulong)) { // If we can use 64-bit tzcnt to count the number of leading ASCII chars, prefer it. @@ -940,12 +922,12 @@ private static unsafe nuint GetIndexOfFirstNonAsciiChar_Sse2(char* pBuffer, nuin if (!AllCharsInUInt64AreAscii(candidateUInt64)) { // Clear the low 7 bits (the ASCII bits) of each char, then tzcnt. - // Remember the / 8 at the end to convert bit count to byte count, + // Remember to divide by 8 at the end to convert bit count to byte count, // then the & ~1 at the end to treat a match in the high byte of // any char the same as a match in the low byte of that same char. candidateUInt64 &= 0xFF80FF80_FF80FF80ul; - pBuffer = (char*)((byte*)pBuffer + ((nuint)(Bmi1.X64.TrailingZeroCount(candidateUInt64) / 8) & ~(nuint)1)); + pBuffer = (char*)((byte*)pBuffer + ((nuint)(BitOperations.TrailingZeroCount(candidateUInt64) >> 3) & ~(nuint)1)); goto Finish; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.cs index 203fd784f1ee7..3f0d0350610ba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.cs @@ -118,8 +118,8 @@ public abstract partial class Encoding : ICloneable private bool _isReadOnly = true; // Encoding (encoder) fallback - internal EncoderFallback encoderFallback = null!; - internal DecoderFallback decoderFallback = null!; + internal EncoderFallback encoderFallback; + internal DecoderFallback decoderFallback; protected Encoding() : this(0) { @@ -159,6 +159,8 @@ protected Encoding(int codePage, EncoderFallback? encoderFallback, DecoderFallba } // Default fallback that we'll use. + [MemberNotNull(nameof(encoderFallback))] + [MemberNotNull(nameof(decoderFallback))] internal virtual void SetDefaultFallbacks() { // For UTF-X encodings, we use a replacement fallback with an "\xFFFD" string, diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs index 1b18fd5eca51f..bdff2d05df01e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -1144,7 +1144,9 @@ public StringBuilder Remove(int startIndex, int length) return this; } +#pragma warning disable CA1830 // Prefer strongly-typed Append and Insert method overloads on StringBuilder. No need to fix for the builder itself public StringBuilder Append(bool value) => Append(value.ToString()); +#pragma warning restore CA1830 public StringBuilder Append(char value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs index 3f697491d218f..feb7a3114c30f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs @@ -7,6 +7,7 @@ // using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace System.Text @@ -31,15 +32,15 @@ public class UTF7Encoding : Encoding internal static readonly UTF7Encoding s_default = new UTF7Encoding(); // The set of base 64 characters. - private byte[] _base64Bytes = null!; + private byte[] _base64Bytes; // The decoded bits for every base64 values. This array has a size of 128 elements. // The index is the code point value of the base 64 characters. The value is -1 if // the code point is not a valid base 64 character. Otherwise, the value is a value // from 0 ~ 63. - private sbyte[] _base64Values = null!; + private sbyte[] _base64Values; // The array to decide if a Unicode code point below 0x80 can be directly encoded in UTF7. // This array has a size of 128. - private bool[] _directEncode = null!; + private bool[] _directEncode; private readonly bool _allowOptionals; @@ -60,6 +61,9 @@ public UTF7Encoding(bool allowOptionals) MakeTables(); } + [MemberNotNull(nameof(_base64Bytes))] + [MemberNotNull(nameof(_base64Values))] + [MemberNotNull(nameof(_directEncode))] private void MakeTables() { // Build our tables diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf16Utility.Validation.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf16Utility.Validation.cs index 73bfa603f9252..c2b38f159d6aa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf16Utility.Validation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf16Utility.Validation.cs @@ -15,15 +15,12 @@ #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types #if SYSTEM_PRIVATE_CORELIB #if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; +using nuint_t = System.UInt64; #else // TARGET_64BIT -using nint = System.Int32; -using nuint = System.UInt32; +using nuint_t = System.UInt32; #endif // TARGET_64BIT #else -using nint = System.Int64; // https://github.com/dotnet/runtime/issues/33575 - use long/ulong outside of corelib until the compiler supports it -using nuint = System.UInt64; +using nuint_t = System.UInt64; #endif namespace System.Text.Unicode @@ -33,8 +30,7 @@ internal static unsafe partial class Utf16Utility #if DEBUG && SYSTEM_PRIVATE_CORELIB static Utf16Utility() { - Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); - Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); + Debug.Assert(sizeof(nuint_t) == IntPtr.Size && nuint.MinValue == 0, "nuint_t is defined incorrectly."); } #endif // DEBUG && SYSTEM_PRIVATE_CORELIB @@ -291,15 +287,15 @@ static Utf16Utility() Vector utf16Data = Unsafe.ReadUnaligned>(pInputBuffer); Vector twoOrMoreUtf8Bytes = Vector.GreaterThanOrEqual(utf16Data, vector0080); Vector threeOrMoreUtf8Bytes = Vector.GreaterThanOrEqual(utf16Data, vector0800); - Vector sumVector = (Vector)(Vector.Zero - twoOrMoreUtf8Bytes - threeOrMoreUtf8Bytes); + Vector sumVector = (Vector)(Vector.Zero - twoOrMoreUtf8Bytes - threeOrMoreUtf8Bytes); // We'll try summing by a natural word (rather than a 16-bit word) at a time, // which should halve the number of operations we must perform. nuint popcnt = 0; - for (int i = 0; i < Vector.Count; i++) + for (int i = 0; i < Vector.Count; i++) { - popcnt += sumVector[i]; + popcnt += (nuint)sumVector[i]; } uint popcnt32 = (uint)popcnt; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs index 64f76fec69147..201626fd6b876 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs @@ -13,34 +13,10 @@ using Internal.Runtime.CompilerServices; #endif -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if SYSTEM_PRIVATE_CORELIB -#if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; -#else // TARGET_64BIT -using nint = System.Int32; -using nuint = System.UInt32; -#endif // TARGET_64BIT -#else -using nint = System.Int64; // https://github.com/dotnet/runtime/issues/33575 - use long/ulong outside of corelib until the compiler supports it -using nuint = System.UInt64; -#endif - namespace System.Text.Unicode { internal static unsafe partial class Utf8Utility { -#if DEBUG && SYSTEM_PRIVATE_CORELIB - static Utf8Utility() - { - Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); - Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); - - _ValidateAdditionalNIntDefinitions(); - } -#endif // DEBUG && SYSTEM_PRIVATE_CORELIB - // On method return, pInputBufferRemaining and pOutputBufferRemaining will both point to where // the next byte would have been consumed from / the next char would have been written to. // inputLength in bytes, outputCharsRemaining in chars. diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Validation.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Validation.cs index 8284828d53043..a4a1932987fe3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Validation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Validation.cs @@ -11,32 +11,10 @@ using Internal.Runtime.CompilerServices; #endif -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if SYSTEM_PRIVATE_CORELIB -#if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; -#else // TARGET_64BIT -using nint = System.Int32; -using nuint = System.UInt32; -#endif // TARGET_64BIT -#else -using nint = System.Int64; // https://github.com/dotnet/runtime/issues/33575 - use long/ulong outside of corelib until the compiler supports it -using nuint = System.UInt64; -#endif - namespace System.Text.Unicode { internal static unsafe partial class Utf8Utility { -#if DEBUG && SYSTEM_PRIVATE_CORELIB - private static void _ValidateAdditionalNIntDefinitions() - { - Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); - Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); - } -#endif // DEBUG && SYSTEM_PRIVATE_CORELIB - // Returns &inputBuffer[inputLength] if the input buffer is valid. /// /// Given an input buffer of byte length , @@ -144,7 +122,7 @@ private static void _ValidateAdditionalNIntDefinitions() do { - if (Sse2.IsSupported && Bmi1.IsSupported) + if (Sse2.IsSupported) { // pInputBuffer is 32-bit aligned but not necessary 128-bit aligned, so we're // going to perform an unaligned load. We don't necessarily care about aligning @@ -180,7 +158,6 @@ private static void _ValidateAdditionalNIntDefinitions() Debug.Assert(BitConverter.IsLittleEndian); Debug.Assert(Sse2.IsSupported); - Debug.Assert(Bmi1.IsSupported); // The 'mask' value will have a 0 bit for each ASCII byte we saw and a 1 bit // for each non-ASCII byte we saw. We can count the number of ASCII bytes, @@ -189,7 +166,7 @@ private static void _ValidateAdditionalNIntDefinitions() Debug.Assert(mask != 0); - pInputBuffer += Bmi1.TrailingZeroCount(mask); + pInputBuffer += BitOperations.TrailingZeroCount(mask); if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) { goto ProcessRemainingBytesSlow; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.WhiteSpace.CoreLib.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.WhiteSpace.CoreLib.cs index cf656bc1dc2d1..6c34b06728dd9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.WhiteSpace.CoreLib.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.WhiteSpace.CoreLib.cs @@ -5,14 +5,6 @@ using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nint = System.Int32; -using nuint = System.UInt32; -#endif - namespace System.Text.Unicode { internal static partial class Utf8Utility diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Utf8Span.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Utf8Span.cs index eb6cdb6527d41..3a90590bb6da7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Utf8Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Utf8Span.cs @@ -15,20 +15,6 @@ #pragma warning disable 0809 //warning CS0809: Obsolete member 'Utf8Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if SYSTEM_PRIVATE_CORELIB -#if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; -#else -using nint = System.Int32; -using nuint = System.UInt32; -#endif -#else -using nint = System.Int64; // https://github.com/dotnet/runtime/issues/33575 - use long/ulong outside of corelib until the compiler supports it -using nuint = System.UInt64; -#endif - namespace System.Text { [StructLayout(LayoutKind.Auto)] @@ -132,7 +118,7 @@ private Utf8Span(ReadOnlySpan rawData) #if SYSTEM_PRIVATE_CORELIB return ref Unsafe.AddByteOffset(ref DangerousGetMutableReference(), index); #else - return ref Unsafe.AddByteOffset(ref DangerousGetMutableReference(), (IntPtr)index); + return ref Unsafe.AddByteOffset(ref DangerousGetMutableReference(), (nint)index); #endif } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs index 8bdf89070a9ad..9abd9ac2aa98a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs @@ -243,7 +243,7 @@ public bool TrySetApartmentState(ApartmentState state) break; default: - throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_Enum, nameof(state)); + throw new ArgumentOutOfRangeException(nameof(state), SR.ArgumentOutOfRange_Enum); } return TrySetApartmentStateUnchecked(state); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.cs index fe1021272a282..de78cc1a7002f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.cs @@ -22,26 +22,6 @@ namespace System.Threading { - internal static class ThreadPoolGlobals - { - public static volatile bool threadPoolInitialized; - public static bool enableWorkerTracking; - - public static readonly ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue(); - - /// Shim used to invoke of the supplied . - internal static readonly Action s_invokeAsyncStateMachineBox = state => - { - if (!(state is IAsyncStateMachineBox box)) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.state); - return; - } - - box.MoveNext(); - }; - } - [StructLayout(LayoutKind.Sequential)] // enforce layout so that padding reduces false sharing internal sealed class ThreadPoolWorkQueue { @@ -552,7 +532,7 @@ public long LocalCount /// internal static bool Dispatch() { - ThreadPoolWorkQueue outerWorkQueue = ThreadPoolGlobals.workQueue; + ThreadPoolWorkQueue outerWorkQueue = ThreadPool.s_workQueue; // // Save the start time @@ -627,7 +607,7 @@ internal static bool Dispatch() // // Execute the workitem outside of any finally blocks, so that it can be aborted if needed. // - if (ThreadPoolGlobals.enableWorkerTracking) + if (ThreadPool.s_enableWorkerTracking) { bool reportedStatus = false; try @@ -954,6 +934,21 @@ internal static void PerformWaitOrTimerCallback(_ThreadPoolWaitOrTimerCallback h public static partial class ThreadPool { + internal static readonly ThreadPoolWorkQueue s_workQueue = new ThreadPoolWorkQueue(); + internal static readonly bool s_enableWorkerTracking = GetEnableWorkerTracking(); + + /// Shim used to invoke of the supplied . + internal static readonly Action s_invokeAsyncStateMachineBox = state => + { + if (!(state is IAsyncStateMachineBox box)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.state); + return; + } + + box.MoveNext(); + }; + [CLSCompliant(false)] public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, @@ -1080,15 +1075,13 @@ public static bool QueueUserWorkItem(WaitCallback callBack, object? state) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.callBack); } - EnsureInitialized(); - ExecutionContext? context = ExecutionContext.Capture(); object tpcallBack = (context == null || context.IsDefault) ? new QueueUserWorkItemCallbackDefaultContext(callBack!, state) : (object)new QueueUserWorkItemCallback(callBack!, state, context); - ThreadPoolGlobals.workQueue.Enqueue(tpcallBack, forceGlobal: true); + s_workQueue.Enqueue(tpcallBack, forceGlobal: true); return true; } @@ -1100,15 +1093,13 @@ public static bool QueueUserWorkItem(Action callBack, TState sta ThrowHelper.ThrowArgumentNullException(ExceptionArgument.callBack); } - EnsureInitialized(); - ExecutionContext? context = ExecutionContext.Capture(); object tpcallBack = (context == null || context.IsDefault) ? new QueueUserWorkItemCallbackDefaultContext(callBack!, state) : (object)new QueueUserWorkItemCallback(callBack!, state, context); - ThreadPoolGlobals.workQueue.Enqueue(tpcallBack, forceGlobal: !preferLocal); + s_workQueue.Enqueue(tpcallBack, forceGlobal: !preferLocal); return true; } @@ -1126,7 +1117,7 @@ public static bool UnsafeQueueUserWorkItem(Action callBack, TSta // // This occurs when user code queues its provided continuation to the ThreadPool; // internally we call UnsafeQueueUserWorkItemInternal directly for Tasks. - if (ReferenceEquals(callBack, ThreadPoolGlobals.s_invokeAsyncStateMachineBox)) + if (ReferenceEquals(callBack, ThreadPool.s_invokeAsyncStateMachineBox)) { if (!(state is IAsyncStateMachineBox)) { @@ -1138,9 +1129,7 @@ public static bool UnsafeQueueUserWorkItem(Action callBack, TSta return true; } - EnsureInitialized(); - - ThreadPoolGlobals.workQueue.Enqueue( + s_workQueue.Enqueue( new QueueUserWorkItemCallbackDefaultContext(callBack!, state), forceGlobal: !preferLocal); return true; @@ -1153,11 +1142,9 @@ public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object? state) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.callBack); } - EnsureInitialized(); - object tpcallBack = new QueueUserWorkItemCallbackDefaultContext(callBack!, state); - ThreadPoolGlobals.workQueue.Enqueue(tpcallBack, forceGlobal: true); + s_workQueue.Enqueue(tpcallBack, forceGlobal: true); return true; } @@ -1183,25 +1170,21 @@ internal static void UnsafeQueueUserWorkItemInternal(object callBack, bool prefe { Debug.Assert((callBack is IThreadPoolWorkItem) ^ (callBack is Task)); - EnsureInitialized(); - - ThreadPoolGlobals.workQueue.Enqueue(callBack, forceGlobal: !preferLocal); + s_workQueue.Enqueue(callBack, forceGlobal: !preferLocal); } // This method tries to take the target callback out of the current thread's queue. internal static bool TryPopCustomWorkItem(object workItem) { Debug.Assert(null != workItem); - return - ThreadPoolGlobals.threadPoolInitialized && // if not initialized, so there's no way this workitem was ever queued. - ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem); + return s_workQueue.LocalFindAndPop(workItem); } // Get all workitems. Called by TaskScheduler in its debugger hooks. internal static IEnumerable GetQueuedWorkItems() { // Enumerate global queue - foreach (object workItem in ThreadPoolGlobals.workQueue.workItems) + foreach (object workItem in s_workQueue.workItems) { yield return workItem; } @@ -1239,7 +1222,7 @@ internal static IEnumerable GetLocallyQueuedWorkItems() } } - internal static IEnumerable GetGloballyQueuedWorkItems() => ThreadPoolGlobals.workQueue.workItems; + internal static IEnumerable GetGloballyQueuedWorkItems() => s_workQueue.workItems; private static object[] ToObjectArray(IEnumerable workitems) { @@ -1285,7 +1268,7 @@ public static long PendingWorkItemCount { get { - ThreadPoolWorkQueue workQueue = ThreadPoolGlobals.workQueue; + ThreadPoolWorkQueue workQueue = s_workQueue; return workQueue.LocalCount + workQueue.GlobalCount + PendingUnmanagedWorkItemCount; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs index 3b590ae738280..98e65d497e92b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Threading.Tasks; @@ -695,7 +696,7 @@ public sealed class Timer : MarshalByRefObject, IDisposable, IAsyncDisposable { private const uint MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe; - private TimerHolder _timer = null!; // initialized in helper called by ctors + private TimerHolder _timer; public Timer(TimerCallback callback, object? state, @@ -774,6 +775,7 @@ public Timer(TimerCallback callback) TimerSetup(callback, this, DueTime, Period); } + [MemberNotNull(nameof(_timer))] private void TimerSetup(TimerCallback callback, object? state, uint dueTime, diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs index 59f244f6c3477..d041c32b7b534 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs @@ -23,7 +23,7 @@ public virtual bool IsEnumDefined(object value) throw new ArgumentNullException(nameof(value)); if (!IsEnum) - throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + throw new ArgumentException(SR.Arg_MustBeEnum, nameof(value)); // Check if both of them are of the same type Type valueType = value.GetType(); @@ -70,7 +70,7 @@ public virtual bool IsEnumDefined(object value) throw new ArgumentNullException(nameof(value)); if (!IsEnum) - throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); + throw new ArgumentException(SR.Arg_MustBeEnum, nameof(value)); Type valueType = value.GetType(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index aeb60457d9741..76aa11bc20491 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -267,7 +267,7 @@ public static Type[] GetTypeArray(object[] args) for (int i = 0; i < cls.Length; i++) { if (args[i] == null) - throw new ArgumentNullException(); + throw new ArgumentException(SR.ArgumentNull_ArrayValue, nameof(args)); cls[i] = args[i].GetType(); } return cls; diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index 99eb0cf759087..d28bd83c90a31 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -11,9 +11,9 @@ #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types #if TARGET_64BIT -using nuint = System.UInt64; +using nuint_t = System.UInt64; #else -using nuint = System.UInt32; +using nuint_t = System.UInt32; #endif namespace System @@ -156,7 +156,7 @@ public unsafe uint ToUInt32() public static int Size { [NonVersionable] - get => sizeof(nuint); + get => sizeof(nuint_t); } [NonVersionable] @@ -165,13 +165,13 @@ public static int Size public static UIntPtr MaxValue { [NonVersionable] - get => (UIntPtr)nuint.MaxValue; + get => (UIntPtr)nuint_t.MaxValue; } public static UIntPtr MinValue { [NonVersionable] - get => (UIntPtr)nuint.MinValue; + get => (UIntPtr)nuint_t.MinValue; } public unsafe int CompareTo(object? value) @@ -180,9 +180,8 @@ public unsafe int CompareTo(object? value) { return 1; } - if (value is UIntPtr o) + if (value is nuint i) { - nuint i = (nuint)o; if ((nuint)_value < i) return -1; if ((nuint)_value > i) return 1; return 0; @@ -191,31 +190,31 @@ public unsafe int CompareTo(object? value) throw new ArgumentException(SR.Arg_MustBeUIntPtr); } - public unsafe int CompareTo(UIntPtr value) => ((nuint)_value).CompareTo((nuint)value); + public unsafe int CompareTo(UIntPtr value) => ((nuint_t)_value).CompareTo((nuint_t)value); [NonVersionable] public unsafe bool Equals(UIntPtr other) => (nuint)_value == (nuint)other; - public unsafe override string ToString() => ((nuint)_value).ToString(); - public unsafe string ToString(string? format) => ((nuint)_value).ToString(format); - public unsafe string ToString(IFormatProvider? provider) => ((nuint)_value).ToString(provider); - public unsafe string ToString(string? format, IFormatProvider? provider) => ((nuint)_value).ToString(format, provider); + public unsafe override string ToString() => ((nuint_t)_value).ToString(); + public unsafe string ToString(string? format) => ((nuint_t)_value).ToString(format); + public unsafe string ToString(IFormatProvider? provider) => ((nuint_t)_value).ToString(provider); + public unsafe string ToString(string? format, IFormatProvider? provider) => ((nuint_t)_value).ToString(format, provider); - public static UIntPtr Parse(string s) => (UIntPtr)nuint.Parse(s); - public static UIntPtr Parse(string s, NumberStyles style) => (UIntPtr)nuint.Parse(s, style); - public static UIntPtr Parse(string s, IFormatProvider? provider) => (UIntPtr)nuint.Parse(s, provider); - public static UIntPtr Parse(string s, NumberStyles style, IFormatProvider? provider) => (UIntPtr)nuint.Parse(s, style, provider); + public static UIntPtr Parse(string s) => (UIntPtr)nuint_t.Parse(s); + public static UIntPtr Parse(string s, NumberStyles style) => (UIntPtr)nuint_t.Parse(s, style); + public static UIntPtr Parse(string s, IFormatProvider? provider) => (UIntPtr)nuint_t.Parse(s, provider); + public static UIntPtr Parse(string s, NumberStyles style, IFormatProvider? provider) => (UIntPtr)nuint_t.Parse(s, style, provider); public static bool TryParse(string? s, out UIntPtr result) { Unsafe.SkipInit(out result); - return nuint.TryParse(s, out Unsafe.As(ref result)); + return nuint_t.TryParse(s, out Unsafe.As(ref result)); } public static bool TryParse(string? s, NumberStyles style, IFormatProvider? provider, out UIntPtr result) { Unsafe.SkipInit(out result); - return nuint.TryParse(s, style, provider, out Unsafe.As(ref result)); + return nuint_t.TryParse(s, style, provider, out Unsafe.As(ref result)); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Utf8String.cs b/src/libraries/System.Private.CoreLib/src/System/Utf8String.cs index e6cba4d2e4c2b..0989371e22878 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Utf8String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Utf8String.cs @@ -13,20 +13,6 @@ using Internal.Runtime.CompilerServices; #endif -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if SYSTEM_PRIVATE_CORELIB -#if TARGET_64BIT -using nint = System.Int64; -using nuint = System.UInt64; -#else -using nint = System.Int32; -using nuint = System.UInt32; -#endif -#else -using nint = System.Int64; // https://github.com/dotnet/runtime/issues/33575 - use long/ulong outside of corelib until the compiler supports it -using nuint = System.UInt64; -#endif - namespace System { /// @@ -133,7 +119,7 @@ public int CompareTo(Utf8String? other, StringComparison comparison) #if SYSTEM_PRIVATE_CORELIB return ref Unsafe.AddByteOffset(ref DangerousGetMutableReference(), index); #else - return ref Unsafe.AddByteOffset(ref DangerousGetMutableReference(), (IntPtr)index); + return ref Unsafe.AddByteOffset(ref DangerousGetMutableReference(), (nint)index); #endif } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs index 6f09bd393b63b..2f0194b2334b6 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs @@ -245,7 +245,7 @@ public override string LookupPrefix(string ns) { return JsonGlobals.xmlPrefix; } - if (ns == string.Empty) + if (ns.Length == 0) { return string.Empty; } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs index d9d9277f33485..67f0afc57a017 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs @@ -502,8 +502,8 @@ private CollectionSetItemDelegate GetCollectionSetItemDelegate(CollectionData { Type keyType = collectionContract.ItemType.GenericTypeArguments[0]; Type valueType = collectionContract.ItemType.GenericTypeArguments[1]; - Func objectToKeyValuePairGetKey = (Func)s_objectToKeyValuePairGetKey.MakeGenericMethod(keyType, valueType).CreateDelegate(typeof(Func)); - Func objectToKeyValuePairGetValue = (Func)s_objectToKeyValuePairGetValue.MakeGenericMethod(keyType, valueType).CreateDelegate(typeof(Func)); + Func objectToKeyValuePairGetKey = s_objectToKeyValuePairGetKey.MakeGenericMethod(keyType, valueType).CreateDelegate>(); + Func objectToKeyValuePairGetValue = s_objectToKeyValuePairGetValue.MakeGenericMethod(keyType, valueType).CreateDelegate>(); if (collectionContract.Kind == CollectionKind.GenericDictionary) { diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionXmlFormatReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionXmlFormatReader.cs index 6c10360268146..3f9c5dc1e84f3 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionXmlFormatReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionXmlFormatReader.cs @@ -55,7 +55,7 @@ protected override void ReflectionReadMembers(XmlReaderDelegator xmlReader, XmlO context.IncrementItemCount(memberCount); int memberIndex = -1; int firstRequiredMember; - bool[] requiredMembers = GetRequiredMembers(classContract, out firstRequiredMember); + _ = GetRequiredMembers(classContract, out firstRequiredMember); bool hasRequiredMembers = (firstRequiredMember < memberCount); int requiredIndex = hasRequiredMembers ? firstRequiredMember : -1; DataMember[] members = new DataMember[memberCount]; diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaExporter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaExporter.cs index f610d58635d4d..b5de0afbeb763 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaExporter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaExporter.cs @@ -450,7 +450,7 @@ private void ExportISerializableDataContract(ClassDataContract dataContract, Xml XmlElement isValueTypeElement = null; if (dataContract.BaseContract != null) { - XmlSchemaComplexContentExtension extension = CreateTypeContent(type, dataContract.BaseContract.StableName, schema); + _ = CreateTypeContent(type, dataContract.BaseContract.StableName, schema); } else { diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs index 8eb7f8ee8f6f3..bd5f5d8e3b6c4 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs @@ -119,7 +119,7 @@ public XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classC ReadClass(classContract); } - bool isFactoryType = InvokeFactoryMethod(classContract, objectId); + _ = InvokeFactoryMethod(classContract, objectId); if (Globals.TypeOfIDeserializationCallback.IsAssignableFrom(classContract.UnderlyingType)) { _ilg.Call(_objectLocal, XmlFormatGeneratorStatics.OnDeserializationMethod, null); diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs index 64dbb9a7b9f40..43d74a87879fb 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs @@ -213,28 +213,37 @@ private bool TryEnsureBytes(int count) { if (_stream == null) return false; - DiagnosticUtility.DebugAssert(_offset <= int.MaxValue - count, ""); - int newOffsetMax = _offset + count; - if (newOffsetMax < _offsetMax) - return true; - DiagnosticUtility.DebugAssert(newOffsetMax <= _windowOffsetMax, ""); - if (newOffsetMax > _buffer.Length) - { - byte[] newBuffer = new byte[Math.Max(newOffsetMax, _buffer.Length * 2)]; - System.Buffer.BlockCopy(_buffer, 0, newBuffer, 0, _offsetMax); - _buffer = newBuffer; - _streamBuffer = newBuffer; - } - int needed = newOffsetMax - _offsetMax; - while (needed > 0) + + // The data could be coming from an untrusted source, so we use a standard + // "multiply by 2" growth algorithm to avoid overly large memory utilization. + // Constant value of 256 comes from MemoryStream implementation. + + do { - int actual = _stream.Read(_buffer, _offsetMax, needed); - if (actual == 0) - return false; - _offsetMax += actual; - needed -= actual; - } - return true; + DiagnosticUtility.DebugAssert(_offset <= int.MaxValue - count, ""); + int newOffsetMax = _offset + count; + if (newOffsetMax <= _offsetMax) + return true; + DiagnosticUtility.DebugAssert(newOffsetMax <= _windowOffsetMax, ""); + if (newOffsetMax > _buffer.Length) + { + byte[] newBuffer = new byte[Math.Max(256, _buffer.Length * 2)]; + System.Buffer.BlockCopy(_buffer, 0, newBuffer, 0, _offsetMax); + newOffsetMax = Math.Min(newOffsetMax, newBuffer.Length); + _buffer = newBuffer; + _streamBuffer = newBuffer; + } + int needed = newOffsetMax - _offsetMax; + DiagnosticUtility.DebugAssert(needed > 0, ""); + do + { + int actual = _stream.Read(_buffer, _offsetMax, needed); + if (actual == 0) + return false; + _offsetMax += actual; + needed -= actual; + } while (needed > 0); + } while (true); } public void Advance(int count) @@ -491,7 +500,7 @@ public TimeSpan ReadTimeSpan() public Guid ReadGuid() { int offset; - byte[] buffer = GetBuffer(ValueHandleLength.Guid, out offset); + _ = GetBuffer(ValueHandleLength.Guid, out offset); Guid guid = GetGuid(offset); Advance(ValueHandleLength.Guid); return guid; @@ -500,7 +509,7 @@ public Guid ReadGuid() public string ReadUTF8String(int length) { int offset; - byte[] buffer = GetBuffer(length, out offset); + _ = GetBuffer(length, out offset); char[] chars = GetCharBuffer(length); int charCount = GetChars(offset, length, chars); string value = new string(chars, 0, charCount); @@ -844,7 +853,6 @@ public bool IsWhitespaceUTF8(int offset, int length) public bool IsWhitespaceUnicode(int offset, int length) { - byte[] buffer = _buffer; for (int i = 0; i < length; i += sizeof(char)) { char ch = (char)GetInt16(offset + i); diff --git a/src/libraries/System.Private.Uri/src/Resources/Strings.resx b/src/libraries/System.Private.Uri/src/Resources/Strings.resx index 655f2820692e2..92a87cd44ccaa 100644 --- a/src/libraries/System.Private.Uri/src/Resources/Strings.resx +++ b/src/libraries/System.Private.Uri/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + -- suppress ws betw and comment - RawText(base.newLineChars); + RawText(base._newLineChars); for (int i = _indentLevel; i > 0; i--) { RawText(_indentChars); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlRawTextWriterGenerator.ttinclude b/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlRawTextWriterGenerator.ttinclude index f8101cbe653ae..09cc00e36c08b 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlRawTextWriterGenerator.ttinclude +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlRawTextWriterGenerator.ttinclude @@ -19,8 +19,8 @@ namespace System.Xml { internal class <#= ClassName #> : <#= BaseClassName #> { - protected ByteStack elementScope; - protected ElementProperties currentElementProperties; + protected ByteStack _elementScope; + protected ElementProperties _currentElementProperties; private AttributeProperties _currentAttributeProperties; private bool _endsWithAmpersand; @@ -29,8 +29,8 @@ namespace System.Xml private string _mediaType; private bool _doNotEscapeUriAttributes; - protected static TernaryTreeReadOnly elementPropertySearch; - protected static TernaryTreeReadOnly attributePropertySearch; + protected static TernaryTreeReadOnly _elementPropertySearch; + protected static TernaryTreeReadOnly _attributePropertySearch; private const int StackIncrement = 10; <# if (WriterType == RawTextWriterType.Encoded) { #> @@ -108,7 +108,7 @@ namespace System.Xml { Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); - elementScope.Push((byte)currentElementProperties); + _elementScope.Push((byte)_currentElementProperties); if (ns.Length == 0) { @@ -116,7 +116,7 @@ namespace System.Xml #><#= SetTextContentMark(4, false) #> - currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName); + _currentElementProperties = (ElementProperties)_elementPropertySearch.FindCaseInsensitiveString(localName); base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; base.RawText(localName); base.attrEndPos = bufPos; @@ -125,7 +125,7 @@ namespace System.Xml { // Since the HAS_NS has no impact to the ElementTextBlock behavior, // we don't need to push it into the stack. - currentElementProperties = ElementProperties.HAS_NS; + _currentElementProperties = ElementProperties.HAS_NS; base.WriteStartElement(prefix, localName, ns); } } @@ -138,7 +138,7 @@ namespace System.Xml // Detect whether content is output contentPos = bufPos; - if ((currentElementProperties & ElementProperties.HEAD) != 0) + if ((_currentElementProperties & ElementProperties.HEAD) != 0) { WriteMetaElement(); } @@ -156,7 +156,7 @@ namespace System.Xml #><#= SetTextContentMark(4, false) #> - if ((currentElementProperties & ElementProperties.EMPTY) == 0) + if ((_currentElementProperties & ElementProperties.EMPTY) == 0) { <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'<'; <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'/'; @@ -170,7 +170,7 @@ namespace System.Xml base.WriteEndElement(prefix, localName, ns); } - currentElementProperties = (ElementProperties)elementScope.Pop(); + _currentElementProperties = (ElementProperties)_elementScope.Pop(); } internal override void WriteFullEndElement(string prefix, string localName, string ns) @@ -181,7 +181,7 @@ namespace System.Xml #><#= SetTextContentMark(4, false) #> - if ((currentElementProperties & ElementProperties.EMPTY) == 0) + if ((_currentElementProperties & ElementProperties.EMPTY) == 0) { <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'<'; <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'/'; @@ -195,7 +195,7 @@ namespace System.Xml base.WriteFullEndElement(prefix, localName, ns); } - currentElementProperties = (ElementProperties)elementScope.Pop(); + _currentElementProperties = (ElementProperties)_elementScope.Pop(); } // 1. How the outputBooleanAttribute(fBOOL) and outputHtmlUriText(fURI) being set? @@ -311,10 +311,10 @@ namespace System.Xml } base.RawText(localName); - if ((currentElementProperties & (ElementProperties.BOOL_PARENT | ElementProperties.URI_PARENT | ElementProperties.NAME_PARENT)) != 0) + if ((_currentElementProperties & (ElementProperties.BOOL_PARENT | ElementProperties.URI_PARENT | ElementProperties.NAME_PARENT)) != 0) { - _currentAttributeProperties = (AttributeProperties)attributePropertySearch.FindCaseInsensitiveString(localName) & - (AttributeProperties)currentElementProperties; + _currentAttributeProperties = (AttributeProperties)_attributePropertySearch.FindCaseInsensitiveString(localName) & + (AttributeProperties)_currentElementProperties; if ((_currentAttributeProperties & AttributeProperties.BOOLEAN) != 0) { @@ -451,16 +451,16 @@ namespace System.Xml Debug.Assert((int)ElementProperties.BOOL_PARENT == (int)AttributeProperties.BOOLEAN); Debug.Assert((int)ElementProperties.NAME_PARENT == (int)AttributeProperties.NAME); - if (elementPropertySearch == null) + if (_elementPropertySearch == null) { - //elementPropertySearch should be init last for the mutli thread safe situation. - attributePropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlAttributes); - elementPropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlElements); + //_elementPropertySearch should be init last for the mutli thread safe situation. + _attributePropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlAttributes); + _elementPropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlElements); } - elementScope = new ByteStack(StackIncrement); + _elementScope = new ByteStack(StackIncrement); _uriEscapingBuffer = new byte[5]; - currentElementProperties = ElementProperties.DEFAULT; + _currentElementProperties = ElementProperties.DEFAULT; _mediaType = settings.MediaType; _doNotEscapeUriAttributes = settings.DoNotEscapeUriAttributes; @@ -493,7 +493,7 @@ namespace System.Xml // only the top of the stack is the real E1 element properties. protected unsafe void WriteHtmlElementTextBlock(char* pSrc, char* pSrcEnd) { - if ((currentElementProperties & ElementProperties.NO_ENTITIES) != 0) + if ((_currentElementProperties & ElementProperties.NO_ENTITIES) != 0) { base.RawText(pSrc, pSrcEnd); } @@ -522,7 +522,7 @@ namespace System.Xml WriteHtmlAttributeText(pSrc, pSrcEnd); } } - else if ((currentElementProperties & ElementProperties.HAS_NS) != 0) + else if ((_currentElementProperties & ElementProperties.HAS_NS) != 0) { base.WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -844,15 +844,15 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - base.elementScope.Push((byte)base.currentElementProperties); + base._elementScope.Push((byte)base._currentElementProperties); if (ns.Length == 0) { Debug.Assert(prefix.Length == 0); - base.currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName); + base._currentElementProperties = (ElementProperties)_elementPropertySearch.FindCaseInsensitiveString(localName); - if (_endBlockPos == base.bufPos && (base.currentElementProperties & ElementProperties.BLOCK_WS) != 0) + if (_endBlockPos == base.bufPos && (base._currentElementProperties & ElementProperties.BLOCK_WS) != 0) { WriteIndent(); } @@ -862,7 +862,7 @@ namespace System.Xml } else { - base.currentElementProperties = ElementProperties.HAS_NS | ElementProperties.BLOCK_WS; + base._currentElementProperties = ElementProperties.HAS_NS | ElementProperties.BLOCK_WS; if (_endBlockPos == base.bufPos) { @@ -888,13 +888,13 @@ namespace System.Xml // Detect whether content is output base.contentPos = base.bufPos; - if ((currentElementProperties & ElementProperties.HEAD) != 0) + if ((_currentElementProperties & ElementProperties.HEAD) != 0) { WriteIndent(); WriteMetaElement(); _endBlockPos = base.bufPos; } - else if ((base.currentElementProperties & ElementProperties.BLOCK_WS) != 0) + else if ((base._currentElementProperties & ElementProperties.BLOCK_WS) != 0) { // store the element block position _endBlockPos = base.bufPos; @@ -909,7 +909,7 @@ namespace System.Xml _indentLevel--; // If this element has block whitespace properties, - isBlockWs = (base.currentElementProperties & ElementProperties.BLOCK_WS) != 0; + isBlockWs = (base._currentElementProperties & ElementProperties.BLOCK_WS) != 0; if (isBlockWs) { // And if the last node to be output had block whitespace properties, diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlUtf8RawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlUtf8RawTextWriter.cs index f9934ec9548d1..375a10747e6b0 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlUtf8RawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/HtmlUtf8RawTextWriter.cs @@ -17,8 +17,8 @@ namespace System.Xml { internal class HtmlUtf8RawTextWriter : XmlUtf8RawTextWriter { - protected ByteStack elementScope; - protected ElementProperties currentElementProperties; + protected ByteStack _elementScope; + protected ElementProperties _currentElementProperties; private AttributeProperties _currentAttributeProperties; private bool _endsWithAmpersand; @@ -27,8 +27,8 @@ internal class HtmlUtf8RawTextWriter : XmlUtf8RawTextWriter private string _mediaType; private bool _doNotEscapeUriAttributes; - protected static TernaryTreeReadOnly elementPropertySearch; - protected static TernaryTreeReadOnly attributePropertySearch; + protected static TernaryTreeReadOnly _elementPropertySearch; + protected static TernaryTreeReadOnly _attributePropertySearch; private const int StackIncrement = 10; @@ -69,27 +69,27 @@ public override void WriteDocType(string name, string pubid, string sysid, strin RawText("\" \""); RawText(sysid); } - bufBytes[bufPos++] = (byte)'"'; + _bufBytes[_bufPos++] = (byte)'"'; } else if (sysid != null) { RawText(" SYSTEM \""); RawText(sysid); - bufBytes[bufPos++] = (byte)'"'; + _bufBytes[_bufPos++] = (byte)'"'; } else { - bufBytes[bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)' '; } if (subset != null) { - bufBytes[bufPos++] = (byte)'['; + _bufBytes[_bufPos++] = (byte)'['; RawText(subset); - bufBytes[bufPos++] = (byte)']'; + _bufBytes[_bufPos++] = (byte)']'; } - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'>'; } // For the HTML element, it should call this method with ns and prefix as String.Empty @@ -97,22 +97,22 @@ public override void WriteStartElement(string prefix, string localName, string n { Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); - elementScope.Push((byte)currentElementProperties); + _elementScope.Push((byte)_currentElementProperties); if (ns.Length == 0) { Debug.Assert(prefix.Length == 0); - currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName); - base.bufBytes[bufPos++] = (byte)'<'; + _currentElementProperties = (ElementProperties)_elementPropertySearch.FindCaseInsensitiveString(localName); + base._bufBytes[_bufPos++] = (byte)'<'; base.RawText(localName); - base.attrEndPos = bufPos; + base._attrEndPos = _bufPos; } else { // Since the HAS_NS has no impact to the ElementTextBlock behavior, // we don't need to push it into the stack. - currentElementProperties = ElementProperties.HAS_NS; + _currentElementProperties = ElementProperties.HAS_NS; base.WriteStartElement(prefix, localName, ns); } } @@ -120,12 +120,12 @@ public override void WriteStartElement(string prefix, string localName, string n // Output >. For HTML needs to output META info internal override void StartElementContent() { - base.bufBytes[base.bufPos++] = (byte)'>'; + base._bufBytes[base._bufPos++] = (byte)'>'; // Detect whether content is output - contentPos = bufPos; + _contentPos = _bufPos; - if ((currentElementProperties & ElementProperties.HEAD) != 0) + if ((_currentElementProperties & ElementProperties.HEAD) != 0) { WriteMetaElement(); } @@ -141,12 +141,12 @@ internal override void WriteEndElement(string prefix, string localName, string n { Debug.Assert(prefix.Length == 0); - if ((currentElementProperties & ElementProperties.EMPTY) == 0) + if ((_currentElementProperties & ElementProperties.EMPTY) == 0) { - bufBytes[base.bufPos++] = (byte)'<'; - bufBytes[base.bufPos++] = (byte)'/'; + _bufBytes[base._bufPos++] = (byte)'<'; + _bufBytes[base._bufPos++] = (byte)'/'; base.RawText(localName); - bufBytes[base.bufPos++] = (byte)'>'; + _bufBytes[base._bufPos++] = (byte)'>'; } } else @@ -155,7 +155,7 @@ internal override void WriteEndElement(string prefix, string localName, string n base.WriteEndElement(prefix, localName, ns); } - currentElementProperties = (ElementProperties)elementScope.Pop(); + _currentElementProperties = (ElementProperties)_elementScope.Pop(); } internal override void WriteFullEndElement(string prefix, string localName, string ns) @@ -164,12 +164,12 @@ internal override void WriteFullEndElement(string prefix, string localName, stri { Debug.Assert(prefix.Length == 0); - if ((currentElementProperties & ElementProperties.EMPTY) == 0) + if ((_currentElementProperties & ElementProperties.EMPTY) == 0) { - bufBytes[base.bufPos++] = (byte)'<'; - bufBytes[base.bufPos++] = (byte)'/'; + _bufBytes[base._bufPos++] = (byte)'<'; + _bufBytes[base._bufPos++] = (byte)'/'; base.RawText(localName); - bufBytes[base.bufPos++] = (byte)'>'; + _bufBytes[base._bufPos++] = (byte)'>'; } } else @@ -178,7 +178,7 @@ internal override void WriteFullEndElement(string prefix, string localName, stri base.WriteFullEndElement(prefix, localName, ns); } - currentElementProperties = (ElementProperties)elementScope.Pop(); + _currentElementProperties = (ElementProperties)_elementScope.Pop(); } // 1. How the outputBooleanAttribute(fBOOL) and outputHtmlUriText(fURI) being set? @@ -286,20 +286,20 @@ public override void WriteStartAttribute(string prefix, string localName, string { Debug.Assert(prefix.Length == 0); - if (base.attrEndPos == bufPos) + if (base._attrEndPos == _bufPos) { - base.bufBytes[bufPos++] = (byte)' '; + base._bufBytes[_bufPos++] = (byte)' '; } base.RawText(localName); - if ((currentElementProperties & (ElementProperties.BOOL_PARENT | ElementProperties.URI_PARENT | ElementProperties.NAME_PARENT)) != 0) + if ((_currentElementProperties & (ElementProperties.BOOL_PARENT | ElementProperties.URI_PARENT | ElementProperties.NAME_PARENT)) != 0) { - _currentAttributeProperties = (AttributeProperties)attributePropertySearch.FindCaseInsensitiveString(localName) & - (AttributeProperties)currentElementProperties; + _currentAttributeProperties = (AttributeProperties)_attributePropertySearch.FindCaseInsensitiveString(localName) & + (AttributeProperties)_currentElementProperties; if ((_currentAttributeProperties & AttributeProperties.BOOLEAN) != 0) { - base.inAttributeValue = true; + base._inAttributeValue = true; return; } } @@ -308,8 +308,8 @@ public override void WriteStartAttribute(string prefix, string localName, string _currentAttributeProperties = AttributeProperties.DEFAULT; } - base.bufBytes[bufPos++] = (byte)'='; - base.bufBytes[bufPos++] = (byte)'"'; + base._bufBytes[_bufPos++] = (byte)'='; + base._bufBytes[_bufPos++] = (byte)'"'; } else { @@ -317,7 +317,7 @@ public override void WriteStartAttribute(string prefix, string localName, string _currentAttributeProperties = AttributeProperties.DEFAULT; } - base.inAttributeValue = true; + base._inAttributeValue = true; } // Output the amp; at end of EndAttribute @@ -325,7 +325,7 @@ public override void WriteEndAttribute() { if ((_currentAttributeProperties & AttributeProperties.BOOLEAN) != 0) { - base.attrEndPos = bufPos; + base._attrEndPos = _bufPos; } else { @@ -335,10 +335,10 @@ public override void WriteEndAttribute() _endsWithAmpersand = false; } - base.bufBytes[bufPos++] = (byte)'"'; + base._bufBytes[_bufPos++] = (byte)'"'; } - base.inAttributeValue = false; - base.attrEndPos = bufPos; + base._inAttributeValue = false; + base._attrEndPos = _bufPos; } // HTML PI's use ">" to terminate rather than "?>". @@ -346,16 +346,16 @@ public override void WriteProcessingInstruction(string target, string text) { Debug.Assert(target != null && target.Length != 0 && text != null); - bufBytes[base.bufPos++] = (byte)'<'; - bufBytes[base.bufPos++] = (byte)'?'; + _bufBytes[base._bufPos++] = (byte)'<'; + _bufBytes[base._bufPos++] = (byte)'?'; base.RawText(target); - bufBytes[base.bufPos++] = (byte)' '; + _bufBytes[base._bufPos++] = (byte)' '; base.WriteCommentOrPi(text, '?'); - base.bufBytes[base.bufPos++] = (byte)'>'; + base._bufBytes[base._bufPos++] = (byte)'>'; - if (base.bufPos > base.bufLen) + if (base._bufPos > base._bufLen) { FlushBuffer(); } @@ -369,7 +369,7 @@ public override unsafe void WriteString(string text) fixed (char* pSrc = text) { char* pSrcEnd = pSrc + text.Length; - if (base.inAttributeValue) + if (base._inAttributeValue) { WriteHtmlAttributeTextBlock(pSrc, pSrcEnd); } @@ -403,7 +403,7 @@ public override unsafe void WriteChars(char[] buffer, int index, int count) fixed (char* pSrcBegin = &buffer[index]) { - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count); } @@ -424,16 +424,16 @@ private void Init(XmlWriterSettings settings) Debug.Assert((int)ElementProperties.BOOL_PARENT == (int)AttributeProperties.BOOLEAN); Debug.Assert((int)ElementProperties.NAME_PARENT == (int)AttributeProperties.NAME); - if (elementPropertySearch == null) + if (_elementPropertySearch == null) { //elementPropertySearch should be init last for the mutli thread safe situation. - attributePropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlAttributes); - elementPropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlElements); + _attributePropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlAttributes); + _elementPropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlElements); } - elementScope = new ByteStack(StackIncrement); + _elementScope = new ByteStack(StackIncrement); _uriEscapingBuffer = new byte[5]; - currentElementProperties = ElementProperties.DEFAULT; + _currentElementProperties = ElementProperties.DEFAULT; _mediaType = settings.MediaType; _doNotEscapeUriAttributes = settings.DoNotEscapeUriAttributes; @@ -451,7 +451,7 @@ protected void WriteMetaElement() base.RawText(" content=\""); base.RawText(_mediaType); base.RawText("; charset="); - base.RawText(base.encoding.WebName); + base.RawText(base._encoding.WebName); base.RawText("\">"); } @@ -466,7 +466,7 @@ protected void WriteMetaElement() // only the top of the stack is the real E1 element properties. protected unsafe void WriteHtmlElementTextBlock(char* pSrc, char* pSrcEnd) { - if ((currentElementProperties & ElementProperties.NO_ENTITIES) != 0) + if ((_currentElementProperties & ElementProperties.NO_ENTITIES) != 0) { base.RawText(pSrc, pSrcEnd); } @@ -495,7 +495,7 @@ protected unsafe void WriteHtmlAttributeTextBlock(char* pSrc, char* pSrcEnd) WriteHtmlAttributeText(pSrc, pSrcEnd); } } - else if ((currentElementProperties & ElementProperties.HAS_NS) != 0) + else if ((_currentElementProperties & ElementProperties.HAS_NS) != 0) { base.WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -536,20 +536,20 @@ private unsafe void WriteHtmlAttributeText(char* pSrc, char* pSrcEnd) _endsWithAmpersand = false; } - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; char ch = (char)0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst++ = (byte)ch; pSrc++; @@ -565,7 +565,7 @@ private unsafe void WriteHtmlAttributeText(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -609,7 +609,7 @@ private unsafe void WriteHtmlAttributeText(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -624,20 +624,20 @@ private unsafe void WriteUriAttributeText(char* pSrc, char* pSrcEnd) _endsWithAmpersand = false; } - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; char ch = (char)0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch < 0x80)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch < 0x80)) { *pDst++ = (byte)ch; pSrc++; @@ -653,7 +653,7 @@ private unsafe void WriteUriAttributeText(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -712,17 +712,17 @@ private unsafe void WriteUriAttributeText(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } // For handling &{ in Html text field. If & is not followed by {, it still needs to be escaped. private void OutputRestAmps() { - base.bufBytes[bufPos++] = (byte)'a'; - base.bufBytes[bufPos++] = (byte)'m'; - base.bufBytes[bufPos++] = (byte)'p'; - base.bufBytes[bufPos++] = (byte)';'; + base._bufBytes[_bufPos++] = (byte)'a'; + base._bufBytes[_bufPos++] = (byte)'m'; + base._bufBytes[_bufPos++] = (byte)'p'; + base._bufBytes[_bufPos++] = (byte)';'; } } @@ -797,67 +797,67 @@ public override void WriteDocType(string name, string pubid, string sysid, strin base.WriteDocType(name, pubid, sysid, subset); // Allow indentation after DocTypeDecl - _endBlockPos = base.bufPos; + _endBlockPos = base._bufPos; } public override void WriteStartElement(string prefix, string localName, string ns) { Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); - base.elementScope.Push((byte)base.currentElementProperties); + base._elementScope.Push((byte)base._currentElementProperties); if (ns.Length == 0) { Debug.Assert(prefix.Length == 0); - base.currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName); + base._currentElementProperties = (ElementProperties)_elementPropertySearch.FindCaseInsensitiveString(localName); - if (_endBlockPos == base.bufPos && (base.currentElementProperties & ElementProperties.BLOCK_WS) != 0) + if (_endBlockPos == base._bufPos && (base._currentElementProperties & ElementProperties.BLOCK_WS) != 0) { WriteIndent(); } _indentLevel++; - base.bufBytes[bufPos++] = (byte)'<'; + base._bufBytes[_bufPos++] = (byte)'<'; } else { - base.currentElementProperties = ElementProperties.HAS_NS | ElementProperties.BLOCK_WS; + base._currentElementProperties = ElementProperties.HAS_NS | ElementProperties.BLOCK_WS; - if (_endBlockPos == base.bufPos) + if (_endBlockPos == base._bufPos) { WriteIndent(); } _indentLevel++; - base.bufBytes[base.bufPos++] = (byte)'<'; + base._bufBytes[base._bufPos++] = (byte)'<'; if (prefix.Length != 0) { base.RawText(prefix); - base.bufBytes[base.bufPos++] = (byte)':'; + base._bufBytes[base._bufPos++] = (byte)':'; } } base.RawText(localName); - base.attrEndPos = bufPos; + base._attrEndPos = _bufPos; } internal override void StartElementContent() { - base.bufBytes[base.bufPos++] = (byte)'>'; + base._bufBytes[base._bufPos++] = (byte)'>'; // Detect whether content is output - base.contentPos = base.bufPos; + base._contentPos = base._bufPos; - if ((currentElementProperties & ElementProperties.HEAD) != 0) + if ((_currentElementProperties & ElementProperties.HEAD) != 0) { WriteIndent(); WriteMetaElement(); - _endBlockPos = base.bufPos; + _endBlockPos = base._bufPos; } - else if ((base.currentElementProperties & ElementProperties.BLOCK_WS) != 0) + else if ((base._currentElementProperties & ElementProperties.BLOCK_WS) != 0) { // store the element block position - _endBlockPos = base.bufPos; + _endBlockPos = base._bufPos; } } @@ -869,12 +869,12 @@ internal override void WriteEndElement(string prefix, string localName, string n _indentLevel--; // If this element has block whitespace properties, - isBlockWs = (base.currentElementProperties & ElementProperties.BLOCK_WS) != 0; + isBlockWs = (base._currentElementProperties & ElementProperties.BLOCK_WS) != 0; if (isBlockWs) { // And if the last node to be output had block whitespace properties, // And if content was output within this element, - if (_endBlockPos == base.bufPos && base.contentPos != base.bufPos) + if (_endBlockPos == base._bufPos && base._contentPos != base._bufPos) { // Then indent WriteIndent(); @@ -884,12 +884,12 @@ internal override void WriteEndElement(string prefix, string localName, string n base.WriteEndElement(prefix, localName, ns); // Reset contentPos in case of empty elements - base.contentPos = 0; + base._contentPos = 0; // Mark end of element in buffer for element's with block whitespace properties if (isBlockWs) { - _endBlockPos = base.bufPos; + _endBlockPos = base._bufPos; } } @@ -897,7 +897,7 @@ public override void WriteStartAttribute(string prefix, string localName, string { if (_newLineOnAttributes) { - RawText(base.newLineChars); + RawText(base._newLineChars); _indentLevel++; WriteIndent(); _indentLevel--; @@ -908,7 +908,7 @@ public override void WriteStartAttribute(string prefix, string localName, string protected override void FlushBuffer() { // Make sure the buffer will reset the block position - _endBlockPos = (_endBlockPos == base.bufPos) ? 1 : 0; + _endBlockPos = (_endBlockPos == base._bufPos) ? 1 : 0; base.FlushBuffer(); } @@ -936,7 +936,7 @@ private void WriteIndent() // -- suppress ws betw and PI // -- suppress ws betw and comment - RawText(base.newLineChars); + RawText(base._newLineChars); for (int i = _indentLevel; i > 0; i--) { RawText(_indentChars); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/IRemovableWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/IRemovableWriter.cs index affd635ff1e77..00666a5d34482 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/IRemovableWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/IRemovableWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml { /// diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/IValidationEventHandling.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/IValidationEventHandling.cs index 528cad5a3f02b..2b8f5d247b6e1 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/IValidationEventHandling.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/IValidationEventHandling.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Xml.Schema; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/IncrementalReadDecoders.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/IncrementalReadDecoders.cs index 912736c508147..4cf58e2b3a930 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/IncrementalReadDecoders.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/IncrementalReadDecoders.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Xml @@ -38,7 +39,7 @@ internal class IncrementalReadDummyDecoder : IncrementalReadDecoder // internal class IncrementalReadCharsDecoder : IncrementalReadDecoder { - private char[] _buffer; + private char[]? _buffer; private int _startIndex; private int _curIndex; private int _endIndex; @@ -61,6 +62,7 @@ internal override bool IsFull internal override int Decode(char[] chars, int startPos, int len) { + Debug.Assert(_buffer != null); Debug.Assert(chars != null); Debug.Assert(len >= 0); Debug.Assert(startPos >= 0); @@ -73,6 +75,7 @@ internal override int Decode(char[] chars, int startPos, int len) { copyCount = len; } + Buffer.BlockCopy(chars, startPos * 2, _buffer, _curIndex * 2, copyCount * 2); _curIndex += copyCount; @@ -81,6 +84,7 @@ internal override int Decode(char[] chars, int startPos, int len) internal override int Decode(string str, int startPos, int len) { + Debug.Assert(_buffer != null); Debug.Assert(str != null); Debug.Assert(len >= 0); Debug.Assert(startPos >= 0); @@ -93,6 +97,7 @@ internal override int Decode(string str, int startPos, int len) { copyCount = len; } + str.CopyTo(startPos, _buffer, _curIndex, copyCount); _curIndex += copyCount; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs index a36958ec93901..f17a495025efb 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/NamespaceHandling.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/NamespaceHandling.cs index 9fdb5af95a18b..9627334206f0a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/NamespaceHandling.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/NamespaceHandling.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml { // diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriter.cs index ea8030fe3f539..9ab4c5b35bcf7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml { using System; @@ -24,9 +25,9 @@ internal class QueryOutputWriter : XmlRawWriter { private readonly XmlRawWriter _wrapped; private bool _inCDataSection; - private readonly Dictionary _lookupCDataElems; - private readonly BitStack _bitsCData; - private readonly XmlQualifiedName _qnameCData; + private readonly Dictionary? _lookupCDataElems; + private readonly BitStack? _bitsCData; + private readonly XmlQualifiedName? _qnameCData; private bool _outputDocType; private readonly bool _checkWellFormedDoc; private bool _hasDocElem; @@ -86,15 +87,15 @@ public QueryOutputWriter(XmlRawWriter writer, XmlWriterSettings settings) /// /// Get and set the namespace resolver that's used by this RawWriter to resolve prefixes. /// - internal override IXmlNamespaceResolver NamespaceResolver + internal override IXmlNamespaceResolver? NamespaceResolver { get { - return this.resolver; + return this._resolver; } set { - this.resolver = value; + this._resolver = value; _wrapped.NamespaceResolver = value; } } @@ -119,7 +120,7 @@ public override XmlWriterSettings Settings { get { - XmlWriterSettings settings = _wrapped.Settings; + XmlWriterSettings settings = _wrapped.Settings!; settings.ReadOnly = false; settings.DocTypeSystem = _systemId; @@ -133,7 +134,7 @@ public override XmlWriterSettings Settings /// /// Suppress this explicit call to WriteDocType if information was provided by XmlWriterSettings. /// - public override void WriteDocType(string name, string pubid, string sysid, string subset) + public override void WriteDocType(string name, string? pubid, string? sysid, string? subset) { if (_publicId == null && _systemId == null) { @@ -146,7 +147,7 @@ public override void WriteDocType(string name, string pubid, string sysid, strin /// Check well-formedness, possibly output doc-type-decl, and determine whether this element is a /// CData section element. /// - public override void WriteStartElement(string prefix, string localName, string ns) + public override void WriteStartElement(string? prefix, string localName, string? ns) { EndCDataSection(); @@ -164,7 +165,7 @@ public override void WriteStartElement(string prefix, string localName, string n if (_outputDocType) { _wrapped.WriteDocType( - prefix.Length != 0 ? prefix + ":" + localName : localName, + string.IsNullOrEmpty(prefix) ? localName : prefix + ":" + localName, _publicId, _systemId, null); @@ -177,8 +178,8 @@ public override void WriteStartElement(string prefix, string localName, string n if (_lookupCDataElems != null) { // Determine whether this element is a CData section element - _qnameCData.Init(localName, ns); - _bitsCData.PushBit(_lookupCDataElems.ContainsKey(_qnameCData)); + _qnameCData!.Init(localName, ns); + _bitsCData!.PushBit(_lookupCDataElems.ContainsKey(_qnameCData)); } } @@ -192,7 +193,7 @@ internal override void WriteEndElement(string prefix, string localName, string n _depth--; if (_lookupCDataElems != null) - _bitsCData.PopBit(); + _bitsCData!.PopBit(); } internal override void WriteFullEndElement(string prefix, string localName, string ns) @@ -205,7 +206,7 @@ internal override void WriteFullEndElement(string prefix, string localName, stri _depth--; if (_lookupCDataElems != null) - _bitsCData.PopBit(); + _bitsCData!.PopBit(); } internal override void StartElementContent() @@ -213,7 +214,7 @@ internal override void StartElementContent() _wrapped.StartElementContent(); } - public override void WriteStartAttribute(string prefix, string localName, string ns) + public override void WriteStartAttribute(string? prefix, string localName, string? ns) { _inAttr = true; _wrapped.WriteStartAttribute(prefix, localName, ns); @@ -248,7 +249,7 @@ internal override void WriteEndNamespaceDeclaration() _wrapped.WriteEndNamespaceDeclaration(); } - public override void WriteCData(string text) + public override void WriteCData(string? text) { _wrapped.WriteCData(text); } @@ -273,7 +274,7 @@ public override void WriteWhitespace(string ws) _wrapped.WriteWhitespace(ws); } - public override void WriteString(string text) + public override void WriteString(string? text) { if (!_inAttr && (_inCDataSection || StartCDataSection())) _wrapped.WriteCData(text); @@ -351,7 +352,7 @@ public override void Flush() private bool StartCDataSection() { Debug.Assert(!_inCDataSection); - if (_lookupCDataElems != null && _bitsCData.PeekBit()) + if (_lookupCDataElems != null && _bitsCData!.PeekBit()) { _inCDataSection = true; return true; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriterV1.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriterV1.cs index 462854bc4c554..4f6ea549c7459 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriterV1.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/QueryOutputWriterV1.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Diagnostics; @@ -25,9 +26,9 @@ internal class QueryOutputWriterV1 : XmlWriter { private readonly XmlWriter _wrapped; private bool _inCDataSection; - private readonly Dictionary _lookupCDataElems; - private readonly BitStack _bitsCData; - private readonly XmlQualifiedName _qnameCData; + private readonly Dictionary? _lookupCDataElems; + private readonly BitStack? _bitsCData; + private readonly XmlQualifiedName? _qnameCData; private bool _outputDocType, _inAttr; private readonly string _systemId, _publicId; @@ -71,7 +72,7 @@ public QueryOutputWriterV1(XmlWriter writer, XmlWriterSettings settings) if (settings.CDataSectionElements != null && settings.CDataSectionElements.Count > 0) { _bitsCData = new BitStack(); - _lookupCDataElems = new Dictionary(); + _lookupCDataElems = new Dictionary(); _qnameCData = new XmlQualifiedName(); // Add each element name to the lookup table @@ -122,7 +123,7 @@ public override void WriteEndDocument() /// /// Suppress this explicit call to WriteDocType if information was provided by XmlWriterSettings. /// - public override void WriteDocType(string name, string pubid, string sysid, string subset) + public override void WriteDocType(string name, string? pubid, string? sysid, string? subset) { if (_publicId == null && _systemId == null) { @@ -135,7 +136,7 @@ public override void WriteDocType(string name, string pubid, string sysid, strin /// Output doc-type-decl on the first element, and determine whether this element is a /// CData section element. /// - public override void WriteStartElement(string prefix, string localName, string ns) + public override void WriteStartElement(string? prefix, string localName, string? ns) { EndCDataSection(); @@ -146,11 +147,12 @@ public override void WriteStartElement(string prefix, string localName, string n if (ws == WriteState.Start || ws == WriteState.Prolog) { _wrapped.WriteDocType( - prefix.Length != 0 ? prefix + ":" + localName : localName, + string.IsNullOrEmpty(prefix) ? localName : prefix + ":" + localName, _publicId, _systemId, null); } + _outputDocType = false; } @@ -158,6 +160,9 @@ public override void WriteStartElement(string prefix, string localName, string n if (_lookupCDataElems != null) { + Debug.Assert(_qnameCData != null); + Debug.Assert(_bitsCData != null); + // Determine whether this element is a CData section element _qnameCData.Init(localName, ns); _bitsCData.PushBit(_lookupCDataElems.ContainsKey(_qnameCData)); @@ -171,7 +176,10 @@ public override void WriteEndElement() _wrapped.WriteEndElement(); if (_lookupCDataElems != null) + { + Debug.Assert(_bitsCData != null); _bitsCData.PopBit(); + } } public override void WriteFullEndElement() @@ -181,10 +189,13 @@ public override void WriteFullEndElement() _wrapped.WriteFullEndElement(); if (_lookupCDataElems != null) + { + Debug.Assert(_bitsCData != null); _bitsCData.PopBit(); + } } - public override void WriteStartAttribute(string prefix, string localName, string ns) + public override void WriteStartAttribute(string? prefix, string localName, string? ns) { _inAttr = true; _wrapped.WriteStartAttribute(prefix, localName, ns); @@ -196,7 +207,7 @@ public override void WriteEndAttribute() _wrapped.WriteEndAttribute(); } - public override void WriteCData(string text) + public override void WriteCData(string? text) { _wrapped.WriteCData(text); } @@ -221,7 +232,7 @@ public override void WriteWhitespace(string ws) _wrapped.WriteWhitespace(ws); } - public override void WriteString(string text) + public override void WriteString(string? text) { if (!_inAttr && (_inCDataSection || StartCDataSection())) _wrapped.WriteCData(text); @@ -291,7 +302,7 @@ public override void Flush() _wrapped.Flush(); } - public override string LookupPrefix(string ns) + public override string? LookupPrefix(string ns) { return _wrapped.LookupPrefix(ns); } @@ -308,11 +319,12 @@ public override string LookupPrefix(string ns) private bool StartCDataSection() { Debug.Assert(!_inCDataSection); - if (_lookupCDataElems != null && _bitsCData.PeekBit()) + if (_lookupCDataElems != null && _bitsCData!.PeekBit()) { _inCDataSection = true; return true; } + return false; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/RawTextWriterEncoded.ttinclude b/src/libraries/System.Private.Xml/src/System/Xml/Core/RawTextWriterEncoded.ttinclude index a3bd4d0b67053..bfb440689a66e 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/RawTextWriterEncoded.ttinclude +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/RawTextWriterEncoded.ttinclude @@ -5,7 +5,7 @@ WriterType = RawTextWriterType.Encoded; ClassName = "XmlEncodedRawTextWriter"; ClassNameIndent = "XmlEncodedRawTextWriterIndent"; - BufferName = "bufChars"; + BufferName = "_bufChars"; BufferType = "char"; EncodeCharBody = @"/* Surrogate character */ if (XmlCharType.IsSurrogate(ch)) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/TextEncodedRawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/TextEncodedRawTextWriter.cs index 2059fc771e495..bc9cbc38851ef 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/TextEncodedRawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/TextEncodedRawTextWriter.cs @@ -67,12 +67,12 @@ internal override void StartElementContent() // Ignore attributes public override void WriteStartAttribute(string prefix, string localName, string ns) { - base.inAttributeValue = true; + base._inAttributeValue = true; } public override void WriteEndAttribute() { - base.inAttributeValue = false; + base._inAttributeValue = false; } // Ignore namespace declarations @@ -118,7 +118,7 @@ public override void WriteSurrogateCharEntity(char lowChar, char highChar) // Output text content without any escaping; ignore attribute values public override void WriteWhitespace(string ws) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(ws); } @@ -127,7 +127,7 @@ public override void WriteWhitespace(string ws) // Output text content without any escaping; ignore attribute values public override void WriteString(string textBlock) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(textBlock); } @@ -136,7 +136,7 @@ public override void WriteString(string textBlock) // Output text content without any escaping; ignore attribute values public override void WriteChars(char[] buffer, int index, int count) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(buffer, index, count); } @@ -145,7 +145,7 @@ public override void WriteChars(char[] buffer, int index, int count) // Output text content without any escaping; ignore attribute values public override void WriteRaw(char[] buffer, int index, int count) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(buffer, index, count); } @@ -154,7 +154,7 @@ public override void WriteRaw(char[] buffer, int index, int count) // Output text content without any escaping; ignore attribute values public override void WriteRaw(string data) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(data); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/TextUtf8RawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/TextUtf8RawTextWriter.cs index 776f810949d27..b7df1c67074dc 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/TextUtf8RawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/TextUtf8RawTextWriter.cs @@ -62,12 +62,12 @@ internal override void StartElementContent() // Ignore attributes public override void WriteStartAttribute(string prefix, string localName, string ns) { - base.inAttributeValue = true; + base._inAttributeValue = true; } public override void WriteEndAttribute() { - base.inAttributeValue = false; + base._inAttributeValue = false; } // Ignore namespace declarations @@ -113,7 +113,7 @@ public override void WriteSurrogateCharEntity(char lowChar, char highChar) // Output text content without any escaping; ignore attribute values public override void WriteWhitespace(string ws) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(ws); } @@ -122,7 +122,7 @@ public override void WriteWhitespace(string ws) // Output text content without any escaping; ignore attribute values public override void WriteString(string textBlock) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(textBlock); } @@ -131,7 +131,7 @@ public override void WriteString(string textBlock) // Output text content without any escaping; ignore attribute values public override void WriteChars(char[] buffer, int index, int count) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(buffer, index, count); } @@ -140,7 +140,7 @@ public override void WriteChars(char[] buffer, int index, int count) // Output text content without any escaping; ignore attribute values public override void WriteRaw(char[] buffer, int index, int count) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(buffer, index, count); } @@ -149,7 +149,7 @@ public override void WriteRaw(char[] buffer, int index, int count) // Output text content without any escaping; ignore attribute values public override void WriteRaw(string data) { - if (!base.inAttributeValue) + if (!base._inAttributeValue) { base.WriteRaw(data); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlAutoDetectWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlAutoDetectWriter.cs index dee8b8e5a6ffb..62355d7b66b5f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlAutoDetectWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlAutoDetectWriter.cs @@ -277,11 +277,11 @@ internal override IXmlNamespaceResolver NamespaceResolver { get { - return this.resolver; + return this._resolver; } set { - this.resolver = value; + this._resolver = value; if (_wrapped == null) _eventCache.NamespaceResolver = value; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs index 713f5bcc262af..18d0cc012ba14 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs @@ -31,60 +31,60 @@ internal partial class XmlEncodedRawTextWriter : XmlRawWriter private readonly bool _useAsync; // main buffer - protected byte[] bufBytes; + protected byte[] _bufBytes; // output stream - protected Stream stream; + protected Stream _stream; // encoding of the stream or text writer - protected Encoding encoding; + protected Encoding _encoding; // char type tables - protected XmlCharType xmlCharType = XmlCharType.Instance; + protected XmlCharType _xmlCharType = XmlCharType.Instance; // buffer positions - protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to - // close an empty element or in CDATA section detection of double ]; bufChars[0] will always be 0 - protected int textPos = 1; // text end position; don't indent first element, pi, or comment - protected int contentPos; // element content end position - protected int cdataPos; // cdata end position - protected int attrEndPos; // end of the last attribute - protected int bufLen = BUFSIZE; + protected int _bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + // close an empty element or in CDATA section detection of double ]; bufChars[0] will always be 0 + protected int _textPos = 1; // text end position; don't indent first element, pi, or comment + protected int _contentPos; // element content end position + protected int _cdataPos; // cdata end position + protected int _attrEndPos; // end of the last attribute + protected int _bufLen = BUFSIZE; // flags - protected bool writeToNull; - protected bool hadDoubleBracket; - protected bool inAttributeValue; + protected bool _writeToNull; + protected bool _hadDoubleBracket; + protected bool _inAttributeValue; - protected int bufBytesUsed; - protected char[] bufChars; + protected int _bufBytesUsed; + protected char[] _bufChars; // encoder for encoding chars in specified encoding when writing to stream - protected Encoder encoder; + protected Encoder _encoder; // output text writer - protected TextWriter writer; + protected TextWriter _writer; // escaping of characters invalid in the output encoding - protected bool trackTextContent; - protected bool inTextContent; + protected bool _trackTextContent; + protected bool _inTextContent; private int _lastMarkPos; private int[] _textContentMarks; // even indices contain text content start positions // odd indices contain markup start positions private readonly CharEntityEncoderFallback _charEntityFallback; // writer settings - protected NewLineHandling newLineHandling; - protected bool closeOutput; - protected bool omitXmlDeclaration; - protected string newLineChars; - protected bool checkCharacters; + protected NewLineHandling _newLineHandling; + protected bool _closeOutput; + protected bool _omitXmlDeclaration; + protected string _newLineChars; + protected bool _checkCharacters; - protected XmlStandalone standalone; - protected XmlOutputMethod outputMethod; + protected XmlStandalone _standalone; + protected XmlOutputMethod _outputMethod; - protected bool autoXmlDeclaration; - protected bool mergeCDataSections; + protected bool _autoXmlDeclaration; + protected bool _mergeCDataSections; // // Constants @@ -103,19 +103,19 @@ protected XmlEncodedRawTextWriter(XmlWriterSettings settings) _useAsync = settings.Async; // copy settings - newLineHandling = settings.NewLineHandling; - omitXmlDeclaration = settings.OmitXmlDeclaration; - newLineChars = settings.NewLineChars; - checkCharacters = settings.CheckCharacters; - closeOutput = settings.CloseOutput; + _newLineHandling = settings.NewLineHandling; + _omitXmlDeclaration = settings.OmitXmlDeclaration; + _newLineChars = settings.NewLineChars; + _checkCharacters = settings.CheckCharacters; + _closeOutput = settings.CloseOutput; - standalone = settings.Standalone; - outputMethod = settings.OutputMethod; - mergeCDataSections = settings.MergeCDataSections; + _standalone = settings.Standalone; + _outputMethod = settings.OutputMethod; + _mergeCDataSections = settings.MergeCDataSections; - if (checkCharacters && newLineHandling == NewLineHandling.Replace) + if (_checkCharacters && _newLineHandling == NewLineHandling.Replace) { - ValidateContentChars(newLineChars, "NewLineChars", false); + ValidateContentChars(_newLineChars, "NewLineChars", false); } } @@ -124,20 +124,20 @@ public XmlEncodedRawTextWriter(TextWriter writer, XmlWriterSettings settings) : { Debug.Assert(writer != null && settings != null); - this.writer = writer; - this.encoding = writer.Encoding; + this._writer = writer; + this._encoding = writer.Encoding; // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup if (settings.Async) { - bufLen = ASYNCBUFSIZE; + _bufLen = ASYNCBUFSIZE; } - this.bufChars = new char[bufLen + OVERFLOW]; + this._bufChars = new char[_bufLen + OVERFLOW]; // Write the xml declaration if (settings.AutoXmlDeclaration) { - WriteXmlDeclaration(standalone); - autoXmlDeclaration = true; + WriteXmlDeclaration(_standalone); + _autoXmlDeclaration = true; } } @@ -146,22 +146,22 @@ public XmlEncodedRawTextWriter(Stream stream, XmlWriterSettings settings) : this { Debug.Assert(stream != null && settings != null); - this.stream = stream; - this.encoding = settings.Encoding; + this._stream = stream; + this._encoding = settings.Encoding; // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup if (settings.Async) { - bufLen = ASYNCBUFSIZE; + _bufLen = ASYNCBUFSIZE; } - bufChars = new char[bufLen + OVERFLOW]; - bufBytes = new byte[bufChars.Length]; - bufBytesUsed = 0; + _bufChars = new char[_bufLen + OVERFLOW]; + _bufBytes = new byte[_bufChars.Length]; + _bufBytesUsed = 0; // Init escaping of characters not fitting into the target encoding - trackTextContent = true; - inTextContent = false; + _trackTextContent = true; + _inTextContent = false; _lastMarkPos = 0; _textContentMarks = new int[INIT_MARKS_COUNT]; _textContentMarks[0] = 1; @@ -169,29 +169,29 @@ public XmlEncodedRawTextWriter(Stream stream, XmlWriterSettings settings) : this _charEntityFallback = new CharEntityEncoderFallback(); // grab bom before possibly changing encoding settings - ReadOnlySpan bom = encoding.Preamble; + ReadOnlySpan bom = _encoding.Preamble; // the encoding instance this creates can differ from the one passed in - this.encoding = Encoding.GetEncoding( + this._encoding = Encoding.GetEncoding( settings.Encoding.CodePage, _charEntityFallback, settings.Encoding.DecoderFallback); - encoder = encoding.GetEncoder(); + _encoder = _encoding.GetEncoder(); if (!stream.CanSeek || stream.Position == 0) { if (bom.Length != 0) { - this.stream.Write(bom); + this._stream.Write(bom); } } // Write the xml declaration if (settings.AutoXmlDeclaration) { - WriteXmlDeclaration(standalone); - autoXmlDeclaration = true; + WriteXmlDeclaration(_standalone); + _autoXmlDeclaration = true; } } @@ -205,17 +205,17 @@ public override XmlWriterSettings Settings { XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = encoding; - settings.OmitXmlDeclaration = omitXmlDeclaration; - settings.NewLineHandling = newLineHandling; - settings.NewLineChars = newLineChars; - settings.CloseOutput = closeOutput; + settings.Encoding = _encoding; + settings.OmitXmlDeclaration = _omitXmlDeclaration; + settings.NewLineHandling = _newLineHandling; + settings.NewLineChars = _newLineChars; + settings.CloseOutput = _closeOutput; settings.ConformanceLevel = ConformanceLevel.Auto; - settings.CheckCharacters = checkCharacters; + settings.CheckCharacters = _checkCharacters; - settings.AutoXmlDeclaration = autoXmlDeclaration; - settings.Standalone = standalone; - settings.OutputMethod = outputMethod; + settings.AutoXmlDeclaration = _autoXmlDeclaration; + settings.Standalone = _standalone; + settings.OutputMethod = _outputMethod; settings.ReadOnly = true; return settings; @@ -226,9 +226,9 @@ public override XmlWriterSettings Settings internal override void WriteXmlDeclaration(XmlStandalone standalone) { // Output xml declaration only if user allows it and it was not already output - if (!omitXmlDeclaration && !autoXmlDeclaration) + if (!_omitXmlDeclaration && !_autoXmlDeclaration) { - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } RawText(" 0); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } RawText("'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize the beginning of an element start tag: " 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'<'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - bufChars[bufPos++] = (char)':'; + _bufChars[_bufPos++] = (char)':'; } RawText(localName); - attrEndPos = bufPos; + _attrEndPos = _bufPos; } // Serialize the end of an element start tag in preparation for content serialization: ">" internal override void StartElementContent() { - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'>'; // StartElementContent is always called; therefore, in order to allow shortcut syntax, we save the // position of the '>' character. If WriteEndElement is called and no other characters have been // output, then the '>' character can be overwritten with the shortcut syntax " />". - contentPos = bufPos; + _contentPos = _bufPos; } // Serialize an element end tag: "", if content was output. Otherwise, serialize @@ -341,29 +341,29 @@ internal override void WriteEndElement(string prefix, string localName, string n Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (contentPos != bufPos) + if (_contentPos != _bufPos) { // Content has been output, so can't use shortcut syntax - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'/'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'/'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - bufChars[bufPos++] = (char)':'; + _bufChars[_bufPos++] = (char)':'; } RawText(localName); - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'>'; } else { // Use shortcut syntax; overwrite the already output '>' character - bufPos--; - bufChars[bufPos++] = (char)' '; - bufChars[bufPos++] = (char)'/'; - bufChars[bufPos++] = (char)'>'; + _bufPos--; + _bufChars[_bufPos++] = (char)' '; + _bufChars[_bufPos++] = (char)'/'; + _bufChars[_bufPos++] = (char)'>'; } } @@ -373,18 +373,18 @@ internal override void WriteFullEndElement(string prefix, string localName, stri Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'/'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'/'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - bufChars[bufPos++] = (char)':'; + _bufChars[_bufPos++] = (char)':'; } RawText(localName); - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="' @@ -393,33 +393,33 @@ public override void WriteStartAttribute(string prefix, string localName, string Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (attrEndPos == bufPos) + if (_attrEndPos == _bufPos) { - bufChars[bufPos++] = (char)' '; + _bufChars[_bufPos++] = (char)' '; } if (prefix != null && prefix.Length > 0) { RawText(prefix); - bufChars[bufPos++] = (char)':'; + _bufChars[_bufPos++] = (char)':'; } RawText(localName); - bufChars[bufPos++] = (char)'='; - bufChars[bufPos++] = (char)'"'; + _bufChars[_bufPos++] = (char)'='; + _bufChars[_bufPos++] = (char)'"'; - inAttributeValue = true; + _inAttributeValue = true; } // Serialize the end of an attribute value using double quotes: '"' public override void WriteEndAttribute() { - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'"'; - inAttributeValue = false; - attrEndPos = bufPos; + _bufChars[_bufPos++] = (char)'"'; + _inAttributeValue = false; + _attrEndPos = _bufPos; } internal override void WriteNamespaceDeclaration(string prefix, string namespaceName) @@ -443,7 +443,7 @@ internal override void WriteStartNamespaceDeclaration(string prefix) { Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } if (prefix.Length == 0) { @@ -453,22 +453,22 @@ internal override void WriteStartNamespaceDeclaration(string prefix) { RawText(" xmlns:"); RawText(prefix); - bufChars[bufPos++] = (char)'='; - bufChars[bufPos++] = (char)'"'; + _bufChars[_bufPos++] = (char)'='; + _bufChars[_bufPos++] = (char)'"'; } - inAttributeValue = true; + _inAttributeValue = true; - if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); } + if (_trackTextContent && _inTextContent != true) { ChangeTextContentMark(true); } } internal override void WriteEndNamespaceDeclaration() { - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } - inAttributeValue = false; + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } + _inAttributeValue = false; - bufChars[bufPos++] = (char)'"'; - attrEndPos = bufPos; + _bufChars[_bufPos++] = (char)'"'; + _attrEndPos = _bufPos; } // Serialize a CData section. If the "]]>" pattern is found within @@ -477,36 +477,36 @@ public override void WriteCData(string text) { Debug.Assert(text != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (mergeCDataSections && bufPos == cdataPos) + if (_mergeCDataSections && _bufPos == _cdataPos) { // Merge adjacent cdata sections - overwrite the "]]>" characters - Debug.Assert(bufPos >= 4); - bufPos -= 3; + Debug.Assert(_bufPos >= 4); + _bufPos -= 3; } else { // Start a new cdata section - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'!'; - bufChars[bufPos++] = (char)'['; - bufChars[bufPos++] = (char)'C'; - bufChars[bufPos++] = (char)'D'; - bufChars[bufPos++] = (char)'A'; - bufChars[bufPos++] = (char)'T'; - bufChars[bufPos++] = (char)'A'; - bufChars[bufPos++] = (char)'['; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'!'; + _bufChars[_bufPos++] = (char)'['; + _bufChars[_bufPos++] = (char)'C'; + _bufChars[_bufPos++] = (char)'D'; + _bufChars[_bufPos++] = (char)'A'; + _bufChars[_bufPos++] = (char)'T'; + _bufChars[_bufPos++] = (char)'A'; + _bufChars[_bufPos++] = (char)'['; } WriteCDataSection(text); - bufChars[bufPos++] = (char)']'; - bufChars[bufPos++] = (char)']'; - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)']'; + _bufChars[_bufPos++] = (char)']'; + _bufChars[_bufPos++] = (char)'>'; - textPos = bufPos; - cdataPos = bufPos; + _textPos = _bufPos; + _cdataPos = _bufPos; } // Serialize a comment. @@ -514,18 +514,18 @@ public override void WriteComment(string text) { Debug.Assert(text != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'!'; - bufChars[bufPos++] = (char)'-'; - bufChars[bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'!'; + _bufChars[_bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'-'; WriteCommentOrPi(text, '-'); - bufChars[bufPos++] = (char)'-'; - bufChars[bufPos++] = (char)'-'; - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize a processing instruction. @@ -534,20 +534,20 @@ public override void WriteProcessingInstruction(string name, string text) Debug.Assert(name != null && name.Length > 0); Debug.Assert(text != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'?'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'?'; RawText(name); if (text.Length > 0) { - bufChars[bufPos++] = (char)' '; + _bufChars[_bufPos++] = (char)' '; WriteCommentOrPi(text, '?'); } - bufChars[bufPos++] = (char)'?'; - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'?'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize an entity reference. @@ -555,18 +555,18 @@ public override void WriteEntityRef(string name) { Debug.Assert(name != null && name.Length > 0); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'&'; + _bufChars[_bufPos++] = (char)'&'; RawText(name); - bufChars[bufPos++] = (char)';'; + _bufChars[_bufPos++] = (char)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { FlushBuffer(); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a character entity reference. @@ -574,26 +574,26 @@ public override void WriteCharEntity(char ch) { string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); - if (checkCharacters && !xmlCharType.IsCharData(ch)) + if (_checkCharacters && !_xmlCharType.IsCharData(ch)) { // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char throw XmlConvert.CreateInvalidCharException(ch, '\0'); } - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'&'; - bufChars[bufPos++] = (char)'#'; - bufChars[bufPos++] = (char)'x'; + _bufChars[_bufPos++] = (char)'&'; + _bufChars[_bufPos++] = (char)'#'; + _bufChars[_bufPos++] = (char)'x'; RawText(strVal); - bufChars[bufPos++] = (char)';'; + _bufChars[_bufPos++] = (char)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { FlushBuffer(); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a whitespace node. @@ -602,12 +602,12 @@ public override unsafe void WriteWhitespace(string ws) { Debug.Assert(ws != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } fixed (char* pSrc = ws) { char* pSrcEnd = pSrc + ws.Length; - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -624,12 +624,12 @@ public override unsafe void WriteString(string text) { Debug.Assert(text != null); - if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); } + if (_trackTextContent && _inTextContent != true) { ChangeTextContentMark(true); } fixed (char* pSrc = text) { char* pSrcEnd = pSrc + text.Length; - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -643,15 +643,15 @@ public override unsafe void WriteString(string text) // Serialize surrogate character entity. public override void WriteSurrogateCharEntity(char lowChar, char highChar) { - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar); - bufChars[bufPos++] = (char)'&'; - bufChars[bufPos++] = (char)'#'; - bufChars[bufPos++] = (char)'x'; + _bufChars[_bufPos++] = (char)'&'; + _bufChars[_bufPos++] = (char)'#'; + _bufChars[_bufPos++] = (char)'x'; RawText(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)); - bufChars[bufPos++] = (char)';'; - textPos = bufPos; + _bufChars[_bufPos++] = (char)';'; + _textPos = _bufPos; } // Serialize either attribute or element text using XML rules. @@ -663,11 +663,11 @@ public override unsafe void WriteChars(char[] buffer, int index, int count) Debug.Assert(index >= 0); Debug.Assert(count >= 0 && index + count <= buffer.Length); - if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); } + if (_trackTextContent && _inTextContent != true) { ChangeTextContentMark(true); } fixed (char* pSrcBegin = &buffer[index]) { - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count); } @@ -687,14 +687,14 @@ public override unsafe void WriteRaw(char[] buffer, int index, int count) Debug.Assert(index >= 0); Debug.Assert(count >= 0 && index + count <= buffer.Length); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } fixed (char* pSrcBegin = &buffer[index]) { WriteRawWithCharChecking(pSrcBegin, pSrcBegin + count); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize raw data. @@ -703,14 +703,14 @@ public override unsafe void WriteRaw(string data) { Debug.Assert(data != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } fixed (char* pSrcBegin = data) { WriteRawWithCharChecking(pSrcBegin, pSrcBegin + data.Length); } - textPos = bufPos; + _textPos = _bufPos; } // Flush all bytes in the buffer to output and close the output stream or writer. @@ -724,47 +724,47 @@ public override void Close() finally { // Future calls to Close or Flush shouldn't write to Stream or Writer - writeToNull = true; + _writeToNull = true; - if (stream != null) + if (_stream != null) { try { - stream.Flush(); + _stream.Flush(); } finally { try { - if (closeOutput) + if (_closeOutput) { - stream.Dispose(); + _stream.Dispose(); } } finally { - stream = null; + _stream = null; } } } - else if (writer != null) + else if (_writer != null) { try { - writer.Flush(); + _writer.Flush(); } finally { try { - if (closeOutput) + if (_closeOutput) { - writer.Dispose(); + _writer.Dispose(); } } finally { - writer = null; + _writer = null; } } } @@ -776,13 +776,13 @@ public override void Flush() { FlushBuffer(); FlushEncoder(); - if (stream != null) + if (_stream != null) { - stream.Flush(); + _stream.Flush(); } - else if (writer != null) + else if (_writer != null) { - writer.Flush(); + _writer.Flush(); } } @@ -795,13 +795,13 @@ protected virtual void FlushBuffer() try { // Output all characters (except for previous characters stored at beginning of buffer) - if (!writeToNull) + if (!_writeToNull) { - Debug.Assert(stream != null || writer != null); + Debug.Assert(_stream != null || _writer != null); - if (stream != null) + if (_stream != null) { - if (trackTextContent) + if (_trackTextContent) { _charEntityFallback.Reset(_textContentMarks, _lastMarkPos); // reset text content tracking @@ -819,14 +819,14 @@ protected virtual void FlushBuffer() } Debug.Assert(_textContentMarks[0] == 1); } - EncodeChars(1, bufPos, true); + EncodeChars(1, _bufPos, true); } else { - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { // Write text to TextWriter - writer.Write(bufChars, 1, bufPos - 1); + _writer.Write(_bufChars, 1, _bufPos - 1); } } } @@ -834,20 +834,20 @@ protected virtual void FlushBuffer() catch { // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream - writeToNull = true; + _writeToNull = true; throw; } finally { // Move last buffer character to the beginning of the buffer (so that previous character can always be determined) - bufChars[0] = bufChars[bufPos - 1]; + _bufChars[0] = _bufChars[_bufPos - 1]; // Reset buffer position - textPos = (textPos == bufPos) ? 1 : 0; - attrEndPos = (attrEndPos == bufPos) ? 1 : 0; - contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible - cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible - bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + _textPos = (_textPos == _bufPos) ? 1 : 0; + _attrEndPos = (_attrEndPos == _bufPos) ? 1 : 0; + _contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible + _cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible + _bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to // close an empty element or in CDATA section detection of double ]; bufChars[0] will always be 0 } } @@ -864,35 +864,35 @@ private void EncodeChars(int startOffset, int endOffset, bool writeAllToStream) { _charEntityFallback.StartOffset = startOffset; } - encoder.Convert(bufChars, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed); + _encoder.Convert(_bufChars, startOffset, endOffset - startOffset, _bufBytes, _bufBytesUsed, _bufBytes.Length - _bufBytesUsed, false, out chEnc, out bEnc, out completed); startOffset += chEnc; - bufBytesUsed += bEnc; - if (bufBytesUsed >= (bufBytes.Length - 16)) + _bufBytesUsed += bEnc; + if (_bufBytesUsed >= (_bufBytes.Length - 16)) { - stream.Write(bufBytes, 0, bufBytesUsed); - bufBytesUsed = 0; + _stream.Write(_bufBytes, 0, _bufBytesUsed); + _bufBytesUsed = 0; } } - if (writeAllToStream && bufBytesUsed > 0) + if (writeAllToStream && _bufBytesUsed > 0) { - stream.Write(bufBytes, 0, bufBytesUsed); - bufBytesUsed = 0; + _stream.Write(_bufBytes, 0, _bufBytesUsed); + _bufBytesUsed = 0; } } private void FlushEncoder() { - Debug.Assert(bufPos == 1); - if (stream != null) + Debug.Assert(_bufPos == 1); + if (_stream != null) { int chEnc; int bEnc; bool completed; // decode no chars, just flush - encoder.Convert(bufChars, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed); + _encoder.Convert(_bufChars, 1, 0, _bufBytes, 0, _bufBytes.Length, true, out chEnc, out bEnc, out completed); if (bEnc != 0) { - stream.Write(bufBytes, 0, bEnc); + _stream.Write(_bufBytes, 0, bEnc); } } } @@ -901,20 +901,20 @@ private void FlushEncoder() // are entitized. protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) { - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) { *pDst = (char)ch; pDst++; @@ -931,7 +931,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -957,7 +957,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) pDst++; break; case (char)0x9: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (char)ch; pDst++; @@ -969,7 +969,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) } break; case (char)0xD: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (char)ch; pDst++; @@ -981,7 +981,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (char)ch; pDst++; @@ -1016,7 +1016,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1024,20 +1024,20 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) // are entitized. protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) { - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) { *pDst = (char)ch; pDst++; @@ -1054,7 +1054,7 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1079,7 +1079,7 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) pDst++; break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1090,7 +1090,7 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) } break; case (char)0xD: - switch (newLineHandling) + switch (_newLineHandling) { case NewLineHandling.Replace: // Replace "\r\n", or "\r" with NewLineChars @@ -1136,9 +1136,9 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); - textPos = bufPos; - contentPos = 0; + _bufPos = (int)(pDst - pDstBegin); + _textPos = _bufPos; + _contentPos = 0; } } @@ -1154,18 +1154,18 @@ protected unsafe void RawText(string s) protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd) { - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; char* pSrc = pSrcBegin; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } while (pDst < pDstEnd && ((ch = *pSrc) < XmlCharType.SurHighStart)) @@ -1185,7 +1185,7 @@ protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1212,27 +1212,27 @@ protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd) } } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) { - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { char* pSrc = pSrcBegin; - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && xmlCharType.IsTextChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsTextChar((char)(ch = *pSrc))) { *pDst = (char)ch; pDst++; @@ -1250,7 +1250,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1267,7 +1267,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1284,7 +1284,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1318,7 +1318,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1326,7 +1326,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { FlushBuffer(); } @@ -1335,24 +1335,24 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) // write text fixed (char* pSrcBegin = text) - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { char* pSrc = pSrcBegin; char* pSrcEnd = pSrcBegin + text.Length; - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) { *pDst = (char)ch; pDst++; @@ -1370,7 +1370,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1410,7 +1410,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1427,7 +1427,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1467,7 +1467,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1475,7 +1475,7 @@ protected unsafe void WriteCDataSection(string text) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { FlushBuffer(); } @@ -1486,24 +1486,24 @@ protected unsafe void WriteCDataSection(string text) fixed (char* pSrcBegin = text) - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { char* pSrc = pSrcBegin; char* pSrcEnd = pSrcBegin + text.Length; - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) { *pDst = (char)ch; pDst++; @@ -1521,7 +1521,7 @@ protected unsafe void WriteCDataSection(string text) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1531,7 +1531,7 @@ protected unsafe void WriteCDataSection(string text) switch (ch) { case '>': - if (hadDoubleBracket && pDst[-1] == (char)']') + if (_hadDoubleBracket && pDst[-1] == (char)']') { // pDst[-1] will always correct - there is a padding character at bufChars[0] // The characters "]]>" were found within the CData text pDst = RawEndCData(pDst); @@ -1543,17 +1543,17 @@ protected unsafe void WriteCDataSection(string text) case ']': if (pDst[-1] == (char)']') { // pDst[-1] will always correct - there is a padding character at bufChars[0] - hadDoubleBracket = true; + _hadDoubleBracket = true; } else { - hadDoubleBracket = false; + _hadDoubleBracket = false; } *pDst = (char)']'; pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1570,7 +1570,7 @@ protected unsafe void WriteCDataSection(string text) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1612,7 +1612,7 @@ protected unsafe void WriteCDataSection(string text) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1645,10 +1645,10 @@ protected unsafe void WriteCDataSection(string text) private unsafe char* InvalidXmlChar(int ch, char* pDst, bool entitize) { - Debug.Assert(!xmlCharType.IsWhiteSpace((char)ch)); - Debug.Assert(!xmlCharType.IsAttributeValueChar((char)ch)); + Debug.Assert(!_xmlCharType.IsWhiteSpace((char)ch)); + Debug.Assert(!_xmlCharType.IsAttributeValueChar((char)ch)); - if (checkCharacters) + if (_checkCharacters) { // This method will never be called on surrogates, so it is ok to pass in '\0' to the CreateInvalidCharException throw XmlConvert.CreateInvalidCharException((char)ch, '\0'); @@ -1695,14 +1695,14 @@ internal unsafe void EncodeChar(ref char* pSrc, char* pSrcEnd, ref char* pDst) protected void ChangeTextContentMark(bool value) { - Debug.Assert(inTextContent != value); - Debug.Assert(inTextContent || ((_lastMarkPos & 1) == 0)); - inTextContent = value; + Debug.Assert(_inTextContent != value); + Debug.Assert(_inTextContent || ((_lastMarkPos & 1) == 0)); + _inTextContent = value; if (_lastMarkPos + 1 == _textContentMarks.Length) { GrowTextContentMarks(); } - _textContentMarks[++_lastMarkPos] = bufPos; + _textContentMarks[++_lastMarkPos] = _bufPos; } private void GrowTextContentMarks() @@ -1715,12 +1715,12 @@ private void GrowTextContentMarks() // Write NewLineChars to the specified buffer position and return an updated position. protected unsafe char* WriteNewLine(char* pDst) { - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); // Let RawText do the real work - RawText(newLineChars); - return pDstBegin + bufPos; + RawText(_newLineChars); + return pDstBegin + _bufPos; } } @@ -1858,7 +1858,7 @@ protected unsafe void ValidateContentChars(string chars, string propertyName, bo { if (allowOnlyWhitespace) { - if (!xmlCharType.IsOnlyWhitespace(chars)) + if (!_xmlCharType.IsOnlyWhitespace(chars)) { throw new ArgumentException(SR.Format(SR.Xml_IndentCharsNotWhitespace, propertyName)); } @@ -1868,7 +1868,7 @@ protected unsafe void ValidateContentChars(string chars, string propertyName, bo string error = null; for (int i = 0; i < chars.Length; i++) { - if (!xmlCharType.IsTextChar(chars[i])) + if (!_xmlCharType.IsTextChar(chars[i])) { switch (chars[i]) { @@ -1918,14 +1918,14 @@ internal partial class XmlEncodedRawTextWriterIndent : XmlEncodedRawTextWriter // // Fields // - protected int indentLevel; - protected bool newLineOnAttributes; - protected string indentChars; + protected int _indentLevel; + protected bool _newLineOnAttributes; + protected string _indentChars; - protected bool mixedContent; + protected bool _mixedContent; private BitStack _mixedContentStack; - protected ConformanceLevel conformanceLevel = ConformanceLevel.Auto; + protected ConformanceLevel _conformanceLevel = ConformanceLevel.Auto; // // Constructors @@ -1951,8 +1951,8 @@ public override XmlWriterSettings Settings settings.ReadOnly = false; settings.Indent = true; - settings.IndentChars = indentChars; - settings.NewLineOnAttributes = newLineOnAttributes; + settings.IndentChars = _indentChars; + settings.NewLineOnAttributes = _newLineOnAttributes; settings.ReadOnly = true; return settings; @@ -1962,7 +1962,7 @@ public override XmlWriterSettings Settings public override void WriteDocType(string name, string pubid, string sysid, string subset) { // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -1974,12 +1974,12 @@ public override void WriteStartElement(string prefix, string localName, string n Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } - indentLevel++; - _mixedContentStack.PushBit(mixedContent); + _indentLevel++; + _mixedContentStack.PushBit(_mixedContent); base.WriteStartElement(prefix, localName, ns); } @@ -1987,16 +1987,16 @@ public override void WriteStartElement(string prefix, string localName, string n internal override void StartElementContent() { // If this is the root element and we're writing a document - // do not inherit the mixedContent flag into the root element. + // do not inherit the _mixedContent flag into the root element. // This is to allow for whitespace nodes on root level // without disabling indentation for the whole document. - if (indentLevel == 1 && conformanceLevel == ConformanceLevel.Document) + if (_indentLevel == 1 && _conformanceLevel == ConformanceLevel.Document) { - mixedContent = false; + _mixedContent = false; } else { - mixedContent = _mixedContentStack.PeekBit(); + _mixedContent = _mixedContentStack.PeekBit(); } base.StartElementContent(); } @@ -2004,22 +2004,22 @@ internal override void StartElementContent() internal override void OnRootElement(ConformanceLevel currentConformanceLevel) { // Just remember the current conformance level - conformanceLevel = currentConformanceLevel; + _conformanceLevel = currentConformanceLevel; } internal override void WriteEndElement(string prefix, string localName, string ns) { // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { WriteIndent(); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); base.WriteEndElement(prefix, localName, ns); } @@ -2027,16 +2027,16 @@ internal override void WriteEndElement(string prefix, string localName, string n internal override void WriteFullEndElement(string prefix, string localName, string ns) { // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { WriteIndent(); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); base.WriteFullEndElement(prefix, localName, ns); } @@ -2045,7 +2045,7 @@ internal override void WriteFullEndElement(string prefix, string localName, stri public override void WriteStartAttribute(string prefix, string localName, string ns) { // Add indentation - if (newLineOnAttributes) + if (_newLineOnAttributes) { WriteIndent(); } @@ -2055,13 +2055,13 @@ public override void WriteStartAttribute(string prefix, string localName, string public override void WriteCData(string text) { - mixedContent = true; + _mixedContent = true; base.WriteCData(text); } public override void WriteComment(string text) { - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -2071,7 +2071,7 @@ public override void WriteComment(string text) public override void WriteProcessingInstruction(string target, string text) { - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -2081,55 +2081,55 @@ public override void WriteProcessingInstruction(string target, string text) public override void WriteEntityRef(string name) { - mixedContent = true; + _mixedContent = true; base.WriteEntityRef(name); } public override void WriteCharEntity(char ch) { - mixedContent = true; + _mixedContent = true; base.WriteCharEntity(ch); } public override void WriteSurrogateCharEntity(char lowChar, char highChar) { - mixedContent = true; + _mixedContent = true; base.WriteSurrogateCharEntity(lowChar, highChar); } public override void WriteWhitespace(string ws) { - mixedContent = true; + _mixedContent = true; base.WriteWhitespace(ws); } public override void WriteString(string text) { - mixedContent = true; + _mixedContent = true; base.WriteString(text); } public override void WriteChars(char[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteChars(buffer, index, count); } public override void WriteRaw(char[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteRaw(buffer, index, count); } public override void WriteRaw(string data) { - mixedContent = true; + _mixedContent = true; base.WriteRaw(data); } public override void WriteBase64(byte[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteBase64(buffer, index, count); } @@ -2138,25 +2138,25 @@ public override void WriteBase64(byte[] buffer, int index, int count) // private void Init(XmlWriterSettings settings) { - indentLevel = 0; - indentChars = settings.IndentChars; - newLineOnAttributes = settings.NewLineOnAttributes; + _indentLevel = 0; + _indentChars = settings.IndentChars; + _newLineOnAttributes = settings.NewLineOnAttributes; _mixedContentStack = new BitStack(); // check indent characters that they are valid XML characters - if (base.checkCharacters) + if (base._checkCharacters) { - if (newLineOnAttributes) + if (_newLineOnAttributes) { - base.ValidateContentChars(indentChars, "IndentChars", true); - base.ValidateContentChars(newLineChars, "NewLineChars", true); + base.ValidateContentChars(_indentChars, "IndentChars", true); + base.ValidateContentChars(_newLineChars, "NewLineChars", true); } else { - base.ValidateContentChars(indentChars, "IndentChars", false); - if (base.newLineHandling != NewLineHandling.Replace) + base.ValidateContentChars(_indentChars, "IndentChars", false); + if (base._newLineHandling != NewLineHandling.Replace) { - base.ValidateContentChars(newLineChars, "NewLineChars", false); + base.ValidateContentChars(_newLineChars, "NewLineChars", false); } } } @@ -2165,10 +2165,10 @@ private void Init(XmlWriterSettings settings) // Add indentation to output. Write newline and then repeat IndentChars for each indent level. private void WriteIndent() { - RawText(base.newLineChars); - for (int i = indentLevel; i > 0; i--) + RawText(base._newLineChars); + for (int i = _indentLevel; i > 0; i--) { - RawText(indentChars); + RawText(_indentChars); } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs index 13a694c1f98aa..cbdb13361dfe5 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs @@ -35,19 +35,19 @@ internal override async Task WriteXmlDeclarationAsync(XmlStandalone standalone) { CheckAsyncCall(); // Output xml declaration only if user allows it and it was not already output - if (!omitXmlDeclaration && !autoXmlDeclaration) + if (!_omitXmlDeclaration && !_autoXmlDeclaration) { - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } await RawTextAsync(" 0); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } await RawTextAsync("'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize the beginning of an element start tag: " 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } Task task; - bufChars[bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'<'; if (prefix != null && prefix.Length != 0) { task = RawTextAsync(prefix, ":", localName); @@ -195,7 +195,7 @@ public override Task WriteStartElementAsync(string prefix, string localName, str private void WriteStartElementAsync_SetAttEndPos() { - attrEndPos = bufPos; + _attrEndPos = _bufPos; } // Serialize an element end tag: "", if content was output. Otherwise, serialize @@ -206,13 +206,13 @@ internal override Task WriteEndElementAsync(string prefix, string localName, str Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (contentPos != bufPos) + if (_contentPos != _bufPos) { // Content has been output, so can't use shortcut syntax - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'/'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'/'; if (prefix != null && prefix.Length != 0) { @@ -226,10 +226,10 @@ internal override Task WriteEndElementAsync(string prefix, string localName, str else { // Use shortcut syntax; overwrite the already output '>' character - bufPos--; - bufChars[bufPos++] = (char)' '; - bufChars[bufPos++] = (char)'/'; - bufChars[bufPos++] = (char)'>'; + _bufPos--; + _bufChars[_bufPos++] = (char)' '; + _bufChars[_bufPos++] = (char)'/'; + _bufChars[_bufPos++] = (char)'>'; } return Task.CompletedTask; } @@ -241,10 +241,10 @@ internal override Task WriteFullEndElementAsync(string prefix, string localName, Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'/'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'/'; if (prefix != null && prefix.Length != 0) { @@ -263,11 +263,11 @@ protected internal override Task WriteStartAttributeAsync(string prefix, string Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (attrEndPos == bufPos) + if (_attrEndPos == _bufPos) { - bufChars[bufPos++] = (char)' '; + _bufChars[_bufPos++] = (char)' '; } Task task; if (prefix != null && prefix.Length > 0) @@ -283,9 +283,9 @@ protected internal override Task WriteStartAttributeAsync(string prefix, string private void WriteStartAttribute_SetInAttribute() { - bufChars[bufPos++] = (char)'='; - bufChars[bufPos++] = (char)'"'; - inAttributeValue = true; + _bufChars[_bufPos++] = (char)'='; + _bufChars[_bufPos++] = (char)'"'; + _inAttributeValue = true; } // Serialize the end of an attribute value using double quotes: '"' @@ -293,11 +293,11 @@ protected internal override Task WriteEndAttributeAsync() { CheckAsyncCall(); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'"'; - inAttributeValue = false; - attrEndPos = bufPos; + _bufChars[_bufPos++] = (char)'"'; + _inAttributeValue = false; + _attrEndPos = _bufPos; return Task.CompletedTask; } @@ -317,7 +317,7 @@ internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) CheckAsyncCall(); Debug.Assert(prefix != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } if (prefix.Length == 0) { @@ -327,25 +327,25 @@ internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) { await RawTextAsync(" xmlns:").ConfigureAwait(false); await RawTextAsync(prefix).ConfigureAwait(false); - bufChars[bufPos++] = (char)'='; - bufChars[bufPos++] = (char)'"'; + _bufChars[_bufPos++] = (char)'='; + _bufChars[_bufPos++] = (char)'"'; } - inAttributeValue = true; + _inAttributeValue = true; - if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); } + if (_trackTextContent && _inTextContent != true) { ChangeTextContentMark(true); } } internal override Task WriteEndNamespaceDeclarationAsync() { CheckAsyncCall(); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - inAttributeValue = false; + _inAttributeValue = false; - bufChars[bufPos++] = (char)'"'; - attrEndPos = bufPos; + _bufChars[_bufPos++] = (char)'"'; + _attrEndPos = _bufPos; return Task.CompletedTask; } @@ -357,36 +357,36 @@ public override async Task WriteCDataAsync(string text) CheckAsyncCall(); Debug.Assert(text != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (mergeCDataSections && bufPos == cdataPos) + if (_mergeCDataSections && _bufPos == _cdataPos) { // Merge adjacent cdata sections - overwrite the "]]>" characters - Debug.Assert(bufPos >= 4); - bufPos -= 3; + Debug.Assert(_bufPos >= 4); + _bufPos -= 3; } else { // Start a new cdata section - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'!'; - bufChars[bufPos++] = (char)'['; - bufChars[bufPos++] = (char)'C'; - bufChars[bufPos++] = (char)'D'; - bufChars[bufPos++] = (char)'A'; - bufChars[bufPos++] = (char)'T'; - bufChars[bufPos++] = (char)'A'; - bufChars[bufPos++] = (char)'['; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'!'; + _bufChars[_bufPos++] = (char)'['; + _bufChars[_bufPos++] = (char)'C'; + _bufChars[_bufPos++] = (char)'D'; + _bufChars[_bufPos++] = (char)'A'; + _bufChars[_bufPos++] = (char)'T'; + _bufChars[_bufPos++] = (char)'A'; + _bufChars[_bufPos++] = (char)'['; } await WriteCDataSectionAsync(text).ConfigureAwait(false); - bufChars[bufPos++] = (char)']'; - bufChars[bufPos++] = (char)']'; - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)']'; + _bufChars[_bufPos++] = (char)']'; + _bufChars[_bufPos++] = (char)'>'; - textPos = bufPos; - cdataPos = bufPos; + _textPos = _bufPos; + _cdataPos = _bufPos; } // Serialize a comment. @@ -395,18 +395,18 @@ public override async Task WriteCommentAsync(string text) CheckAsyncCall(); Debug.Assert(text != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'!'; - bufChars[bufPos++] = (char)'-'; - bufChars[bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'!'; + _bufChars[_bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'-'; await WriteCommentOrPiAsync(text, '-').ConfigureAwait(false); - bufChars[bufPos++] = (char)'-'; - bufChars[bufPos++] = (char)'-'; - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'-'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize a processing instruction. @@ -416,20 +416,20 @@ public override async Task WriteProcessingInstructionAsync(string name, string t Debug.Assert(name != null && name.Length > 0); Debug.Assert(text != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'<'; - bufChars[bufPos++] = (char)'?'; + _bufChars[_bufPos++] = (char)'<'; + _bufChars[_bufPos++] = (char)'?'; await RawTextAsync(name).ConfigureAwait(false); if (text.Length > 0) { - bufChars[bufPos++] = (char)' '; + _bufChars[_bufPos++] = (char)' '; await WriteCommentOrPiAsync(text, '?').ConfigureAwait(false); } - bufChars[bufPos++] = (char)'?'; - bufChars[bufPos++] = (char)'>'; + _bufChars[_bufPos++] = (char)'?'; + _bufChars[_bufPos++] = (char)'>'; } // Serialize an entity reference. @@ -438,18 +438,18 @@ public override async Task WriteEntityRefAsync(string name) CheckAsyncCall(); Debug.Assert(name != null && name.Length > 0); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'&'; + _bufChars[_bufPos++] = (char)'&'; await RawTextAsync(name).ConfigureAwait(false); - bufChars[bufPos++] = (char)';'; + _bufChars[_bufPos++] = (char)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a character entity reference. @@ -458,26 +458,26 @@ public override async Task WriteCharEntityAsync(char ch) CheckAsyncCall(); string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); - if (checkCharacters && !xmlCharType.IsCharData(ch)) + if (_checkCharacters && !_xmlCharType.IsCharData(ch)) { // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char throw XmlConvert.CreateInvalidCharException(ch, '\0'); } - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - bufChars[bufPos++] = (char)'&'; - bufChars[bufPos++] = (char)'#'; - bufChars[bufPos++] = (char)'x'; + _bufChars[_bufPos++] = (char)'&'; + _bufChars[_bufPos++] = (char)'#'; + _bufChars[_bufPos++] = (char)'x'; await RawTextAsync(strVal).ConfigureAwait(false); - bufChars[bufPos++] = (char)';'; + _bufChars[_bufPos++] = (char)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a whitespace node. @@ -487,9 +487,9 @@ public override Task WriteWhitespaceAsync(string ws) CheckAsyncCall(); Debug.Assert(ws != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(ws); } @@ -506,9 +506,9 @@ public override Task WriteStringAsync(string text) CheckAsyncCall(); Debug.Assert(text != null); - if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); } + if (_trackTextContent && _inTextContent != true) { ChangeTextContentMark(true); } - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(text); } @@ -523,16 +523,16 @@ public override async Task WriteSurrogateCharEntityAsync(char lowChar, char high { CheckAsyncCall(); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar); - bufChars[bufPos++] = (char)'&'; - bufChars[bufPos++] = (char)'#'; - bufChars[bufPos++] = (char)'x'; + _bufChars[_bufPos++] = (char)'&'; + _bufChars[_bufPos++] = (char)'#'; + _bufChars[_bufPos++] = (char)'x'; await RawTextAsync(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)).ConfigureAwait(false); - bufChars[bufPos++] = (char)';'; - textPos = bufPos; + _bufChars[_bufPos++] = (char)';'; + _textPos = _bufPos; } // Serialize either attribute or element text using XML rules. @@ -545,9 +545,9 @@ public override Task WriteCharsAsync(char[] buffer, int index, int count) Debug.Assert(index >= 0); Debug.Assert(count >= 0 && index + count <= buffer.Length); - if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); } + if (_trackTextContent && _inTextContent != true) { ChangeTextContentMark(true); } - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(buffer, index, count); } @@ -567,11 +567,11 @@ public override async Task WriteRawAsync(char[] buffer, int index, int count) Debug.Assert(index >= 0); Debug.Assert(count >= 0 && index + count <= buffer.Length); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } await WriteRawWithCharCheckingAsync(buffer, index, count).ConfigureAwait(false); - textPos = bufPos; + _textPos = _bufPos; } // Serialize raw data. @@ -581,11 +581,11 @@ public override async Task WriteRawAsync(string data) CheckAsyncCall(); Debug.Assert(data != null); - if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); } + if (_trackTextContent && _inTextContent != false) { ChangeTextContentMark(false); } await WriteRawWithCharCheckingAsync(data).ConfigureAwait(false); - textPos = bufPos; + _textPos = _bufPos; } // Flush all characters in the buffer to output and call Flush() on the output object. @@ -595,13 +595,13 @@ public override async Task FlushAsync() await FlushBufferAsync().ConfigureAwait(false); await FlushEncoderAsync().ConfigureAwait(false); - if (stream != null) + if (_stream != null) { - await stream.FlushAsync().ConfigureAwait(false); + await _stream.FlushAsync().ConfigureAwait(false); } - else if (writer != null) + else if (_writer != null) { - await writer.FlushAsync().ConfigureAwait(false); + await _writer.FlushAsync().ConfigureAwait(false); } } @@ -614,13 +614,13 @@ protected virtual async Task FlushBufferAsync() try { // Output all characters (except for previous characters stored at beginning of buffer) - if (!writeToNull) + if (!_writeToNull) { - Debug.Assert(stream != null || writer != null); + Debug.Assert(_stream != null || _writer != null); - if (stream != null) + if (_stream != null) { - if (trackTextContent) + if (_trackTextContent) { _charEntityFallback.Reset(_textContentMarks, _lastMarkPos); // reset text content tracking @@ -638,14 +638,14 @@ protected virtual async Task FlushBufferAsync() } Debug.Assert(_textContentMarks[0] == 1); } - await EncodeCharsAsync(1, bufPos, true).ConfigureAwait(false); + await EncodeCharsAsync(1, _bufPos, true).ConfigureAwait(false); } else { - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { // Write text to TextWriter - await writer.WriteAsync(bufChars, 1, bufPos - 1).ConfigureAwait(false); + await _writer.WriteAsync(_bufChars.AsMemory(1, _bufPos - 1)).ConfigureAwait(false); } } } @@ -653,21 +653,21 @@ protected virtual async Task FlushBufferAsync() catch { // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream - writeToNull = true; + _writeToNull = true; throw; } finally { // Move last buffer character to the beginning of the buffer (so that previous character can always be determined) - bufChars[0] = bufChars[bufPos - 1]; + _bufChars[0] = _bufChars[_bufPos - 1]; // Reset buffer position - textPos = (textPos == bufPos) ? 1 : 0; - attrEndPos = (attrEndPos == bufPos) ? 1 : 0; - contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible - cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible - bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + _textPos = (_textPos == _bufPos) ? 1 : 0; + _attrEndPos = (_attrEndPos == _bufPos) ? 1 : 0; + _contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible + _cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible + _bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0 } } @@ -683,35 +683,35 @@ private async Task EncodeCharsAsync(int startOffset, int endOffset, bool writeAl { _charEntityFallback.StartOffset = startOffset; } - encoder.Convert(bufChars, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed); + _encoder.Convert(_bufChars, startOffset, endOffset - startOffset, _bufBytes, _bufBytesUsed, _bufBytes.Length - _bufBytesUsed, false, out chEnc, out bEnc, out completed); startOffset += chEnc; - bufBytesUsed += bEnc; - if (bufBytesUsed >= (bufBytes.Length - 16)) + _bufBytesUsed += bEnc; + if (_bufBytesUsed >= (_bufBytes.Length - 16)) { - await stream.WriteAsync(bufBytes, 0, bufBytesUsed).ConfigureAwait(false); - bufBytesUsed = 0; + await _stream.WriteAsync(_bufBytes.AsMemory(0, _bufBytesUsed)).ConfigureAwait(false); + _bufBytesUsed = 0; } } - if (writeAllToStream && bufBytesUsed > 0) + if (writeAllToStream && _bufBytesUsed > 0) { - await stream.WriteAsync(bufBytes, 0, bufBytesUsed).ConfigureAwait(false); - bufBytesUsed = 0; + await _stream.WriteAsync(_bufBytes.AsMemory(0, _bufBytesUsed)).ConfigureAwait(false); + _bufBytesUsed = 0; } } private Task FlushEncoderAsync() { - Debug.Assert(bufPos == 1); - if (stream != null) + Debug.Assert(_bufPos == 1); + if (_stream != null) { int chEnc; int bEnc; bool completed; // decode no chars, just flush - encoder.Convert(bufChars, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed); + _encoder.Convert(_bufChars, 1, 0, _bufBytes, 0, _bufBytes.Length, true, out chEnc, out bEnc, out completed); if (bEnc != 0) { - return stream.WriteAsync(bufBytes, 0, bEnc); + return _stream.WriteAsync(_bufBytes, 0, bEnc); } } @@ -724,20 +724,20 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) { char* pRaw = pSrc; - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) { *pDst = (char)ch; pDst++; @@ -754,7 +754,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -778,7 +778,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) pDst++; break; case (char)0x9: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (char)ch; pDst++; @@ -790,7 +790,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) } break; case (char)0xD: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (char)ch; pDst++; @@ -802,7 +802,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (char)ch; pDst++; @@ -837,7 +837,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -928,20 +928,20 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out needWriteNewLine = false; char* pRaw = pSrc; - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) { *pDst = (char)ch; pDst++; @@ -958,7 +958,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -981,9 +981,9 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out pDst++; break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -994,7 +994,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out } break; case (char)0xD: - switch (newLineHandling) + switch (_newLineHandling) { case NewLineHandling.Replace: // Replace "\r\n", or "\r" with NewLineChars @@ -1003,7 +1003,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); @@ -1041,9 +1041,9 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out } pSrc++; } - bufPos = (int)(pDst - pDstBegin); - textPos = bufPos; - contentPos = 0; + _bufPos = (int)(pDst - pDstBegin); + _textPos = _bufPos; + _contentPos = 0; } return -1; @@ -1054,7 +1054,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char[] chars, int index, int c needWriteNewLine = false; if (count == 0) { - contentPos = 0; + _contentPos = 0; return -1; } fixed (char* pSrc = &chars[index]) @@ -1070,7 +1070,7 @@ protected unsafe int WriteElementTextBlockNoFlush(string text, int index, int co needWriteNewLine = false; if (count == 0) { - contentPos = 0; + _contentPos = 0; return -1; } fixed (char* pSrc = text) @@ -1095,7 +1095,7 @@ protected async Task WriteElementTextBlockAsync(char[] chars, int index, int cou if (needWriteNewLine) { //hit WriteNewLine - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1135,7 +1135,7 @@ private async Task _WriteElementTextBlockAsync(bool newLine, string text, int cu if (newLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1152,7 +1152,7 @@ private async Task _WriteElementTextBlockAsync(bool newLine, string text, int cu if (needWriteNewLine) { //hit WriteNewLine - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1167,18 +1167,18 @@ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd) { char* pRaw = pSrcBegin; - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; char* pSrc = pSrcBegin; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } while (pDst < pDstEnd && ((ch = *pSrc) < XmlCharType.SurHighStart)) @@ -1198,7 +1198,7 @@ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1223,7 +1223,7 @@ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd) } } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1342,21 +1342,21 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc needWriteNewLine = false; char* pRaw = pSrcBegin; - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { char* pSrc = pSrcBegin; - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && xmlCharType.IsTextChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsTextChar((char)(ch = *pSrc))) { *pDst = (char)ch; pDst++; @@ -1374,7 +1374,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1389,7 +1389,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1397,7 +1397,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1408,9 +1408,9 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1444,7 +1444,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1493,7 +1493,7 @@ protected async Task WriteRawWithCharCheckingAsync(char[] chars, int index, int leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1517,7 +1517,7 @@ protected async Task WriteRawWithCharCheckingAsync(string text) leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1539,7 +1539,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, { char* pSrcBegin = pSrcText + index; - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { char* pSrc = pSrcBegin; @@ -1547,18 +1547,18 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, char* pSrcEnd = pSrcBegin + count; - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) { *pDst = (char)ch; pDst++; @@ -1576,7 +1576,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1614,7 +1614,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1622,7 +1622,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1633,9 +1633,9 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1675,7 +1675,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1686,7 +1686,7 @@ protected async Task WriteCommentOrPiAsync(string text, int stopChar) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } @@ -1704,7 +1704,7 @@ protected async Task WriteCommentOrPiAsync(string text, int stopChar) leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1729,7 +1729,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, { char* pSrcBegin = pSrcText + index; - fixed (char* pDstBegin = bufChars) + fixed (char* pDstBegin = _bufChars) { char* pSrc = pSrcBegin; @@ -1737,18 +1737,18 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, char* pRaw = pSrc; - char* pDst = pDstBegin + bufPos; + char* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { char* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) { *pDst = (char)ch; pDst++; @@ -1766,7 +1766,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1774,7 +1774,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, switch (ch) { case '>': - if (hadDoubleBracket && pDst[-1] == (char)']') + if (_hadDoubleBracket && pDst[-1] == (char)']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0] // The characters "]]>" were found within the CData text pDst = RawEndCData(pDst); @@ -1786,17 +1786,17 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, case ']': if (pDst[-1] == (char)']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0] - hadDoubleBracket = true; + _hadDoubleBracket = true; } else { - hadDoubleBracket = false; + _hadDoubleBracket = false; } *pDst = (char)']'; pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1804,7 +1804,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1815,9 +1815,9 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1859,7 +1859,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1870,7 +1870,7 @@ protected async Task WriteCDataSectionAsync(string text) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } @@ -1888,7 +1888,7 @@ protected async Task WriteCDataSectionAsync(string text) leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1907,7 +1907,7 @@ public override async Task WriteDocTypeAsync(string name, string pubid, string s { CheckAsyncCall(); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1920,12 +1920,12 @@ public override async Task WriteStartElementAsync(string prefix, string localNam Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } - indentLevel++; - _mixedContentStack.PushBit(mixedContent); + _indentLevel++; + _mixedContentStack.PushBit(_mixedContent); await base.WriteStartElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1934,16 +1934,16 @@ internal override async Task WriteEndElementAsync(string prefix, string localNam { CheckAsyncCall(); // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); await base.WriteEndElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1952,16 +1952,16 @@ internal override async Task WriteFullEndElementAsync(string prefix, string loca { CheckAsyncCall(); // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); await base.WriteFullEndElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1971,7 +1971,7 @@ protected internal override async Task WriteStartAttributeAsync(string prefix, s { CheckAsyncCall(); // Add indentation - if (newLineOnAttributes) + if (_newLineOnAttributes) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1982,14 +1982,14 @@ protected internal override async Task WriteStartAttributeAsync(string prefix, s public override Task WriteCDataAsync(string text) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCDataAsync(text); } public override async Task WriteCommentAsync(string text) { CheckAsyncCall(); - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -2000,7 +2000,7 @@ public override async Task WriteCommentAsync(string text) public override async Task WriteProcessingInstructionAsync(string target, string text) { CheckAsyncCall(); - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -2011,63 +2011,63 @@ public override async Task WriteProcessingInstructionAsync(string target, string public override Task WriteEntityRefAsync(string name) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteEntityRefAsync(name); } public override Task WriteCharEntityAsync(char ch) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCharEntityAsync(ch); } public override Task WriteSurrogateCharEntityAsync(char lowChar, char highChar) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteSurrogateCharEntityAsync(lowChar, highChar); } public override Task WriteWhitespaceAsync(string ws) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteWhitespaceAsync(ws); } public override Task WriteStringAsync(string text) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteStringAsync(text); } public override Task WriteCharsAsync(char[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCharsAsync(buffer, index, count); } public override Task WriteRawAsync(char[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteRawAsync(buffer, index, count); } public override Task WriteRawAsync(string data) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteRawAsync(data); } public override Task WriteBase64Async(byte[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteBase64Async(buffer, index, count); } @@ -2075,10 +2075,10 @@ public override Task WriteBase64Async(byte[] buffer, int index, int count) private async Task WriteIndentAsync() { CheckAsyncCall(); - await RawTextAsync(base.newLineChars).ConfigureAwait(false); - for (int i = indentLevel; i > 0; i--) + await RawTextAsync(base._newLineChars).ConfigureAwait(false); + for (int i = _indentLevel; i > 0; i--) { - await RawTextAsync(indentChars).ConfigureAwait(false); + await RawTextAsync(_indentChars).ConfigureAwait(false); } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEventCache.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEventCache.cs index b036585efbb22..857f50f3c13af 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEventCache.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEventCache.cs @@ -431,7 +431,7 @@ public override void Flush() /// public override void WriteValue(object value) { - WriteString(XmlUntypedConverter.Untyped.ToString(value, this.resolver)); + WriteString(XmlUntypedConverter.Untyped.ToString(value, this._resolver)); } public override void WriteValue(string value) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude index 10464300bf5a7..f9704285b633f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude @@ -28,44 +28,44 @@ namespace System.Xml private readonly bool _useAsync; // main buffer - protected byte[] bufBytes; + protected byte[] _bufBytes; // output stream - protected Stream stream; + protected Stream _stream; // encoding of the stream or text writer - protected Encoding encoding; + protected Encoding _encoding; // char type tables - protected XmlCharType xmlCharType = XmlCharType.Instance; + protected XmlCharType _xmlCharType = XmlCharType.Instance; // buffer positions - protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to - // close an empty element or in CDATA section detection of double ]; <#= BufferName #>[0] will always be 0 - protected int textPos = 1; // text end position; don't indent first element, pi, or comment - protected int contentPos; // element content end position - protected int cdataPos; // cdata end position - protected int attrEndPos; // end of the last attribute - protected int bufLen = BUFSIZE; + protected int _bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + // close an empty element or in CDATA section detection of double ]; <#= BufferName #>[0] will always be 0 + protected int _textPos = 1; // text end position; don't indent first element, pi, or comment + protected int _contentPos; // element content end position + protected int _cdataPos; // cdata end position + protected int _attrEndPos; // end of the last attribute + protected int _bufLen = BUFSIZE; // flags - protected bool writeToNull; - protected bool hadDoubleBracket; - protected bool inAttributeValue; + protected bool _writeToNull; + protected bool _hadDoubleBracket; + protected bool _inAttributeValue; <# if (WriterType == RawTextWriterType.Encoded) { #> - protected int bufBytesUsed; - protected char[] bufChars; + protected int _bufBytesUsed; + protected char[] _bufChars; // encoder for encoding chars in specified encoding when writing to stream - protected Encoder encoder; + protected Encoder _encoder; // output text writer - protected TextWriter writer; + protected TextWriter _writer; // escaping of characters invalid in the output encoding - protected bool trackTextContent; - protected bool inTextContent; + protected bool _trackTextContent; + protected bool _inTextContent; private int _lastMarkPos; private int[] _textContentMarks; // even indices contain text content start positions // odd indices contain markup start positions @@ -73,17 +73,17 @@ namespace System.Xml <# } #> // writer settings - protected NewLineHandling newLineHandling; - protected bool closeOutput; - protected bool omitXmlDeclaration; - protected string newLineChars; - protected bool checkCharacters; + protected NewLineHandling _newLineHandling; + protected bool _closeOutput; + protected bool _omitXmlDeclaration; + protected string _newLineChars; + protected bool _checkCharacters; - protected XmlStandalone standalone; - protected XmlOutputMethod outputMethod; + protected XmlStandalone _standalone; + protected XmlOutputMethod _outputMethod; - protected bool autoXmlDeclaration; - protected bool mergeCDataSections; + protected bool _autoXmlDeclaration; + protected bool _mergeCDataSections; // // Constants @@ -102,19 +102,19 @@ namespace System.Xml _useAsync = settings.Async; // copy settings - newLineHandling = settings.NewLineHandling; - omitXmlDeclaration = settings.OmitXmlDeclaration; - newLineChars = settings.NewLineChars; - checkCharacters = settings.CheckCharacters; - closeOutput = settings.CloseOutput; + _newLineHandling = settings.NewLineHandling; + _omitXmlDeclaration = settings.OmitXmlDeclaration; + _newLineChars = settings.NewLineChars; + _checkCharacters = settings.CheckCharacters; + _closeOutput = settings.CloseOutput; - standalone = settings.Standalone; - outputMethod = settings.OutputMethod; - mergeCDataSections = settings.MergeCDataSections; + _standalone = settings.Standalone; + _outputMethod = settings.OutputMethod; + _mergeCDataSections = settings.MergeCDataSections; - if (checkCharacters && newLineHandling == NewLineHandling.Replace) + if (_checkCharacters && _newLineHandling == NewLineHandling.Replace) { - ValidateContentChars(newLineChars, "NewLineChars", false); + ValidateContentChars(_newLineChars, "NewLineChars", false); } } <# if (WriterType == RawTextWriterType.Encoded) { #> @@ -124,20 +124,20 @@ namespace System.Xml { Debug.Assert(writer != null && settings != null); - this.writer = writer; - this.encoding = writer.Encoding; + this._writer = writer; + this._encoding = writer.Encoding; // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup if (settings.Async) { - bufLen = ASYNCBUFSIZE; + _bufLen = ASYNCBUFSIZE; } - this.bufChars = new <#= BufferType #>[bufLen + OVERFLOW]; + this._bufChars = new <#= BufferType #>[_bufLen + OVERFLOW]; // Write the xml declaration if (settings.AutoXmlDeclaration) { - WriteXmlDeclaration(standalone); - autoXmlDeclaration = true; + WriteXmlDeclaration(_standalone); + _autoXmlDeclaration = true; } } <# } #> @@ -147,35 +147,35 @@ namespace System.Xml { Debug.Assert(stream != null && settings != null); - this.stream = stream; - this.encoding = settings.Encoding; + this._stream = stream; + this._encoding = settings.Encoding; // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup if (settings.Async) { - bufLen = ASYNCBUFSIZE; + _bufLen = ASYNCBUFSIZE; } - <#= BufferName #> = new <#= BufferType #>[bufLen + OVERFLOW]; + <#= BufferName #> = new <#= BufferType #>[_bufLen + OVERFLOW]; <# if (WriterType == RawTextWriterType.Utf8) { #> // Output UTF-8 byte order mark if Encoding object wants it if (!stream.CanSeek || stream.Position == 0) { - ReadOnlySpan bom = encoding.Preamble; + ReadOnlySpan bom = _encoding.Preamble; if (bom.Length != 0) { - bom.CopyTo(new Span(bufBytes).Slice(1)); - bufPos += bom.Length; - textPos += bom.Length; + bom.CopyTo(new Span(_bufBytes).Slice(1)); + _bufPos += bom.Length; + _textPos += bom.Length; } } <# } else { #> - bufBytes = new byte[bufChars.Length]; - bufBytesUsed = 0; + _bufBytes = new byte[_bufChars.Length]; + _bufBytesUsed = 0; // Init escaping of characters not fitting into the target encoding - trackTextContent = true; - inTextContent = false; + _trackTextContent = true; + _inTextContent = false; _lastMarkPos = 0; _textContentMarks = new int[INIT_MARKS_COUNT]; _textContentMarks[0] = 1; @@ -183,21 +183,21 @@ namespace System.Xml _charEntityFallback = new CharEntityEncoderFallback(); // grab bom before possibly changing encoding settings - ReadOnlySpan bom = encoding.Preamble; + ReadOnlySpan bom = _encoding.Preamble; // the encoding instance this creates can differ from the one passed in - this.encoding = Encoding.GetEncoding( + this._encoding = Encoding.GetEncoding( settings.Encoding.CodePage, _charEntityFallback, settings.Encoding.DecoderFallback); - encoder = encoding.GetEncoder(); + _encoder = _encoding.GetEncoder(); - if (!stream.CanSeek || stream.Position == 0) + if (!_stream.CanSeek || _stream.Position == 0) { if (bom.Length != 0) { - this.stream.Write(bom); + this._stream.Write(bom); } } <# } #> @@ -205,8 +205,8 @@ namespace System.Xml // Write the xml declaration if (settings.AutoXmlDeclaration) { - WriteXmlDeclaration(standalone); - autoXmlDeclaration = true; + WriteXmlDeclaration(_standalone); + _autoXmlDeclaration = true; } } @@ -220,17 +220,17 @@ namespace System.Xml { XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = encoding; - settings.OmitXmlDeclaration = omitXmlDeclaration; - settings.NewLineHandling = newLineHandling; - settings.NewLineChars = newLineChars; - settings.CloseOutput = closeOutput; + settings.Encoding = _encoding; + settings.OmitXmlDeclaration = _omitXmlDeclaration; + settings.NewLineHandling = _newLineHandling; + settings.NewLineChars = _newLineChars; + settings.CloseOutput = _closeOutput; settings.ConformanceLevel = ConformanceLevel.Auto; - settings.CheckCharacters = checkCharacters; + settings.CheckCharacters = _checkCharacters; - settings.AutoXmlDeclaration = autoXmlDeclaration; - settings.Standalone = standalone; - settings.OutputMethod = outputMethod; + settings.AutoXmlDeclaration = _autoXmlDeclaration; + settings.Standalone = _standalone; + settings.OutputMethod = _outputMethod; settings.ReadOnly = true; return settings; @@ -241,7 +241,7 @@ namespace System.Xml internal override void WriteXmlDeclaration(XmlStandalone standalone) { // Output xml declaration only if user allows it and it was not already output - if (!omitXmlDeclaration && !autoXmlDeclaration) + if (!_omitXmlDeclaration && !_autoXmlDeclaration) {<# /* Code block is to squash extra line. */ #><#= SetTextContentMark(4, 1, false) #> RawText("[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; } else if (sysid != null) { RawText(" SYSTEM \""); RawText(sysid); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; } else { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; } if (subset != null) { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'['; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'['; RawText(subset); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)']'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)']'; } - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize the beginning of an element start tag: "<#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)':'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)':'; } RawText(localName); - attrEndPos = bufPos; + _attrEndPos = _bufPos; } // Serialize the end of an element start tag in preparation for content serialization: ">" internal override void StartElementContent() { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; // StartElementContent is always called; therefore, in order to allow shortcut syntax, we save the // position of the '>' character. If WriteEndElement is called and no other characters have been // output, then the '>' character can be overwritten with the shortcut syntax " />". - contentPos = bufPos; + _contentPos = _bufPos; } // Serialize an element end tag: "", if content was output. Otherwise, serialize @@ -357,27 +357,27 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - if (contentPos != bufPos) + if (_contentPos != _bufPos) { // Content has been output, so can't use shortcut syntax - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'/'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)':'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)':'; } RawText(localName); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } else { // Use shortcut syntax; overwrite the already output '>' character - bufPos--; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + _bufPos--; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'/'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } } @@ -389,16 +389,16 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'/'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)':'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)':'; } RawText(localName); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="' @@ -409,21 +409,21 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - if (attrEndPos == bufPos) + if (_attrEndPos == _bufPos) { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; } if (prefix != null && prefix.Length > 0) { RawText(prefix); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)':'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)':'; } RawText(localName); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'='; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'='; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; - inAttributeValue = true; + _inAttributeValue = true; } // Serialize the end of an attribute value using double quotes: '"' @@ -431,9 +431,9 @@ namespace System.Xml {<# #><#= SetTextContentMark(3, 1, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; - inAttributeValue = false; - attrEndPos = bufPos; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; + _inAttributeValue = false; + _attrEndPos = _bufPos; } internal override void WriteNamespaceDeclaration(string prefix, string namespaceName) @@ -467,21 +467,21 @@ namespace System.Xml { RawText(" xmlns:"); RawText(prefix); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'='; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'='; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; } - inAttributeValue = true;<# + _inAttributeValue = true;<# #><#= SetTextContentMark(3, true) #> } internal override void WriteEndNamespaceDeclaration() {<# #><#= SetTextContentMark(3, 1, false) #> - inAttributeValue = false; + _inAttributeValue = false; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; - attrEndPos = bufPos; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; + _attrEndPos = _bufPos; } // Serialize a CData section. If the "]]>" pattern is found within @@ -492,34 +492,34 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - if (mergeCDataSections && bufPos == cdataPos) + if (_mergeCDataSections && _bufPos == _cdataPos) { // Merge adjacent cdata sections - overwrite the "]]>" characters - Debug.Assert(bufPos >= 4); - bufPos -= 3; + Debug.Assert(_bufPos >= 4); + _bufPos -= 3; } else { // Start a new cdata section - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'['; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'C'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'D'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'T'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'['; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'!'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'['; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'C'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'D'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'A'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'T'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'A'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'['; } WriteCDataSection(text); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)']'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)']'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)']'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)']'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; - textPos = bufPos; - cdataPos = bufPos; + _textPos = _bufPos; + _cdataPos = _bufPos; } // Serialize a comment. @@ -529,16 +529,16 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'!'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; WriteCommentOrPi(text, '-'); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize a processing instruction. @@ -549,18 +549,18 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'?'; RawText(name); if (text.Length > 0) { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; WriteCommentOrPi(text, '?'); } - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'?'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize an entity reference. @@ -570,16 +570,16 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'&'; RawText(name); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)';'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { FlushBuffer(); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a character entity reference. @@ -587,7 +587,7 @@ namespace System.Xml { string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); - if (checkCharacters && !xmlCharType.IsCharData(ch)) + if (_checkCharacters && !_xmlCharType.IsCharData(ch)) { // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char throw XmlConvert.CreateInvalidCharException(ch, '\0'); @@ -595,18 +595,18 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'&'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'#'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'x'; RawText(strVal); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)';'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { FlushBuffer(); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a whitespace node. @@ -620,7 +620,7 @@ namespace System.Xml fixed (char* pSrc = ws) { char* pSrcEnd = pSrc + ws.Length; - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -642,7 +642,7 @@ namespace System.Xml fixed (char* pSrc = text) { char* pSrcEnd = pSrc + text.Length; - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -659,12 +659,12 @@ namespace System.Xml #><#= SetTextContentMark(3, 1, false) #> int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'&'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'#'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'x'; RawText(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)';'; - textPos = bufPos; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)';'; + _textPos = _bufPos; } // Serialize either attribute or element text using XML rules. @@ -680,7 +680,7 @@ namespace System.Xml fixed (char* pSrcBegin = &buffer[index]) { - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count); } @@ -707,7 +707,7 @@ namespace System.Xml WriteRawWithCharChecking(pSrcBegin, pSrcBegin + count); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize raw data. @@ -723,7 +723,7 @@ namespace System.Xml WriteRawWithCharChecking(pSrcBegin, pSrcBegin + data.Length); } - textPos = bufPos; + _textPos = _bufPos; } // Flush all bytes in the buffer to output and close the output stream or writer. @@ -737,48 +737,48 @@ namespace System.Xml finally { // Future calls to Close or Flush shouldn't write to Stream or Writer - writeToNull = true; + _writeToNull = true; - if (stream != null) + if (_stream != null) { try { - stream.Flush(); + _stream.Flush(); } finally { try { - if (closeOutput) + if (_closeOutput) { - stream.Dispose(); + _stream.Dispose(); } } finally { - stream = null; + _stream = null; } } } <# if (WriterType == RawTextWriterType.Encoded) { #> - else if (writer != null) + else if (_writer != null) { try { - writer.Flush(); + _writer.Flush(); } finally { try { - if (closeOutput) + if (_closeOutput) { - writer.Dispose(); + _writer.Dispose(); } } finally { - writer = null; + _writer = null; } } } @@ -792,18 +792,18 @@ namespace System.Xml FlushBuffer(); FlushEncoder(); <# if (WriterType == RawTextWriterType.Utf8) { #> - if (stream != null) + if (_stream != null) { - stream.Flush(); + _stream.Flush(); } <# } else { #> - if (stream != null) + if (_stream != null) { - stream.Flush(); + _stream.Flush(); } - else if (writer != null) + else if (_writer != null) { - writer.Flush(); + _writer.Flush(); } <# } #> } @@ -817,20 +817,20 @@ namespace System.Xml try { // Output all characters (except for previous characters stored at beginning of buffer) - if (!writeToNull) + if (!_writeToNull) { <# if (WriterType == RawTextWriterType.Utf8) { #> - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { - Debug.Assert(stream != null); - stream.Write(<#= BufferName #>, 1, bufPos - 1); + Debug.Assert(_stream != null); + _stream.Write(<#= BufferName #>, 1, _bufPos - 1); } <# } else { #> - Debug.Assert(stream != null || writer != null); + Debug.Assert(_stream != null || _writer != null); - if (stream != null) + if (_stream != null) { - if (trackTextContent) + if (_trackTextContent) { _charEntityFallback.Reset(_textContentMarks, _lastMarkPos); // reset text content tracking @@ -848,14 +848,14 @@ namespace System.Xml } Debug.Assert(_textContentMarks[0] == 1); } - EncodeChars(1, bufPos, true); + EncodeChars(1, _bufPos, true); } else { - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { // Write text to TextWriter - writer.Write(<#= BufferName #>, 1, bufPos - 1); + _writer.Write(<#= BufferName #>, 1, _bufPos - 1); } } <# } #> @@ -864,30 +864,30 @@ namespace System.Xml catch { // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream - writeToNull = true; + _writeToNull = true; throw; } finally { // Move last buffer character to the beginning of the buffer (so that previous character can always be determined) - <#= BufferName #>[0] = <#= BufferName #>[bufPos - 1]; + <#= BufferName #>[0] = <#= BufferName #>[_bufPos - 1]; <# if (WriterType == RawTextWriterType.Utf8) { #> if (IsSurrogateByte(<#= BufferName #>[0])) { // Last character was the first byte in a surrogate encoding, so move last three // bytes of encoding to the beginning of the buffer. - <#= BufferName #>[1] = <#= BufferName #>[bufPos]; - <#= BufferName #>[2] = <#= BufferName #>[bufPos + 1]; - <#= BufferName #>[3] = <#= BufferName #>[bufPos + 2]; + <#= BufferName #>[1] = <#= BufferName #>[_bufPos]; + <#= BufferName #>[2] = <#= BufferName #>[_bufPos + 1]; + <#= BufferName #>[3] = <#= BufferName #>[_bufPos + 2]; } <# } #> // Reset buffer position - textPos = (textPos == bufPos) ? 1 : 0; - attrEndPos = (attrEndPos == bufPos) ? 1 : 0; - contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible - cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible - bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + _textPos = (_textPos == _bufPos) ? 1 : 0; + _attrEndPos = (_attrEndPos == _bufPos) ? 1 : 0; + _contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible + _cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible + _bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to // close an empty element or in CDATA section detection of double ]; <#= BufferName #>[0] will always be 0 } } @@ -911,35 +911,35 @@ namespace System.Xml { _charEntityFallback.StartOffset = startOffset; } - encoder.Convert(<#= BufferName #>, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed); + _encoder.Convert(<#= BufferName #>, startOffset, endOffset - startOffset, _bufBytes, _bufBytesUsed, _bufBytes.Length - _bufBytesUsed, false, out chEnc, out bEnc, out completed); startOffset += chEnc; - bufBytesUsed += bEnc; - if (bufBytesUsed >= (bufBytes.Length - 16)) + _bufBytesUsed += bEnc; + if (_bufBytesUsed >= (_bufBytes.Length - 16)) { - stream.Write(bufBytes, 0, bufBytesUsed); - bufBytesUsed = 0; + _stream.Write(_bufBytes, 0, _bufBytesUsed); + _bufBytesUsed = 0; } } - if (writeAllToStream && bufBytesUsed > 0) + if (writeAllToStream && _bufBytesUsed > 0) { - stream.Write(bufBytes, 0, bufBytesUsed); - bufBytesUsed = 0; + _stream.Write(_bufBytes, 0, _bufBytesUsed); + _bufBytesUsed = 0; } } private void FlushEncoder() { - Debug.Assert(bufPos == 1); - if (stream != null) + Debug.Assert(_bufPos == 1); + if (_stream != null) { int chEnc; int bEnc; bool completed; // decode no chars, just flush - encoder.Convert(<#= BufferName #>, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed); + _encoder.Convert(<#= BufferName #>, 1, 0, _bufBytes, 0, _bufBytes.Length, true, out chEnc, out bEnc, out completed); if (bEnc != 0) { - stream.Write(bufBytes, 0, bEnc); + _stream.Write(_bufBytes, 0, bEnc); } } } @@ -951,21 +951,21 @@ namespace System.Xml { fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; for (;;) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -983,7 +983,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1009,7 +1009,7 @@ namespace System.Xml pDst++; break; case (char)0x9: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (<#= BufferType #>)ch; pDst++; @@ -1021,7 +1021,7 @@ namespace System.Xml } break; case (char)0xD: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (<#= BufferType #>)ch; pDst++; @@ -1033,7 +1033,7 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (<#= BufferType #>)ch; pDst++; @@ -1050,7 +1050,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1060,21 +1060,21 @@ namespace System.Xml { fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; for (;;) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1092,7 +1092,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1117,7 +1117,7 @@ namespace System.Xml pDst++; break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1128,7 +1128,7 @@ namespace System.Xml } break; case (char)0xD: - switch (newLineHandling) + switch (_newLineHandling) { case NewLineHandling.Replace: // Replace "\r\n", or "\r" with NewLineChars @@ -1156,9 +1156,9 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); - textPos = bufPos; - contentPos = 0; + _bufPos = (int)(pDst - pDstBegin); + _textPos = _bufPos; + _contentPos = 0; } } @@ -1176,16 +1176,16 @@ namespace System.Xml { fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; char* pSrc = pSrcBegin; int ch = 0; for (;;) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> @@ -1209,7 +1209,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1218,7 +1218,7 @@ namespace System.Xml <#= EncodeChar(5, false) #> } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1227,21 +1227,21 @@ namespace System.Xml fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { char* pSrc = pSrcBegin; - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; for (;;) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && xmlCharType.IsTextChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsTextChar((char)(ch = *pSrc))) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1260,7 +1260,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1277,7 +1277,7 @@ namespace System.Xml pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1294,7 +1294,7 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1310,7 +1310,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1318,7 +1318,7 @@ namespace System.Xml { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { FlushBuffer(); } @@ -1333,21 +1333,21 @@ namespace System.Xml char* pSrcEnd = pSrcBegin + text.Length; - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; for (;;) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1366,7 +1366,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1406,7 +1406,7 @@ namespace System.Xml pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1423,7 +1423,7 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1445,7 +1445,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1453,7 +1453,7 @@ namespace System.Xml { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { FlushBuffer(); } @@ -1470,21 +1470,21 @@ namespace System.Xml char* pSrcEnd = pSrcBegin + text.Length; - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; for (;;) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1503,7 +1503,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1513,7 +1513,7 @@ namespace System.Xml switch (ch) { case '>': - if (hadDoubleBracket && pDst[-1] == (<#= BufferType #>)']') + if (_hadDoubleBracket && pDst[-1] == (<#= BufferType #>)']') { // pDst[-1] will always correct - there is a padding character at <#= BufferName #>[0] // The characters "]]>" were found within the CData text pDst = RawEndCData(pDst); @@ -1525,17 +1525,17 @@ namespace System.Xml case ']': if (pDst[-1] == (<#= BufferType #>)']') { // pDst[-1] will always correct - there is a padding character at <#= BufferName #>[0] - hadDoubleBracket = true; + _hadDoubleBracket = true; } else { - hadDoubleBracket = false; + _hadDoubleBracket = false; } *pDst = (<#= BufferType #>)']'; pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1552,7 +1552,7 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1576,7 +1576,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1630,10 +1630,10 @@ namespace System.Xml private unsafe <#= BufferType #>* InvalidXmlChar(int ch, <#= BufferType #>* pDst, bool entitize) { - Debug.Assert(!xmlCharType.IsWhiteSpace((char)ch)); - Debug.Assert(!xmlCharType.IsAttributeValueChar((char)ch)); + Debug.Assert(!_xmlCharType.IsWhiteSpace((char)ch)); + Debug.Assert(!_xmlCharType.IsAttributeValueChar((char)ch)); - if (checkCharacters) + if (_checkCharacters) { // This method will never be called on surrogates, so it is ok to pass in '\0' to the CreateInvalidCharException throw XmlConvert.CreateInvalidCharException((char)ch, '\0'); @@ -1724,14 +1724,14 @@ namespace System.Xml <# if (WriterType == RawTextWriterType.Encoded) { #> protected void ChangeTextContentMark(bool value) { - Debug.Assert(inTextContent != value); - Debug.Assert(inTextContent || ((_lastMarkPos & 1) == 0)); - inTextContent = value; + Debug.Assert(_inTextContent != value); + Debug.Assert(_inTextContent || ((_lastMarkPos & 1) == 0)); + _inTextContent = value; if (_lastMarkPos + 1 == _textContentMarks.Length) { GrowTextContentMarks(); } - _textContentMarks[++_lastMarkPos] = bufPos; + _textContentMarks[++_lastMarkPos] = _bufPos; } private void GrowTextContentMarks() @@ -1747,10 +1747,10 @@ namespace System.Xml { fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); // Let RawText do the real work - RawText(newLineChars); - return pDstBegin + bufPos; + RawText(_newLineChars); + return pDstBegin + _bufPos; } } @@ -1888,7 +1888,7 @@ namespace System.Xml { if (allowOnlyWhitespace) { - if (!xmlCharType.IsOnlyWhitespace(chars)) + if (!_xmlCharType.IsOnlyWhitespace(chars)) { throw new ArgumentException(SR.Format(SR.Xml_IndentCharsNotWhitespace, propertyName)); } @@ -1898,7 +1898,7 @@ namespace System.Xml string error = null; for (int i = 0; i < chars.Length; i++) { - if (!xmlCharType.IsTextChar(chars[i])) + if (!_xmlCharType.IsTextChar(chars[i])) { switch (chars[i]) { @@ -1948,14 +1948,14 @@ namespace System.Xml // // Fields // - protected int indentLevel; - protected bool newLineOnAttributes; - protected string indentChars; + protected int _indentLevel; + protected bool _newLineOnAttributes; + protected string _indentChars; - protected bool mixedContent; + protected bool _mixedContent; private BitStack _mixedContentStack; - protected ConformanceLevel conformanceLevel = ConformanceLevel.Auto; + protected ConformanceLevel _conformanceLevel = ConformanceLevel.Auto; // // Constructors @@ -1984,8 +1984,8 @@ namespace System.Xml settings.ReadOnly = false; settings.Indent = true; - settings.IndentChars = indentChars; - settings.NewLineOnAttributes = newLineOnAttributes; + settings.IndentChars = _indentChars; + settings.NewLineOnAttributes = _newLineOnAttributes; settings.ReadOnly = true; return settings; @@ -1995,7 +1995,7 @@ namespace System.Xml public override void WriteDocType(string name, string pubid, string sysid, string subset) { // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -2007,12 +2007,12 @@ namespace System.Xml Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } - indentLevel++; - _mixedContentStack.PushBit(mixedContent); + _indentLevel++; + _mixedContentStack.PushBit(_mixedContent); base.WriteStartElement(prefix, localName, ns); } @@ -2020,16 +2020,16 @@ namespace System.Xml internal override void StartElementContent() { // If this is the root element and we're writing a document - // do not inherit the mixedContent flag into the root element. + // do not inherit the _mixedContent flag into the root element. // This is to allow for whitespace nodes on root level // without disabling indentation for the whole document. - if (indentLevel == 1 && conformanceLevel == ConformanceLevel.Document) + if (_indentLevel == 1 && _conformanceLevel == ConformanceLevel.Document) { - mixedContent = false; + _mixedContent = false; } else { - mixedContent = _mixedContentStack.PeekBit(); + _mixedContent = _mixedContentStack.PeekBit(); } base.StartElementContent(); } @@ -2037,22 +2037,22 @@ namespace System.Xml internal override void OnRootElement(ConformanceLevel currentConformanceLevel) { // Just remember the current conformance level - conformanceLevel = currentConformanceLevel; + _conformanceLevel = currentConformanceLevel; } internal override void WriteEndElement(string prefix, string localName, string ns) { // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { WriteIndent(); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); base.WriteEndElement(prefix, localName, ns); } @@ -2060,16 +2060,16 @@ namespace System.Xml internal override void WriteFullEndElement(string prefix, string localName, string ns) { // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { WriteIndent(); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); base.WriteFullEndElement(prefix, localName, ns); } @@ -2078,7 +2078,7 @@ namespace System.Xml public override void WriteStartAttribute(string prefix, string localName, string ns) { // Add indentation - if (newLineOnAttributes) + if (_newLineOnAttributes) { WriteIndent(); } @@ -2088,13 +2088,13 @@ namespace System.Xml public override void WriteCData(string text) { - mixedContent = true; + _mixedContent = true; base.WriteCData(text); } public override void WriteComment(string text) { - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -2104,7 +2104,7 @@ namespace System.Xml public override void WriteProcessingInstruction(string target, string text) { - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -2114,55 +2114,55 @@ namespace System.Xml public override void WriteEntityRef(string name) { - mixedContent = true; + _mixedContent = true; base.WriteEntityRef(name); } public override void WriteCharEntity(char ch) { - mixedContent = true; + _mixedContent = true; base.WriteCharEntity(ch); } public override void WriteSurrogateCharEntity(char lowChar, char highChar) { - mixedContent = true; + _mixedContent = true; base.WriteSurrogateCharEntity(lowChar, highChar); } public override void WriteWhitespace(string ws) { - mixedContent = true; + _mixedContent = true; base.WriteWhitespace(ws); } public override void WriteString(string text) { - mixedContent = true; + _mixedContent = true; base.WriteString(text); } public override void WriteChars(char[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteChars(buffer, index, count); } public override void WriteRaw(char[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteRaw(buffer, index, count); } public override void WriteRaw(string data) { - mixedContent = true; + _mixedContent = true; base.WriteRaw(data); } public override void WriteBase64(byte[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteBase64(buffer, index, count); } @@ -2171,25 +2171,25 @@ namespace System.Xml // private void Init(XmlWriterSettings settings) { - indentLevel = 0; - indentChars = settings.IndentChars; - newLineOnAttributes = settings.NewLineOnAttributes; + _indentLevel = 0; + _indentChars = settings.IndentChars; + _newLineOnAttributes = settings.NewLineOnAttributes; _mixedContentStack = new BitStack(); // check indent characters that they are valid XML characters - if (base.checkCharacters) + if (base._checkCharacters) { - if (newLineOnAttributes) + if (_newLineOnAttributes) { - base.ValidateContentChars(indentChars, "IndentChars", true); - base.ValidateContentChars(newLineChars, "NewLineChars", true); + base.ValidateContentChars(_indentChars, "IndentChars", true); + base.ValidateContentChars(_newLineChars, "NewLineChars", true); } else { - base.ValidateContentChars(indentChars, "IndentChars", false); - if (base.newLineHandling != NewLineHandling.Replace) + base.ValidateContentChars(_indentChars, "IndentChars", false); + if (base._newLineHandling != NewLineHandling.Replace) { - base.ValidateContentChars(newLineChars, "NewLineChars", false); + base.ValidateContentChars(_newLineChars, "NewLineChars", false); } } } @@ -2198,10 +2198,10 @@ namespace System.Xml // Add indentation to output. Write newline and then repeat IndentChars for each indent level. private void WriteIndent() { - RawText(base.newLineChars); - for (int i = indentLevel; i > 0; i--) + RawText(base._newLineChars); + for (int i = _indentLevel; i > 0; i--) { - RawText(indentChars); + RawText(_indentChars); } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude index 52032722d5d9a..f5ce13f095197 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude @@ -37,7 +37,7 @@ namespace System.Xml { CheckAsyncCall(); // Output xml declaration only if user allows it and it was not already output - if (!omitXmlDeclaration && !autoXmlDeclaration) + if (!_omitXmlDeclaration && !_autoXmlDeclaration) {<# /* Code block is to squash extra line. */ #><#= SetTextContentMark(4, 1, false) #> await RawTextAsync(" - else if (writer != null) + else if (_writer != null) { try { - await writer.FlushAsync().ConfigureAwait(false); + await _writer.FlushAsync().ConfigureAwait(false); } finally { try { - if (closeOutput) + if (_closeOutput) { - await writer.DisposeAsync().ConfigureAwait(false); + await _writer.DisposeAsync().ConfigureAwait(false); } } finally { - writer = null; + _writer = null; } } } @@ -152,27 +152,27 @@ namespace System.Xml { await RawTextAsync(sysid).ConfigureAwait(false); } - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; } else if (sysid != null) { await RawTextAsync(" SYSTEM \"").ConfigureAwait(false); await RawTextAsync(sysid).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; } else { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; } if (subset != null) { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'['; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'['; await RawTextAsync(subset).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)']'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)']'; } - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize the beginning of an element start tag: "<#= SetTextContentMark(3, false) #> Task task; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; if (prefix != null && prefix.Length != 0) { task = RawTextAsync(prefix, ":", localName); @@ -199,7 +199,7 @@ namespace System.Xml private void WriteStartElementAsync_SetAttEndPos() { - attrEndPos = bufPos; + _attrEndPos = _bufPos; } // Serialize an element end tag: "", if content was output. Otherwise, serialize @@ -212,11 +212,11 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - if (contentPos != bufPos) + if (_contentPos != _bufPos) { // Content has been output, so can't use shortcut syntax - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'/'; if (prefix != null && prefix.Length != 0) { @@ -230,10 +230,10 @@ namespace System.Xml else { // Use shortcut syntax; overwrite the already output '>' character - bufPos--; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + _bufPos--; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'/'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } return Task.CompletedTask; } @@ -247,8 +247,8 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'/'; if (prefix != null && prefix.Length != 0) { @@ -269,9 +269,9 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - if (attrEndPos == bufPos) + if (_attrEndPos == _bufPos) { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; } Task task; if (prefix != null && prefix.Length > 0) @@ -287,9 +287,9 @@ namespace System.Xml private void WriteStartAttribute_SetInAttribute() { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'='; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; - inAttributeValue = true; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'='; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; + _inAttributeValue = true; } // Serialize the end of an attribute value using double quotes: '"' @@ -299,9 +299,9 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; - inAttributeValue = false; - attrEndPos = bufPos; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; + _inAttributeValue = false; + _attrEndPos = _bufPos; return Task.CompletedTask; } @@ -331,11 +331,11 @@ namespace System.Xml { await RawTextAsync(" xmlns:").ConfigureAwait(false); await RawTextAsync(prefix).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'='; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'='; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; } - inAttributeValue = true;<# + _inAttributeValue = true;<# #><#= SetTextContentMark(3, true) #> } @@ -345,10 +345,10 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - inAttributeValue = false; + _inAttributeValue = false; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"'; - attrEndPos = bufPos; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; + _attrEndPos = _bufPos; return Task.CompletedTask; } @@ -362,34 +362,34 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - if (mergeCDataSections && bufPos == cdataPos) + if (_mergeCDataSections && _bufPos == _cdataPos) { // Merge adjacent cdata sections - overwrite the "]]>" characters - Debug.Assert(bufPos >= 4); - bufPos -= 3; + Debug.Assert(_bufPos >= 4); + _bufPos -= 3; } else { // Start a new cdata section - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'['; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'C'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'D'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'T'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'['; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'!'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'['; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'C'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'D'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'A'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'T'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'A'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'['; } await WriteCDataSectionAsync(text).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)']'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)']'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)']'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)']'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; - textPos = bufPos; - cdataPos = bufPos; + _textPos = _bufPos; + _cdataPos = _bufPos; } // Serialize a comment. @@ -400,16 +400,16 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'!'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; await WriteCommentOrPiAsync(text, '-').ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'-'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize a processing instruction. @@ -421,18 +421,18 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'<'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'?'; await RawTextAsync(name).ConfigureAwait(false); if (text.Length > 0) { - <#= BufferName #>[bufPos++] = (<#= BufferType #>)' '; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; await WriteCommentOrPiAsync(text, '?').ConfigureAwait(false); } - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'?'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'>'; } // Serialize an entity reference. @@ -443,16 +443,16 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'&'; await RawTextAsync(name).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)';'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a character entity reference. @@ -461,7 +461,7 @@ namespace System.Xml CheckAsyncCall(); string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); - if (checkCharacters && !xmlCharType.IsCharData(ch)) + if (_checkCharacters && !_xmlCharType.IsCharData(ch)) { // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char throw XmlConvert.CreateInvalidCharException(ch, '\0'); @@ -469,18 +469,18 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'&'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'#'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'x'; await RawTextAsync(strVal).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)';'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a whitespace node. @@ -491,7 +491,7 @@ namespace System.Xml Debug.Assert(ws != null);<# #><#= SetTextContentMark(3, false) #> - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(ws); } @@ -509,7 +509,7 @@ namespace System.Xml Debug.Assert(text != null);<# #><#= SetTextContentMark(3, true) #> - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(text); } @@ -527,12 +527,12 @@ namespace System.Xml int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#'; - <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'&'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'#'; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'x'; await RawTextAsync(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)).ConfigureAwait(false); - <#= BufferName #>[bufPos++] = (<#= BufferType #>)';'; - textPos = bufPos; + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)';'; + _textPos = _bufPos; } // Serialize either attribute or element text using XML rules. @@ -547,7 +547,7 @@ namespace System.Xml #><#= SetTextContentMark(3, true) #> - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(buffer, index, count); } @@ -571,7 +571,7 @@ namespace System.Xml await WriteRawWithCharCheckingAsync(buffer, index, count).ConfigureAwait(false); - textPos = bufPos; + _textPos = _bufPos; } // Serialize raw data. @@ -585,7 +585,7 @@ namespace System.Xml await WriteRawWithCharCheckingAsync(data).ConfigureAwait(false); - textPos = bufPos; + _textPos = _bufPos; } // Flush all characters in the buffer to output and call Flush() on the output object. @@ -597,14 +597,14 @@ namespace System.Xml await FlushEncoderAsync().ConfigureAwait(false); <# } #> - if (stream != null) + if (_stream != null) { - await stream.FlushAsync().ConfigureAwait(false); + await _stream.FlushAsync().ConfigureAwait(false); } <# if (WriterType == RawTextWriterType.Encoded) { #> - else if (writer != null) + else if (_writer != null) { - await writer.FlushAsync().ConfigureAwait(false); + await _writer.FlushAsync().ConfigureAwait(false); } <# } #> } @@ -618,20 +618,20 @@ namespace System.Xml try { // Output all characters (except for previous characters stored at beginning of buffer) - if (!writeToNull) + if (!_writeToNull) { <# if (WriterType == RawTextWriterType.Utf8) { #> - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { - Debug.Assert(stream != null); - await stream.WriteAsync(bufBytes, 1, bufPos - 1).ConfigureAwait(false); + Debug.Assert(_stream != null); + await _stream.WriteAsync(_bufBytes.AsMemory(1, _bufPos - 1)).ConfigureAwait(false); } <# } else { #> - Debug.Assert(stream != null || writer != null); + Debug.Assert(_stream != null || _writer != null); - if (stream != null) + if (_stream != null) { - if (trackTextContent) + if (_trackTextContent) { _charEntityFallback.Reset(_textContentMarks, _lastMarkPos); // reset text content tracking @@ -649,14 +649,14 @@ namespace System.Xml } Debug.Assert(_textContentMarks[0] == 1); } - await EncodeCharsAsync(1, bufPos, true).ConfigureAwait(false); + await EncodeCharsAsync(1, _bufPos, true).ConfigureAwait(false); } else { - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { // Write text to TextWriter - await writer.WriteAsync(<#= BufferName #>, 1, bufPos - 1).ConfigureAwait(false); + await _writer.WriteAsync(<#= BufferName #>.AsMemory(1, _bufPos - 1)).ConfigureAwait(false); } } <# } #> @@ -665,31 +665,31 @@ namespace System.Xml catch { // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream - writeToNull = true; + _writeToNull = true; throw; } finally { // Move last buffer character to the beginning of the buffer (so that previous character can always be determined) - <#= BufferName #>[0] = <#= BufferName #>[bufPos - 1]; + <#= BufferName #>[0] = <#= BufferName #>[_bufPos - 1]; <# if (WriterType == RawTextWriterType.Utf8) { #> - if (IsSurrogateByte(bufBytes[0])) + if (IsSurrogateByte(_bufBytes[0])) { // Last character was the first byte in a surrogate encoding, so move last three // bytes of encoding to the beginning of the buffer. - bufBytes[1] = bufBytes[bufPos]; - bufBytes[2] = bufBytes[bufPos + 1]; - bufBytes[3] = bufBytes[bufPos + 2]; + _bufBytes[1] = _bufBytes[_bufPos]; + _bufBytes[2] = _bufBytes[_bufPos + 1]; + _bufBytes[3] = _bufBytes[_bufPos + 2]; } <# } #> // Reset buffer position - textPos = (textPos == bufPos) ? 1 : 0; - attrEndPos = (attrEndPos == bufPos) ? 1 : 0; - contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible - cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible - bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + _textPos = (_textPos == _bufPos) ? 1 : 0; + _attrEndPos = (_attrEndPos == _bufPos) ? 1 : 0; + _contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible + _cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible + _bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0 } } @@ -706,35 +706,35 @@ namespace System.Xml { _charEntityFallback.StartOffset = startOffset; } - encoder.Convert(<#= BufferName #>, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed); + _encoder.Convert(<#= BufferName #>, startOffset, endOffset - startOffset, _bufBytes, _bufBytesUsed, _bufBytes.Length - _bufBytesUsed, false, out chEnc, out bEnc, out completed); startOffset += chEnc; - bufBytesUsed += bEnc; - if (bufBytesUsed >= (bufBytes.Length - 16)) + _bufBytesUsed += bEnc; + if (_bufBytesUsed >= (_bufBytes.Length - 16)) { - await stream.WriteAsync(bufBytes, 0, bufBytesUsed).ConfigureAwait(false); - bufBytesUsed = 0; + await _stream.WriteAsync(_bufBytes.AsMemory(0, _bufBytesUsed)).ConfigureAwait(false); + _bufBytesUsed = 0; } } - if (writeAllToStream && bufBytesUsed > 0) + if (writeAllToStream && _bufBytesUsed > 0) { - await stream.WriteAsync(bufBytes, 0, bufBytesUsed).ConfigureAwait(false); - bufBytesUsed = 0; + await _stream.WriteAsync(_bufBytes.AsMemory(0, _bufBytesUsed)).ConfigureAwait(false); + _bufBytesUsed = 0; } } private Task FlushEncoderAsync() { - Debug.Assert(bufPos == 1); - if (stream != null) + Debug.Assert(_bufPos == 1); + if (_stream != null) { int chEnc; int bEnc; bool completed; // decode no chars, just flush - encoder.Convert(<#= BufferName #>, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed); + _encoder.Convert(<#= BufferName #>, 1, 0, _bufBytes, 0, _bufBytes.Length, true, out chEnc, out bEnc, out completed); if (bEnc != 0) { - return stream.WriteAsync(bufBytes, 0, bEnc); + return _stream.WriteAsync(_bufBytes, 0, bEnc); } } @@ -750,21 +750,21 @@ namespace System.Xml fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -782,7 +782,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -806,7 +806,7 @@ namespace System.Xml pDst++; break; case (char)0x9: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (<#= BufferType #>)ch; pDst++; @@ -818,7 +818,7 @@ namespace System.Xml } break; case (char)0xD: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (<#= BufferType #>)ch; pDst++; @@ -830,7 +830,7 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (<#= BufferType #>)ch; pDst++; @@ -847,7 +847,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -940,21 +940,21 @@ namespace System.Xml fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsAttributeValueChar((char)(ch = *pSrc))) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -972,7 +972,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -995,9 +995,9 @@ namespace System.Xml pDst++; break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1008,7 +1008,7 @@ namespace System.Xml } break; case (char)0xD: - switch (newLineHandling) + switch (_newLineHandling) { case NewLineHandling.Replace: // Replace "\r\n", or "\r" with NewLineChars @@ -1017,7 +1017,7 @@ namespace System.Xml pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); @@ -1037,9 +1037,9 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); - textPos = bufPos; - contentPos = 0; + _bufPos = (int)(pDst - pDstBegin); + _textPos = _bufPos; + _contentPos = 0; } return -1; @@ -1050,7 +1050,7 @@ namespace System.Xml needWriteNewLine = false; if (count == 0) { - contentPos = 0; + _contentPos = 0; return -1; } fixed (char* pSrc = &chars[index]) @@ -1066,7 +1066,7 @@ namespace System.Xml needWriteNewLine = false; if (count == 0) { - contentPos = 0; + _contentPos = 0; return -1; } fixed (char* pSrc = text) @@ -1091,7 +1091,7 @@ namespace System.Xml if (needWriteNewLine) { //hit WriteNewLine - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1131,7 +1131,7 @@ namespace System.Xml if (newLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1148,7 +1148,7 @@ namespace System.Xml if (needWriteNewLine) { //hit WriteNewLine - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1165,16 +1165,16 @@ namespace System.Xml fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; char* pSrc = pSrcBegin; int ch = 0; while (true) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> @@ -1198,14 +1198,14 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } <#= EncodeChar(5, false) #> } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1327,21 +1327,21 @@ namespace System.Xml fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>) { char* pSrc = pSrcBegin; - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && xmlCharType.IsTextChar((char)(ch = *pSrc))) + while (pDst < pDstEnd && _xmlCharType.IsTextChar((char)(ch = *pSrc))) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1360,7 +1360,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1375,7 +1375,7 @@ namespace System.Xml pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1383,7 +1383,7 @@ namespace System.Xml pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1394,9 +1394,9 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1412,7 +1412,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1461,7 +1461,7 @@ namespace System.Xml leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1485,7 +1485,7 @@ namespace System.Xml leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1515,21 +1515,21 @@ namespace System.Xml char* pSrcEnd = pSrcBegin + count; - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar)) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1548,7 +1548,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1586,7 +1586,7 @@ namespace System.Xml pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1594,7 +1594,7 @@ namespace System.Xml pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1605,9 +1605,9 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1629,7 +1629,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1640,7 +1640,7 @@ namespace System.Xml { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } @@ -1658,7 +1658,7 @@ namespace System.Xml leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1691,21 +1691,21 @@ namespace System.Xml char* pRaw = pSrc; - <#= BufferType #>* pDst = pDstBegin + bufPos; + <#= BufferType #>* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } <# if (WriterType == RawTextWriterType.Utf8) { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) <# } else { #> - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']')) <# } #> { *pDst = (<#= BufferType #>)ch; @@ -1724,7 +1724,7 @@ namespace System.Xml // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1732,7 +1732,7 @@ namespace System.Xml switch (ch) { case '>': - if (hadDoubleBracket && pDst[-1] == (<#= BufferType #>)']') + if (_hadDoubleBracket && pDst[-1] == (<#= BufferType #>)']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0] // The characters "]]>" were found within the CData text pDst = RawEndCData(pDst); @@ -1744,17 +1744,17 @@ namespace System.Xml case ']': if (pDst[-1] == (<#= BufferType #>)']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0] - hadDoubleBracket = true; + _hadDoubleBracket = true; } else { - hadDoubleBracket = false; + _hadDoubleBracket = false; } *pDst = (<#= BufferType #>)']'; pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1762,7 +1762,7 @@ namespace System.Xml pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1773,9 +1773,9 @@ namespace System.Xml } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1799,7 +1799,7 @@ namespace System.Xml } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1810,7 +1810,7 @@ namespace System.Xml { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } @@ -1828,7 +1828,7 @@ namespace System.Xml leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1847,7 +1847,7 @@ namespace System.Xml { CheckAsyncCall(); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1860,12 +1860,12 @@ namespace System.Xml Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } - indentLevel++; - _mixedContentStack.PushBit(mixedContent); + _indentLevel++; + _mixedContentStack.PushBit(_mixedContent); await base.WriteStartElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1874,16 +1874,16 @@ namespace System.Xml { CheckAsyncCall(); // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); await base.WriteEndElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1892,16 +1892,16 @@ namespace System.Xml { CheckAsyncCall(); // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); await base.WriteFullEndElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1911,7 +1911,7 @@ namespace System.Xml { CheckAsyncCall(); // Add indentation - if (newLineOnAttributes) + if (_newLineOnAttributes) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1922,14 +1922,14 @@ namespace System.Xml public override Task WriteCDataAsync(string text) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCDataAsync(text); } public override async Task WriteCommentAsync(string text) { CheckAsyncCall(); - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1940,7 +1940,7 @@ namespace System.Xml public override async Task WriteProcessingInstructionAsync(string target, string text) { CheckAsyncCall(); - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1951,63 +1951,63 @@ namespace System.Xml public override Task WriteEntityRefAsync(string name) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteEntityRefAsync(name); } public override Task WriteCharEntityAsync(char ch) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCharEntityAsync(ch); } public override Task WriteSurrogateCharEntityAsync(char lowChar, char highChar) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteSurrogateCharEntityAsync(lowChar, highChar); } public override Task WriteWhitespaceAsync(string ws) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteWhitespaceAsync(ws); } public override Task WriteStringAsync(string text) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteStringAsync(text); } public override Task WriteCharsAsync(char[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCharsAsync(buffer, index, count); } public override Task WriteRawAsync(char[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteRawAsync(buffer, index, count); } public override Task WriteRawAsync(string data) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteRawAsync(data); } public override Task WriteBase64Async(byte[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteBase64Async(buffer, index, count); } @@ -2015,10 +2015,10 @@ namespace System.Xml private async Task WriteIndentAsync() { CheckAsyncCall(); - await RawTextAsync(base.newLineChars).ConfigureAwait(false); - for (int i = indentLevel; i > 0; i--) + await RawTextAsync(base._newLineChars).ConfigureAwait(false); + for (int i = _indentLevel; i > 0; i--) { - await RawTextAsync(indentChars).ConfigureAwait(false); + await RawTextAsync(_indentChars).ConfigureAwait(false); } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriter.cs index 952c3d2348e99..e9d8937b34913 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Diagnostics; @@ -43,10 +44,10 @@ internal abstract partial class XmlRawWriter : XmlWriter // Fields // // base64 converter - protected XmlRawWriterBase64Encoder base64Encoder; + protected XmlRawWriterBase64Encoder? _base64Encoder; // namespace resolver - protected IXmlNamespaceResolver resolver; + protected IXmlNamespaceResolver? _resolver; // // XmlWriter implementation @@ -68,7 +69,7 @@ public override void WriteEndDocument() throw new InvalidOperationException(SR.Xml_InvalidOperation); } - public override void WriteDocType(string name, string pubid, string sysid, string subset) + public override void WriteDocType(string name, string? pubid, string? sysid, string? subset) { } @@ -87,12 +88,13 @@ public override void WriteFullEndElement() // By default, convert base64 value to string and call WriteString. public override void WriteBase64(byte[] buffer, int index, int count) { - if (base64Encoder == null) + if (_base64Encoder == null) { - base64Encoder = new XmlRawWriterBase64Encoder(this); + _base64Encoder = new XmlRawWriterBase64Encoder(this); } + // Encode will call WriteRaw to write out the encoded characters - base64Encoder.Encode(buffer, index, count); + _base64Encoder.Encode(buffer, index, count); } // Raw writers do not have to keep track of namespaces. @@ -135,13 +137,13 @@ public override void WriteName(string name) } // Raw writers do not have to verify QName values. - public override void WriteQualifiedName(string localName, string ns) + public override void WriteQualifiedName(string localName, string? ns) { throw new InvalidOperationException(SR.Xml_InvalidOperation); } // Forward call to WriteString(string). - public override void WriteCData(string text) + public override void WriteCData(string? text) { WriteString(text); } @@ -184,17 +186,18 @@ public override void WriteRaw(string data) } // Override in order to handle Xml simple typed values and to pass resolver for QName values - public override void WriteValue(object value) + public override void WriteValue(object? value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } - WriteString(XmlUntypedConverter.Untyped.ToString(value, resolver)); + + WriteString(XmlUntypedConverter.Untyped.ToString(value, _resolver)); } // Override in order to handle Xml simple typed values and to pass resolver for QName values - public override void WriteValue(string value) + public override void WriteValue(string? value) { WriteString(value); } @@ -227,15 +230,15 @@ public override void WriteNode(System.Xml.XPath.XPathNavigator navigator, bool d // // Get and set the namespace resolver that's used by this RawWriter to resolve prefixes. - internal virtual IXmlNamespaceResolver NamespaceResolver + internal virtual IXmlNamespaceResolver? NamespaceResolver { get { - return resolver; + return _resolver; } set { - resolver = value; + _resolver = value; } } @@ -275,6 +278,7 @@ internal virtual void WriteQualifiedName(string prefix, string localName, string WriteString(prefix); WriteString(":"); } + WriteString(localName); } @@ -311,7 +315,8 @@ internal virtual void WriteEndNamespaceDeclaration() internal virtual void WriteEndBase64() { // The Flush will call WriteRaw to write out the rest of the encoded characters - base64Encoder.Flush(); + Debug.Assert(_base64Encoder != null); + _base64Encoder.Flush(); } internal virtual void Close(WriteState currentState) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriterAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriterAsync.cs index b602201b1eb20..c668e07932fb7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriterAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawWriterAsync.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Diagnostics; @@ -60,7 +61,7 @@ public override Task WriteEndDocumentAsync() throw new InvalidOperationException(SR.Xml_InvalidOperation); } - public override Task WriteDocTypeAsync(string name, string pubid, string sysid, string subset) + public override Task WriteDocTypeAsync(string name, string? pubid, string? sysid, string subset) { return Task.CompletedTask; } @@ -80,12 +81,12 @@ public override Task WriteFullEndElementAsync() // By default, convert base64 value to string and call WriteString. public override Task WriteBase64Async(byte[] buffer, int index, int count) { - if (base64Encoder == null) + if (_base64Encoder == null) { - base64Encoder = new XmlRawWriterBase64Encoder(this); + _base64Encoder = new XmlRawWriterBase64Encoder(this); } // Encode will call WriteRaw to write out the encoded characters - return base64Encoder.EncodeAsync(buffer, index, count); + return _base64Encoder.EncodeAsync(buffer, index, count); } // Raw writers do not have to verify NmToken values. @@ -101,7 +102,7 @@ public override Task WriteNameAsync(string name) } // Raw writers do not have to verify QName values. - public override Task WriteQualifiedNameAsync(string localName, string ns) + public override Task WriteQualifiedNameAsync(string localName, string? ns) { throw new InvalidOperationException(SR.Xml_InvalidOperation); } @@ -200,6 +201,7 @@ internal virtual async Task WriteQualifiedNameAsync(string prefix, string localN await WriteStringAsync(prefix).ConfigureAwait(false); await WriteStringAsync(":").ConfigureAwait(false); } + await WriteStringAsync(localName).ConfigureAwait(false); } @@ -224,7 +226,8 @@ internal virtual Task WriteEndNamespaceDeclarationAsync() internal virtual Task WriteEndBase64Async() { // The Flush will call WriteRaw to write out the rest of the encoded characters - return base64Encoder.FlushAsync(); + Debug.Assert(_base64Encoder != null); + return _base64Encoder.FlushAsync(); } internal virtual ValueTask DisposeAsyncCore(WriteState currentState) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs index 93eb9bb60d85e..67d70187bd0a8 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs @@ -651,6 +651,7 @@ private XmlReader AddValidationInternal(XmlReader reader, XmlResolver? resolver, { reader = new XsdValidatingReader(reader, GetXmlResolver_CheckConfig(), this); } + return reader; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextEncoder.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextEncoder.cs index 912615c9a1662..2e69660d785a3 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextEncoder.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextEncoder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Text; @@ -29,7 +30,7 @@ internal class XmlTextEncoder private char _quoteChar; // caching of attribute value - private StringBuilder _attrValue; + private StringBuilder? _attrValue; private bool _cacheAttrValue; // XmlCharType @@ -77,8 +78,10 @@ internal void EndAttribute() { if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Length = 0; } + _inAttribute = false; _cacheAttrValue = false; } @@ -89,6 +92,7 @@ internal string AttributeValue { if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); return _attrValue.ToString(); } else @@ -134,6 +138,7 @@ internal void Write(char[] array, int offset, int count) if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append(array, offset, count); } @@ -241,6 +246,7 @@ internal void WriteSurrogateCharEntity(char lowChar, char highChar) if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append(highChar); _attrValue.Append(lowChar); } @@ -259,6 +265,7 @@ internal void Write(string text) if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append(text); } @@ -395,8 +402,10 @@ internal void WriteRawWithSurrogateChecking(string text) { return; } + if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append(text); } @@ -469,8 +478,10 @@ internal void WriteRaw(char[] array, int offset, int count) if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append(array, offset, count); } + _textWriter.Write(array, offset, count); } @@ -486,10 +497,12 @@ internal void WriteCharEntity(char ch) string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append("&#x"); _attrValue.Append(strVal); _attrValue.Append(';'); } + WriteCharEntityImpl(strVal); } @@ -497,10 +510,12 @@ internal void WriteEntityRef(string name) { if (_cacheAttrValue) { + Debug.Assert(_attrValue != null); _attrValue.Append('&'); _attrValue.Append(name); _attrValue.Append(';'); } + WriteEntityRefImpl(name); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.Unix.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.Unix.cs index 96e32fd9d3a1d..bc856150e1304 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.Unix.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.Unix.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml { internal partial class XmlTextReaderImpl { - static partial void ConvertAbsoluteUnixPathToAbsoluteUri(ref string url, XmlResolver resolver) + static partial void ConvertAbsoluteUnixPathToAbsoluteUri(ref string url, XmlResolver? resolver) { // new Uri(uri, UriKind.RelativeOrAbsolute) returns a Relative Uri for absolute unix paths (e.g. /tmp). // We convert the native unix path to a 'file://' uri string to make it an Absolute Uri. @@ -27,4 +28,4 @@ internal partial class XmlTextReaderImpl } } } -} \ No newline at end of file +} diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs index ae7235e0f64d4..7b181e4b798bb 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs @@ -8410,6 +8410,7 @@ private int IncrementalRead(Array array, int index, int count) private int IncrementalRead() { Debug.Assert(_incReadDecoder != null); + Debug.Assert(_ps.chars != null); int charsDecoded = 0; OuterContinue: @@ -8505,7 +8506,6 @@ private int IncrementalRead() _incReadState == IncrementalReadState.Attributes || _incReadState == IncrementalReadState.AttributeValue); - Debug.Assert(_ps.chars != null); char[] chars = _ps.chars; startPos = _ps.charPos; pos = startPos; @@ -9633,6 +9633,7 @@ private int ReadContentAsBinary(byte[] buffer, int index, int count) if (_incReadState == IncrementalReadState.ReadContentAsBinary_OnPartialValue) { _curNode.SetValue(string.Empty); + Debug.Assert(_ps.chars != null); // read next chunk of text bool endOfValue = false; @@ -9657,12 +9658,12 @@ private int ReadContentAsBinary(byte[] buffer, int index, int count) } startPos += charsRead; } + _incReadState = endOfValue ? IncrementalReadState.ReadContentAsBinary_OnCachedValue : IncrementalReadState.ReadContentAsBinary_OnPartialValue; _readValueOffset = 0; if (_incReadDecoder.IsFull) { - Debug.Assert(_ps.chars != null); _curNode.SetValue(_ps.chars, startPos, endPos - startPos); // adjust line info for the chunk that has been already decoded AdjustLineInfo(_ps.chars, startPos - charsRead, startPos, _ps.eolNormalized, ref _incReadLineInfo); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs index a6e8135b92176..50a457599f8f0 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs @@ -975,7 +975,7 @@ private async Task InitStreamInputAsync(Uri baseUri, string baseUriStr, Stream s _ps.bytePos = 0; while (_ps.bytesUsed < 4 && _ps.bytes.Length - _ps.bytesUsed > 0) { - int read = await stream.ReadAsync(_ps.bytes, _ps.bytesUsed, _ps.bytes.Length - _ps.bytesUsed).ConfigureAwait(false); + int read = await stream.ReadAsync(_ps.bytes.AsMemory(_ps.bytesUsed)).ConfigureAwait(false); if (read == 0) { _ps.isStreamEof = true; @@ -1192,7 +1192,7 @@ private async Task ReadDataAsync() // read new bytes if (_ps.bytePos == _ps.bytesUsed && _ps.bytes.Length - _ps.bytesUsed > 0) { - int read = await _ps.stream.ReadAsync(_ps.bytes, _ps.bytesUsed, _ps.bytes.Length - _ps.bytesUsed).ConfigureAwait(false); + int read = await _ps.stream.ReadAsync(_ps.bytes.AsMemory(_ps.bytesUsed)).ConfigureAwait(false); if (read == 0) { _ps.isStreamEof = true; @@ -1214,7 +1214,7 @@ private async Task ReadDataAsync() else if (_ps.textReader != null) { // read chars - charsRead = await _ps.textReader.ReadAsync(_ps.chars, _ps.charsUsed, _ps.chars.Length - _ps.charsUsed - 1).ConfigureAwait(false); + charsRead = await _ps.textReader.ReadAsync(_ps.chars.AsMemory(_ps.charsUsed, _ps.chars.Length - _ps.charsUsed - 1)).ConfigureAwait(false); _ps.charsUsed += charsRead; } else diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs index dc9a77df0696b..7f65f254fa31c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections; using System.Collections.Generic; @@ -25,7 +26,7 @@ public enum Formatting // and not Mixed Content (http://www.w3.org/TR/1998/REC-xml-19980210#sec-mixed-content) // according to the XML 1.0 definitions of these terms. Indented, - }; + } // Represents a writer that provides fast non-cached forward-only way of generating XML streams // containing XML documents that conform to the W3CExtensible Markup Language (XML) 1.0 specification @@ -47,12 +48,12 @@ private enum NamespaceState private struct TagInfo { - internal string name; - internal string prefix; + internal string? name; + internal string? prefix; internal string defaultNs; internal NamespaceState defaultNsState; internal XmlSpace xmlSpace; - internal string xmlLang; + internal string? xmlLang; internal int prevNsTop; internal int prefixCount; internal bool mixed; // whether to pretty print the contents of this element. @@ -131,9 +132,9 @@ private enum Token // Fields // // output - private readonly TextWriter _textWriter; - private readonly XmlTextEncoder _xmlEncoder; - private readonly Encoding _encoding; + private readonly TextWriter _textWriter = null!; + private readonly XmlTextEncoder _xmlEncoder = null!; + private readonly Encoding? _encoding; // formatting private Formatting _formatting; @@ -159,20 +160,20 @@ private static char[] CreateDefaultIndentChars() private Token _lastToken; // Base64 content - private XmlTextWriterBase64Encoder _base64Encoder; + private XmlTextWriterBase64Encoder? _base64Encoder; // misc private char _quoteChar; private char _curQuoteChar; private bool _namespaces; private SpecialAttr _specialAttr; - private string _prefixForXmlNs; + private string? _prefixForXmlNs; private bool _flush; // namespaces private Namespace[] _nsStack; private int _nsTop; - private Dictionary _nsHashtable; + private Dictionary? _nsHashtable; private bool _useNsHashtable; // char types @@ -259,7 +260,7 @@ private static char[] CreateDefaultIndentChars() // // Constructors // - internal XmlTextWriter() + private XmlTextWriter() { _namespaces = true; _formatting = Formatting.None; @@ -281,7 +282,7 @@ internal XmlTextWriter() } // Creates an instance of the XmlTextWriter class using the specified stream. - public XmlTextWriter(Stream w, Encoding encoding) : this() + public XmlTextWriter(Stream w, Encoding? encoding) : this() { _encoding = encoding; if (encoding != null) @@ -313,12 +314,18 @@ public XmlTextWriter(TextWriter w) : this() // XmlTextWriter properties // // Gets the XmlTextWriter base stream. - public Stream BaseStream + public Stream? BaseStream { get { - StreamWriter streamWriter = _textWriter as StreamWriter; - return (streamWriter == null ? null : streamWriter.BaseStream); + if (_textWriter is StreamWriter streamWriter) + { + return streamWriter.BaseStream; + } + else + { + return null; + } } } @@ -437,7 +444,7 @@ public override void WriteEndDocument() } // Writes out the DOCTYPE declaration with the specified name and optional attributes. - public override void WriteDocType(string name, string pubid, string sysid, string subset) + public override void WriteDocType(string name, string? pubid, string? sysid, string? subset) { try { @@ -476,7 +483,7 @@ public override void WriteDocType(string name, string pubid, string sysid, strin } // Writes out the specified start tag and associates it with the given namespace and prefix. - public override void WriteStartElement(string prefix, string localName, string ns) + public override void WriteStartElement(string? prefix, string localName, string? ns) { try { @@ -503,7 +510,7 @@ public override void WriteStartElement(string prefix, string localName, string n { if (prefix == null) { - string definedPrefix = FindPrefix(ns); + string? definedPrefix = FindPrefix(ns); if (definedPrefix != null) { prefix = definedPrefix; @@ -523,6 +530,7 @@ public override void WriteStartElement(string prefix, string localName, string n { prefix = null; } + VerifyPrefixXml(prefix, ns); PushNamespace(prefix, ns, false); // define } @@ -565,7 +573,7 @@ public override void WriteFullEndElement() } // Writes the start of an attribute. - public override void WriteStartAttribute(string prefix, string localName, string ns) + public override void WriteStartAttribute(string? prefix, string localName, string? ns) { try { @@ -607,6 +615,7 @@ public override void WriteStartAttribute(string prefix, string localName, string { throw new ArgumentException(SR.Xml_XmlnsBelongsToReservedNs); } + if (localName == null || localName.Length == 0) { localName = prefix; @@ -617,6 +626,7 @@ public override void WriteStartAttribute(string prefix, string localName, string { _prefixForXmlNs = localName; } + _specialAttr = SpecialAttr.XmlNs; } else if (prefix == null && localName == "xmlns") @@ -626,6 +636,7 @@ public override void WriteStartAttribute(string prefix, string localName, string // add the below line back in when DOM is fixed throw new ArgumentException(SR.Xml_XmlnsBelongsToReservedNs); } + _specialAttr = SpecialAttr.XmlNs; _prefixForXmlNs = null; } @@ -651,8 +662,9 @@ public override void WriteStartAttribute(string prefix, string localName, string { prefix = null; } + // Now verify prefix validity - string definedPrefix = FindPrefix(ns); + string? definedPrefix = FindPrefix(ns); if (definedPrefix != null && (prefix == null || prefix == definedPrefix)) { prefix = definedPrefix; @@ -667,6 +679,7 @@ public override void WriteStartAttribute(string prefix, string localName, string } } } + if (prefix != null && prefix.Length != 0) { _textWriter.Write(prefix); @@ -679,15 +692,18 @@ public override void WriteStartAttribute(string prefix, string localName, string { throw new ArgumentException(SR.Xml_NoNamespaces); } + if (localName == "xml:lang") { _specialAttr = SpecialAttr.XmlLang; } + else if (localName == "xml:space") { _specialAttr = SpecialAttr.XmlSpace; } } + _xmlEncoder.StartAttribute(_specialAttr != SpecialAttr.None); _textWriter.Write(localName); @@ -721,7 +737,7 @@ public override void WriteEndAttribute() } // Writes out a <![CDATA[...]]> block containing the specified text. - public override void WriteCData(string text) + public override void WriteCData(string? text) { try { @@ -730,12 +746,14 @@ public override void WriteCData(string text) { throw new ArgumentException(SR.Xml_InvalidCDataChars); } + _textWriter.Write(""); } catch @@ -770,7 +788,7 @@ public override void WriteComment(string text) } // Writes out a processing instruction with a space between the name and text as follows: - public override void WriteProcessingInstruction(string name, string text) + public override void WriteProcessingInstruction(string name, string? text) { try { @@ -778,10 +796,12 @@ public override void WriteProcessingInstruction(string name, string text) { throw new ArgumentException(SR.Xml_InvalidPiChars); } + if (0 == string.Compare(name, "xml", StringComparison.OrdinalIgnoreCase) && _stateTable == s_stateTableDocument) { throw new ArgumentException(SR.Xml_DupXmlDecl); } + AutoComplete(Token.PI); InternalWriteProcessingInstruction(name, text); } @@ -848,7 +868,7 @@ public override void WriteWhitespace(string ws) } // Writes out the specified text content. - public override void WriteString(string text) + public override void WriteString(string? text) { try { @@ -1040,7 +1060,7 @@ public override void WriteName(string name) } // Writes out the specified namespace-qualified name by looking up the prefix that is in scope for the given namespace. - public override void WriteQualifiedName(string localName, string ns) + public override void WriteQualifiedName(string localName, string? ns) { try { @@ -1049,16 +1069,18 @@ public override void WriteQualifiedName(string localName, string ns) { if (ns != null && ns.Length != 0 && ns != _stack[_top].defaultNs) { - string prefix = FindPrefix(ns); + string? prefix = FindPrefix(ns); if (prefix == null) { if (_currentState != State.Attribute) { throw new ArgumentException(SR.Format(SR.Xml_UndefNamespace, ns)); } - prefix = GeneratePrefix(); // need a prefix if + + prefix = GeneratePrefix(); PushNamespace(prefix, ns, false); } + if (prefix.Length != 0) { InternalWriteName(prefix, true); @@ -1070,6 +1092,7 @@ public override void WriteQualifiedName(string localName, string ns) { throw new ArgumentException(SR.Xml_NoNamespaces); } + InternalWriteName(localName, true); } catch @@ -1080,17 +1103,19 @@ public override void WriteQualifiedName(string localName, string ns) } // Returns the closest prefix defined in the current namespace scope for the specified namespace URI. - public override string LookupPrefix(string ns) + public override string? LookupPrefix(string ns) { if (ns == null || ns.Length == 0) { throw new ArgumentException(SR.Xml_EmptyName); } - string s = FindPrefix(ns); + + string? s = FindPrefix(ns); if (s == null && ns == _stack[_top].defaultNs) { s = string.Empty; } + return s; } @@ -1110,16 +1135,18 @@ public override XmlSpace XmlSpace } // Gets the current xml:lang scope. - public override string XmlLang + public override string? XmlLang { get { for (int i = _top; i > 0; i--) { - string xlang = _stack[i].xmlLang; + string? xlang = _stack[i].xmlLang; + if (xlang != null) return xlang; } + return null; } } @@ -1444,7 +1471,7 @@ private void Indent(bool beforeEndElement) // pushes new namespace scope, and returns generated prefix, if one // was needed to resolve conflicts. - private void PushNamespace(string prefix, string ns, bool declared) + private void PushNamespace(string? prefix, string ns, bool declared) { if (XmlReservedNs.NsXmlNs == ns) { @@ -1469,6 +1496,7 @@ private void PushNamespace(string prefix, string ns, bool declared) Debug.Fail("Should have never come here"); return; } + _stack[_top].defaultNsState = (declared ? NamespaceState.DeclaredAndWrittenOut : NamespaceState.DeclaredButNotWrittenOut); } else @@ -1497,6 +1525,7 @@ private void PushNamespace(string prefix, string ns, bool declared) _nsStack[existingNsIndex].declared = true; // old one is silenced now } } + AddNamespace(prefix, ns, declared); } } @@ -1521,28 +1550,36 @@ private void AddNamespace(string prefix, string ns, bool declared) { // add all _nsHashtable = new Dictionary(); + _useNsHashtable = true; + for (int i = 0; i <= nsIndex; i++) { AddToNamespaceHashtable(i); } - _useNsHashtable = true; } } private void AddToNamespaceHashtable(int namespaceIndex) { + Debug.Assert(_useNsHashtable); + Debug.Assert(_nsHashtable != null); + string prefix = _nsStack[namespaceIndex].prefix; int existingNsIndex; + if (_nsHashtable.TryGetValue(prefix, out existingNsIndex)) { _nsStack[namespaceIndex].prevNsIndex = existingNsIndex; } + _nsHashtable[prefix] = namespaceIndex; } private void PopNamespaces(int indexFrom, int indexTo) { Debug.Assert(_useNsHashtable); + Debug.Assert(_nsHashtable != null); + for (int i = indexTo; i >= indexFrom; i--) { Debug.Assert(_nsHashtable.ContainsKey(_nsStack[i].prefix)); @@ -1564,16 +1601,18 @@ private string GeneratePrefix() + "p" + temp.ToString("d", CultureInfo.InvariantCulture); } - private void InternalWriteProcessingInstruction(string name, string text) + private void InternalWriteProcessingInstruction(string name, string? text) { _textWriter.Write(""); } @@ -1581,6 +1620,7 @@ private int LookupNamespace(string prefix) { if (_useNsHashtable) { + Debug.Assert(_nsHashtable != null); int nsIndex; if (_nsHashtable.TryGetValue(prefix, out nsIndex)) { @@ -1597,6 +1637,7 @@ private int LookupNamespace(string prefix) } } } + return -1; } @@ -1604,7 +1645,9 @@ private int LookupNamespaceInCurrentScope(string prefix) { if (_useNsHashtable) { + Debug.Assert(_nsHashtable != null); int nsIndex; + if (_nsHashtable.TryGetValue(prefix, out nsIndex)) { if (nsIndex > _stack[_top].prevNsTop) @@ -1626,7 +1669,7 @@ private int LookupNamespaceInCurrentScope(string prefix) return -1; } - private string FindPrefix(string ns) + private string? FindPrefix(string ns) { for (int i = _nsTop; i >= 0; i--) { @@ -1638,6 +1681,7 @@ private string FindPrefix(string ns) } } } + return null; } @@ -1745,7 +1789,7 @@ private void HandleSpecialAttribute() } - private void VerifyPrefixXml(string prefix, string ns) + private void VerifyPrefixXml(string? prefix, string ns) { if (prefix != null && prefix.Length == 3) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs index 3781b016706e5..dddd35f6ceeda 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs @@ -26,44 +26,44 @@ internal partial class XmlUtf8RawTextWriter : XmlRawWriter private readonly bool _useAsync; // main buffer - protected byte[] bufBytes; + protected byte[] _bufBytes; // output stream - protected Stream stream; + protected Stream _stream; // encoding of the stream or text writer - protected Encoding encoding; + protected Encoding _encoding; // char type tables - protected XmlCharType xmlCharType = XmlCharType.Instance; + protected XmlCharType _xmlCharType = XmlCharType.Instance; // buffer positions - protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to - // close an empty element or in CDATA section detection of double ]; bufBytes[0] will always be 0 - protected int textPos = 1; // text end position; don't indent first element, pi, or comment - protected int contentPos; // element content end position - protected int cdataPos; // cdata end position - protected int attrEndPos; // end of the last attribute - protected int bufLen = BUFSIZE; + protected int _bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + // close an empty element or in CDATA section detection of double ]; bufBytes[0] will always be 0 + protected int _textPos = 1; // text end position; don't indent first element, pi, or comment + protected int _contentPos; // element content end position + protected int _cdataPos; // cdata end position + protected int _attrEndPos; // end of the last attribute + protected int _bufLen = BUFSIZE; // flags - protected bool writeToNull; - protected bool hadDoubleBracket; - protected bool inAttributeValue; + protected bool _writeToNull; + protected bool _hadDoubleBracket; + protected bool _inAttributeValue; // writer settings - protected NewLineHandling newLineHandling; - protected bool closeOutput; - protected bool omitXmlDeclaration; - protected string newLineChars; - protected bool checkCharacters; + protected NewLineHandling _newLineHandling; + protected bool _closeOutput; + protected bool _omitXmlDeclaration; + protected string _newLineChars; + protected bool _checkCharacters; - protected XmlStandalone standalone; - protected XmlOutputMethod outputMethod; + protected XmlStandalone _standalone; + protected XmlOutputMethod _outputMethod; - protected bool autoXmlDeclaration; - protected bool mergeCDataSections; + protected bool _autoXmlDeclaration; + protected bool _mergeCDataSections; // // Constants @@ -81,19 +81,19 @@ protected XmlUtf8RawTextWriter(XmlWriterSettings settings) _useAsync = settings.Async; // copy settings - newLineHandling = settings.NewLineHandling; - omitXmlDeclaration = settings.OmitXmlDeclaration; - newLineChars = settings.NewLineChars; - checkCharacters = settings.CheckCharacters; - closeOutput = settings.CloseOutput; + _newLineHandling = settings.NewLineHandling; + _omitXmlDeclaration = settings.OmitXmlDeclaration; + _newLineChars = settings.NewLineChars; + _checkCharacters = settings.CheckCharacters; + _closeOutput = settings.CloseOutput; - standalone = settings.Standalone; - outputMethod = settings.OutputMethod; - mergeCDataSections = settings.MergeCDataSections; + _standalone = settings.Standalone; + _outputMethod = settings.OutputMethod; + _mergeCDataSections = settings.MergeCDataSections; - if (checkCharacters && newLineHandling == NewLineHandling.Replace) + if (_checkCharacters && _newLineHandling == NewLineHandling.Replace) { - ValidateContentChars(newLineChars, "NewLineChars", false); + ValidateContentChars(_newLineChars, "NewLineChars", false); } } @@ -102,33 +102,33 @@ public XmlUtf8RawTextWriter(Stream stream, XmlWriterSettings settings) : this(se { Debug.Assert(stream != null && settings != null); - this.stream = stream; - this.encoding = settings.Encoding; + this._stream = stream; + this._encoding = settings.Encoding; // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup if (settings.Async) { - bufLen = ASYNCBUFSIZE; + _bufLen = ASYNCBUFSIZE; } - bufBytes = new byte[bufLen + OVERFLOW]; + _bufBytes = new byte[_bufLen + OVERFLOW]; // Output UTF-8 byte order mark if Encoding object wants it if (!stream.CanSeek || stream.Position == 0) { - ReadOnlySpan bom = encoding.Preamble; + ReadOnlySpan bom = _encoding.Preamble; if (bom.Length != 0) { - bom.CopyTo(new Span(bufBytes).Slice(1)); - bufPos += bom.Length; - textPos += bom.Length; + bom.CopyTo(new Span(_bufBytes).Slice(1)); + _bufPos += bom.Length; + _textPos += bom.Length; } } // Write the xml declaration if (settings.AutoXmlDeclaration) { - WriteXmlDeclaration(standalone); - autoXmlDeclaration = true; + WriteXmlDeclaration(_standalone); + _autoXmlDeclaration = true; } } @@ -142,17 +142,17 @@ public override XmlWriterSettings Settings { XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = encoding; - settings.OmitXmlDeclaration = omitXmlDeclaration; - settings.NewLineHandling = newLineHandling; - settings.NewLineChars = newLineChars; - settings.CloseOutput = closeOutput; + settings.Encoding = _encoding; + settings.OmitXmlDeclaration = _omitXmlDeclaration; + settings.NewLineHandling = _newLineHandling; + settings.NewLineChars = _newLineChars; + settings.CloseOutput = _closeOutput; settings.ConformanceLevel = ConformanceLevel.Auto; - settings.CheckCharacters = checkCharacters; + settings.CheckCharacters = _checkCharacters; - settings.AutoXmlDeclaration = autoXmlDeclaration; - settings.Standalone = standalone; - settings.OutputMethod = outputMethod; + settings.AutoXmlDeclaration = _autoXmlDeclaration; + settings.Standalone = _standalone; + settings.OutputMethod = _outputMethod; settings.ReadOnly = true; return settings; @@ -163,7 +163,7 @@ public override XmlWriterSettings Settings internal override void WriteXmlDeclaration(XmlStandalone standalone) { // Output xml declaration only if user allows it and it was not already output - if (!omitXmlDeclaration && !autoXmlDeclaration) + if (!_omitXmlDeclaration && !_autoXmlDeclaration) { RawText("'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize the beginning of an element start tag: " 0); Debug.Assert(prefix != null); - bufBytes[bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'<'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - bufBytes[bufPos++] = (byte)':'; + _bufBytes[_bufPos++] = (byte)':'; } RawText(localName); - attrEndPos = bufPos; + _attrEndPos = _bufPos; } // Serialize the end of an element start tag in preparation for content serialization: ">" internal override void StartElementContent() { - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'>'; // StartElementContent is always called; therefore, in order to allow shortcut syntax, we save the // position of the '>' character. If WriteEndElement is called and no other characters have been // output, then the '>' character can be overwritten with the shortcut syntax " />". - contentPos = bufPos; + _contentPos = _bufPos; } // Serialize an element end tag: "", if content was output. Otherwise, serialize @@ -272,27 +272,27 @@ internal override void WriteEndElement(string prefix, string localName, string n Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (contentPos != bufPos) + if (_contentPos != _bufPos) { // Content has been output, so can't use shortcut syntax - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'/'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'/'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - bufBytes[bufPos++] = (byte)':'; + _bufBytes[_bufPos++] = (byte)':'; } RawText(localName); - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'>'; } else { // Use shortcut syntax; overwrite the already output '>' character - bufPos--; - bufBytes[bufPos++] = (byte)' '; - bufBytes[bufPos++] = (byte)'/'; - bufBytes[bufPos++] = (byte)'>'; + _bufPos--; + _bufBytes[_bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)'/'; + _bufBytes[_bufPos++] = (byte)'>'; } } @@ -302,16 +302,16 @@ internal override void WriteFullEndElement(string prefix, string localName, stri Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'/'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'/'; if (prefix != null && prefix.Length != 0) { RawText(prefix); - bufBytes[bufPos++] = (byte)':'; + _bufBytes[_bufPos++] = (byte)':'; } RawText(localName); - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="' @@ -320,30 +320,30 @@ public override void WriteStartAttribute(string prefix, string localName, string Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (attrEndPos == bufPos) + if (_attrEndPos == _bufPos) { - bufBytes[bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)' '; } if (prefix != null && prefix.Length > 0) { RawText(prefix); - bufBytes[bufPos++] = (byte)':'; + _bufBytes[_bufPos++] = (byte)':'; } RawText(localName); - bufBytes[bufPos++] = (byte)'='; - bufBytes[bufPos++] = (byte)'"'; + _bufBytes[_bufPos++] = (byte)'='; + _bufBytes[_bufPos++] = (byte)'"'; - inAttributeValue = true; + _inAttributeValue = true; } // Serialize the end of an attribute value using double quotes: '"' public override void WriteEndAttribute() { - bufBytes[bufPos++] = (byte)'"'; - inAttributeValue = false; - attrEndPos = bufPos; + _bufBytes[_bufPos++] = (byte)'"'; + _inAttributeValue = false; + _attrEndPos = _bufPos; } internal override void WriteNamespaceDeclaration(string prefix, string namespaceName) @@ -375,19 +375,19 @@ internal override void WriteStartNamespaceDeclaration(string prefix) { RawText(" xmlns:"); RawText(prefix); - bufBytes[bufPos++] = (byte)'='; - bufBytes[bufPos++] = (byte)'"'; + _bufBytes[_bufPos++] = (byte)'='; + _bufBytes[_bufPos++] = (byte)'"'; } - inAttributeValue = true; + _inAttributeValue = true; } internal override void WriteEndNamespaceDeclaration() { - inAttributeValue = false; + _inAttributeValue = false; - bufBytes[bufPos++] = (byte)'"'; - attrEndPos = bufPos; + _bufBytes[_bufPos++] = (byte)'"'; + _attrEndPos = _bufPos; } // Serialize a CData section. If the "]]>" pattern is found within @@ -396,34 +396,34 @@ public override void WriteCData(string text) { Debug.Assert(text != null); - if (mergeCDataSections && bufPos == cdataPos) + if (_mergeCDataSections && _bufPos == _cdataPos) { // Merge adjacent cdata sections - overwrite the "]]>" characters - Debug.Assert(bufPos >= 4); - bufPos -= 3; + Debug.Assert(_bufPos >= 4); + _bufPos -= 3; } else { // Start a new cdata section - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'!'; - bufBytes[bufPos++] = (byte)'['; - bufBytes[bufPos++] = (byte)'C'; - bufBytes[bufPos++] = (byte)'D'; - bufBytes[bufPos++] = (byte)'A'; - bufBytes[bufPos++] = (byte)'T'; - bufBytes[bufPos++] = (byte)'A'; - bufBytes[bufPos++] = (byte)'['; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'!'; + _bufBytes[_bufPos++] = (byte)'['; + _bufBytes[_bufPos++] = (byte)'C'; + _bufBytes[_bufPos++] = (byte)'D'; + _bufBytes[_bufPos++] = (byte)'A'; + _bufBytes[_bufPos++] = (byte)'T'; + _bufBytes[_bufPos++] = (byte)'A'; + _bufBytes[_bufPos++] = (byte)'['; } WriteCDataSection(text); - bufBytes[bufPos++] = (byte)']'; - bufBytes[bufPos++] = (byte)']'; - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)']'; + _bufBytes[_bufPos++] = (byte)']'; + _bufBytes[_bufPos++] = (byte)'>'; - textPos = bufPos; - cdataPos = bufPos; + _textPos = _bufPos; + _cdataPos = _bufPos; } // Serialize a comment. @@ -431,16 +431,16 @@ public override void WriteComment(string text) { Debug.Assert(text != null); - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'!'; - bufBytes[bufPos++] = (byte)'-'; - bufBytes[bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'!'; + _bufBytes[_bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'-'; WriteCommentOrPi(text, '-'); - bufBytes[bufPos++] = (byte)'-'; - bufBytes[bufPos++] = (byte)'-'; - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize a processing instruction. @@ -449,18 +449,18 @@ public override void WriteProcessingInstruction(string name, string text) Debug.Assert(name != null && name.Length > 0); Debug.Assert(text != null); - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'?'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'?'; RawText(name); if (text.Length > 0) { - bufBytes[bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)' '; WriteCommentOrPi(text, '?'); } - bufBytes[bufPos++] = (byte)'?'; - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'?'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize an entity reference. @@ -468,16 +468,16 @@ public override void WriteEntityRef(string name) { Debug.Assert(name != null && name.Length > 0); - bufBytes[bufPos++] = (byte)'&'; + _bufBytes[_bufPos++] = (byte)'&'; RawText(name); - bufBytes[bufPos++] = (byte)';'; + _bufBytes[_bufPos++] = (byte)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { FlushBuffer(); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a character entity reference. @@ -485,24 +485,24 @@ public override void WriteCharEntity(char ch) { string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); - if (checkCharacters && !xmlCharType.IsCharData(ch)) + if (_checkCharacters && !_xmlCharType.IsCharData(ch)) { // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char throw XmlConvert.CreateInvalidCharException(ch, '\0'); } - bufBytes[bufPos++] = (byte)'&'; - bufBytes[bufPos++] = (byte)'#'; - bufBytes[bufPos++] = (byte)'x'; + _bufBytes[_bufPos++] = (byte)'&'; + _bufBytes[_bufPos++] = (byte)'#'; + _bufBytes[_bufPos++] = (byte)'x'; RawText(strVal); - bufBytes[bufPos++] = (byte)';'; + _bufBytes[_bufPos++] = (byte)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { FlushBuffer(); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a whitespace node. @@ -514,7 +514,7 @@ public override unsafe void WriteWhitespace(string ws) fixed (char* pSrc = ws) { char* pSrcEnd = pSrc + ws.Length; - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -534,7 +534,7 @@ public override unsafe void WriteString(string text) fixed (char* pSrc = text) { char* pSrcEnd = pSrc + text.Length; - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrc, pSrcEnd); } @@ -550,12 +550,12 @@ public override void WriteSurrogateCharEntity(char lowChar, char highChar) { int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar); - bufBytes[bufPos++] = (byte)'&'; - bufBytes[bufPos++] = (byte)'#'; - bufBytes[bufPos++] = (byte)'x'; + _bufBytes[_bufPos++] = (byte)'&'; + _bufBytes[_bufPos++] = (byte)'#'; + _bufBytes[_bufPos++] = (byte)'x'; RawText(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)); - bufBytes[bufPos++] = (byte)';'; - textPos = bufPos; + _bufBytes[_bufPos++] = (byte)';'; + _textPos = _bufPos; } // Serialize either attribute or element text using XML rules. @@ -569,7 +569,7 @@ public override unsafe void WriteChars(char[] buffer, int index, int count) fixed (char* pSrcBegin = &buffer[index]) { - if (inAttributeValue) + if (_inAttributeValue) { WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count); } @@ -594,7 +594,7 @@ public override unsafe void WriteRaw(char[] buffer, int index, int count) WriteRawWithCharChecking(pSrcBegin, pSrcBegin + count); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize raw data. @@ -608,7 +608,7 @@ public override unsafe void WriteRaw(string data) WriteRawWithCharChecking(pSrcBegin, pSrcBegin + data.Length); } - textPos = bufPos; + _textPos = _bufPos; } // Flush all bytes in the buffer to output and close the output stream or writer. @@ -622,26 +622,26 @@ public override void Close() finally { // Future calls to Close or Flush shouldn't write to Stream or Writer - writeToNull = true; + _writeToNull = true; - if (stream != null) + if (_stream != null) { try { - stream.Flush(); + _stream.Flush(); } finally { try { - if (closeOutput) + if (_closeOutput) { - stream.Dispose(); + _stream.Dispose(); } } finally { - stream = null; + _stream = null; } } } @@ -653,9 +653,9 @@ public override void Flush() { FlushBuffer(); FlushEncoder(); - if (stream != null) + if (_stream != null) { - stream.Flush(); + _stream.Flush(); } } @@ -668,40 +668,40 @@ protected virtual void FlushBuffer() try { // Output all characters (except for previous characters stored at beginning of buffer) - if (!writeToNull) + if (!_writeToNull) { - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { - Debug.Assert(stream != null); - stream.Write(bufBytes, 1, bufPos - 1); + Debug.Assert(_stream != null); + _stream.Write(_bufBytes, 1, _bufPos - 1); } } } catch { // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream - writeToNull = true; + _writeToNull = true; throw; } finally { // Move last buffer character to the beginning of the buffer (so that previous character can always be determined) - bufBytes[0] = bufBytes[bufPos - 1]; - if (IsSurrogateByte(bufBytes[0])) + _bufBytes[0] = _bufBytes[_bufPos - 1]; + if (IsSurrogateByte(_bufBytes[0])) { // Last character was the first byte in a surrogate encoding, so move last three // bytes of encoding to the beginning of the buffer. - bufBytes[1] = bufBytes[bufPos]; - bufBytes[2] = bufBytes[bufPos + 1]; - bufBytes[3] = bufBytes[bufPos + 2]; + _bufBytes[1] = _bufBytes[_bufPos]; + _bufBytes[2] = _bufBytes[_bufPos + 1]; + _bufBytes[3] = _bufBytes[_bufPos + 2]; } // Reset buffer position - textPos = (textPos == bufPos) ? 1 : 0; - attrEndPos = (attrEndPos == bufPos) ? 1 : 0; - contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible - cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible - bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + _textPos = (_textPos == _bufPos) ? 1 : 0; + _attrEndPos = (_attrEndPos == _bufPos) ? 1 : 0; + _contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible + _cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible + _bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to // close an empty element or in CDATA section detection of double ]; bufBytes[0] will always be 0 } } @@ -716,20 +716,20 @@ private void FlushEncoder() // are entitized. protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) { - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -746,7 +746,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -772,7 +772,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) pDst++; break; case (char)0x9: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (byte)ch; pDst++; @@ -784,7 +784,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) } break; case (char)0xD: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (byte)ch; pDst++; @@ -796,7 +796,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (byte)ch; pDst++; @@ -830,7 +830,7 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -838,20 +838,20 @@ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd) // are entitized. protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) { - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -868,7 +868,7 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -893,7 +893,7 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) pDst++; break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -904,7 +904,7 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) } break; case (char)0xD: - switch (newLineHandling) + switch (_newLineHandling) { case NewLineHandling.Replace: // Replace "\r\n", or "\r" with NewLineChars @@ -949,9 +949,9 @@ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); - textPos = bufPos; - contentPos = 0; + _bufPos = (int)(pDst - pDstBegin); + _textPos = _bufPos; + _contentPos = 0; } } @@ -967,18 +967,18 @@ protected unsafe void RawText(string s) protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd) { - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; char* pSrc = pSrcBegin; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } while (pDst < pDstEnd && ((ch = *pSrc) <= 0x7F)) @@ -998,7 +998,7 @@ protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1024,27 +1024,27 @@ protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd) } } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) { - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { char* pSrc = pSrcBegin; - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -1062,7 +1062,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1079,7 +1079,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1096,7 +1096,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1129,7 +1129,7 @@ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1137,7 +1137,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { FlushBuffer(); } @@ -1146,24 +1146,24 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) // write text fixed (char* pSrcBegin = text) - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { char* pSrc = pSrcBegin; char* pSrcEnd = pSrcBegin + text.Length; - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -1181,7 +1181,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1221,7 +1221,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1238,7 +1238,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1277,7 +1277,7 @@ protected unsafe void WriteCommentOrPi(string text, int stopChar) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1285,7 +1285,7 @@ protected unsafe void WriteCDataSection(string text) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { FlushBuffer(); } @@ -1296,24 +1296,24 @@ protected unsafe void WriteCDataSection(string text) fixed (char* pSrcBegin = text) - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { char* pSrc = pSrcBegin; char* pSrcEnd = pSrcBegin + text.Length; - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -1331,7 +1331,7 @@ protected unsafe void WriteCDataSection(string text) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); FlushBuffer(); pDst = pDstBegin + 1; continue; @@ -1341,7 +1341,7 @@ protected unsafe void WriteCDataSection(string text) switch (ch) { case '>': - if (hadDoubleBracket && pDst[-1] == (byte)']') + if (_hadDoubleBracket && pDst[-1] == (byte)']') { // pDst[-1] will always correct - there is a padding character at bufBytes[0] // The characters "]]>" were found within the CData text pDst = RawEndCData(pDst); @@ -1353,17 +1353,17 @@ protected unsafe void WriteCDataSection(string text) case ']': if (pDst[-1] == (byte)']') { // pDst[-1] will always correct - there is a padding character at bufBytes[0] - hadDoubleBracket = true; + _hadDoubleBracket = true; } else { - hadDoubleBracket = false; + _hadDoubleBracket = false; } *pDst = (byte)']'; pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1380,7 +1380,7 @@ protected unsafe void WriteCDataSection(string text) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { pDst = WriteNewLine(pDst); } @@ -1421,7 +1421,7 @@ protected unsafe void WriteCDataSection(string text) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } } @@ -1467,10 +1467,10 @@ private static bool IsSurrogateByte(byte b) private unsafe byte* InvalidXmlChar(int ch, byte* pDst, bool entitize) { - Debug.Assert(!xmlCharType.IsWhiteSpace((char)ch)); - Debug.Assert(!xmlCharType.IsAttributeValueChar((char)ch)); + Debug.Assert(!_xmlCharType.IsWhiteSpace((char)ch)); + Debug.Assert(!_xmlCharType.IsAttributeValueChar((char)ch)); - if (checkCharacters) + if (_checkCharacters) { // This method will never be called on surrogates, so it is ok to pass in '\0' to the CreateInvalidCharException throw XmlConvert.CreateInvalidCharException((char)ch, '\0'); @@ -1572,12 +1572,12 @@ internal static unsafe void CharToUTF8(ref char* pSrc, char* pSrcEnd, ref byte* // Write NewLineChars to the specified buffer position and return an updated position. protected unsafe byte* WriteNewLine(byte* pDst) { - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); // Let RawText do the real work - RawText(newLineChars); - return pDstBegin + bufPos; + RawText(_newLineChars); + return pDstBegin + _bufPos; } } @@ -1715,7 +1715,7 @@ protected void ValidateContentChars(string chars, string propertyName, bool allo { if (allowOnlyWhitespace) { - if (!xmlCharType.IsOnlyWhitespace(chars)) + if (!_xmlCharType.IsOnlyWhitespace(chars)) { throw new ArgumentException(SR.Format(SR.Xml_IndentCharsNotWhitespace, propertyName)); } @@ -1725,7 +1725,7 @@ protected void ValidateContentChars(string chars, string propertyName, bool allo string error = null; for (int i = 0; i < chars.Length; i++) { - if (!xmlCharType.IsTextChar(chars[i])) + if (!_xmlCharType.IsTextChar(chars[i])) { switch (chars[i]) { @@ -1775,14 +1775,14 @@ internal partial class XmlUtf8RawTextWriterIndent : XmlUtf8RawTextWriter // // Fields // - protected int indentLevel; - protected bool newLineOnAttributes; - protected string indentChars; + protected int _indentLevel; + protected bool _newLineOnAttributes; + protected string _indentChars; - protected bool mixedContent; + protected bool _mixedContent; private BitStack _mixedContentStack; - protected ConformanceLevel conformanceLevel = ConformanceLevel.Auto; + protected ConformanceLevel _conformanceLevel = ConformanceLevel.Auto; // // Constructors @@ -1804,8 +1804,8 @@ public override XmlWriterSettings Settings settings.ReadOnly = false; settings.Indent = true; - settings.IndentChars = indentChars; - settings.NewLineOnAttributes = newLineOnAttributes; + settings.IndentChars = _indentChars; + settings.NewLineOnAttributes = _newLineOnAttributes; settings.ReadOnly = true; return settings; @@ -1815,7 +1815,7 @@ public override XmlWriterSettings Settings public override void WriteDocType(string name, string pubid, string sysid, string subset) { // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -1827,12 +1827,12 @@ public override void WriteStartElement(string prefix, string localName, string n Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } - indentLevel++; - _mixedContentStack.PushBit(mixedContent); + _indentLevel++; + _mixedContentStack.PushBit(_mixedContent); base.WriteStartElement(prefix, localName, ns); } @@ -1840,16 +1840,16 @@ public override void WriteStartElement(string prefix, string localName, string n internal override void StartElementContent() { // If this is the root element and we're writing a document - // do not inherit the mixedContent flag into the root element. + // do not inherit the _mixedContent flag into the root element. // This is to allow for whitespace nodes on root level // without disabling indentation for the whole document. - if (indentLevel == 1 && conformanceLevel == ConformanceLevel.Document) + if (_indentLevel == 1 && _conformanceLevel == ConformanceLevel.Document) { - mixedContent = false; + _mixedContent = false; } else { - mixedContent = _mixedContentStack.PeekBit(); + _mixedContent = _mixedContentStack.PeekBit(); } base.StartElementContent(); } @@ -1857,22 +1857,22 @@ internal override void StartElementContent() internal override void OnRootElement(ConformanceLevel currentConformanceLevel) { // Just remember the current conformance level - conformanceLevel = currentConformanceLevel; + _conformanceLevel = currentConformanceLevel; } internal override void WriteEndElement(string prefix, string localName, string ns) { // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { WriteIndent(); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); base.WriteEndElement(prefix, localName, ns); } @@ -1880,16 +1880,16 @@ internal override void WriteEndElement(string prefix, string localName, string n internal override void WriteFullEndElement(string prefix, string localName, string ns) { // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { WriteIndent(); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); base.WriteFullEndElement(prefix, localName, ns); } @@ -1898,7 +1898,7 @@ internal override void WriteFullEndElement(string prefix, string localName, stri public override void WriteStartAttribute(string prefix, string localName, string ns) { // Add indentation - if (newLineOnAttributes) + if (_newLineOnAttributes) { WriteIndent(); } @@ -1908,13 +1908,13 @@ public override void WriteStartAttribute(string prefix, string localName, string public override void WriteCData(string text) { - mixedContent = true; + _mixedContent = true; base.WriteCData(text); } public override void WriteComment(string text) { - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -1924,7 +1924,7 @@ public override void WriteComment(string text) public override void WriteProcessingInstruction(string target, string text) { - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { WriteIndent(); } @@ -1934,55 +1934,55 @@ public override void WriteProcessingInstruction(string target, string text) public override void WriteEntityRef(string name) { - mixedContent = true; + _mixedContent = true; base.WriteEntityRef(name); } public override void WriteCharEntity(char ch) { - mixedContent = true; + _mixedContent = true; base.WriteCharEntity(ch); } public override void WriteSurrogateCharEntity(char lowChar, char highChar) { - mixedContent = true; + _mixedContent = true; base.WriteSurrogateCharEntity(lowChar, highChar); } public override void WriteWhitespace(string ws) { - mixedContent = true; + _mixedContent = true; base.WriteWhitespace(ws); } public override void WriteString(string text) { - mixedContent = true; + _mixedContent = true; base.WriteString(text); } public override void WriteChars(char[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteChars(buffer, index, count); } public override void WriteRaw(char[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteRaw(buffer, index, count); } public override void WriteRaw(string data) { - mixedContent = true; + _mixedContent = true; base.WriteRaw(data); } public override void WriteBase64(byte[] buffer, int index, int count) { - mixedContent = true; + _mixedContent = true; base.WriteBase64(buffer, index, count); } @@ -1991,25 +1991,25 @@ public override void WriteBase64(byte[] buffer, int index, int count) // private void Init(XmlWriterSettings settings) { - indentLevel = 0; - indentChars = settings.IndentChars; - newLineOnAttributes = settings.NewLineOnAttributes; + _indentLevel = 0; + _indentChars = settings.IndentChars; + _newLineOnAttributes = settings.NewLineOnAttributes; _mixedContentStack = new BitStack(); // check indent characters that they are valid XML characters - if (base.checkCharacters) + if (base._checkCharacters) { - if (newLineOnAttributes) + if (_newLineOnAttributes) { - base.ValidateContentChars(indentChars, "IndentChars", true); - base.ValidateContentChars(newLineChars, "NewLineChars", true); + base.ValidateContentChars(_indentChars, "IndentChars", true); + base.ValidateContentChars(_newLineChars, "NewLineChars", true); } else { - base.ValidateContentChars(indentChars, "IndentChars", false); - if (base.newLineHandling != NewLineHandling.Replace) + base.ValidateContentChars(_indentChars, "IndentChars", false); + if (base._newLineHandling != NewLineHandling.Replace) { - base.ValidateContentChars(newLineChars, "NewLineChars", false); + base.ValidateContentChars(_newLineChars, "NewLineChars", false); } } } @@ -2018,10 +2018,10 @@ private void Init(XmlWriterSettings settings) // Add indentation to output. Write newline and then repeat IndentChars for each indent level. private void WriteIndent() { - RawText(base.newLineChars); - for (int i = indentLevel; i > 0; i--) + RawText(base._newLineChars); + for (int i = _indentLevel; i > 0; i--) { - RawText(indentChars); + RawText(_indentChars); } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs index d4916eb83445a..358c774d59d0a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs @@ -35,7 +35,7 @@ internal override async Task WriteXmlDeclarationAsync(XmlStandalone standalone) { CheckAsyncCall(); // Output xml declaration only if user allows it and it was not already output - if (!omitXmlDeclaration && !autoXmlDeclaration) + if (!_omitXmlDeclaration && !_autoXmlDeclaration) { await RawTextAsync("'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize the beginning of an element start tag: "", if content was output. Otherwise, serialize @@ -180,11 +180,11 @@ internal override Task WriteEndElementAsync(string prefix, string localName, str Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (contentPos != bufPos) + if (_contentPos != _bufPos) { // Content has been output, so can't use shortcut syntax - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'/'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'/'; if (prefix != null && prefix.Length != 0) { @@ -198,10 +198,10 @@ internal override Task WriteEndElementAsync(string prefix, string localName, str else { // Use shortcut syntax; overwrite the already output '>' character - bufPos--; - bufBytes[bufPos++] = (byte)' '; - bufBytes[bufPos++] = (byte)'/'; - bufBytes[bufPos++] = (byte)'>'; + _bufPos--; + _bufBytes[_bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)'/'; + _bufBytes[_bufPos++] = (byte)'>'; } return Task.CompletedTask; } @@ -213,8 +213,8 @@ internal override Task WriteFullEndElementAsync(string prefix, string localName, Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'/'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'/'; if (prefix != null && prefix.Length != 0) { @@ -233,9 +233,9 @@ protected internal override Task WriteStartAttributeAsync(string prefix, string Debug.Assert(localName != null && localName.Length > 0); Debug.Assert(prefix != null); - if (attrEndPos == bufPos) + if (_attrEndPos == _bufPos) { - bufBytes[bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)' '; } Task task; if (prefix != null && prefix.Length > 0) @@ -251,9 +251,9 @@ protected internal override Task WriteStartAttributeAsync(string prefix, string private void WriteStartAttribute_SetInAttribute() { - bufBytes[bufPos++] = (byte)'='; - bufBytes[bufPos++] = (byte)'"'; - inAttributeValue = true; + _bufBytes[_bufPos++] = (byte)'='; + _bufBytes[_bufPos++] = (byte)'"'; + _inAttributeValue = true; } // Serialize the end of an attribute value using double quotes: '"' @@ -261,9 +261,9 @@ protected internal override Task WriteEndAttributeAsync() { CheckAsyncCall(); - bufBytes[bufPos++] = (byte)'"'; - inAttributeValue = false; - attrEndPos = bufPos; + _bufBytes[_bufPos++] = (byte)'"'; + _inAttributeValue = false; + _attrEndPos = _bufPos; return Task.CompletedTask; } @@ -291,21 +291,21 @@ internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) { await RawTextAsync(" xmlns:").ConfigureAwait(false); await RawTextAsync(prefix).ConfigureAwait(false); - bufBytes[bufPos++] = (byte)'='; - bufBytes[bufPos++] = (byte)'"'; + _bufBytes[_bufPos++] = (byte)'='; + _bufBytes[_bufPos++] = (byte)'"'; } - inAttributeValue = true; + _inAttributeValue = true; } internal override Task WriteEndNamespaceDeclarationAsync() { CheckAsyncCall(); - inAttributeValue = false; + _inAttributeValue = false; - bufBytes[bufPos++] = (byte)'"'; - attrEndPos = bufPos; + _bufBytes[_bufPos++] = (byte)'"'; + _attrEndPos = _bufPos; return Task.CompletedTask; } @@ -317,34 +317,34 @@ public override async Task WriteCDataAsync(string text) CheckAsyncCall(); Debug.Assert(text != null); - if (mergeCDataSections && bufPos == cdataPos) + if (_mergeCDataSections && _bufPos == _cdataPos) { // Merge adjacent cdata sections - overwrite the "]]>" characters - Debug.Assert(bufPos >= 4); - bufPos -= 3; + Debug.Assert(_bufPos >= 4); + _bufPos -= 3; } else { // Start a new cdata section - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'!'; - bufBytes[bufPos++] = (byte)'['; - bufBytes[bufPos++] = (byte)'C'; - bufBytes[bufPos++] = (byte)'D'; - bufBytes[bufPos++] = (byte)'A'; - bufBytes[bufPos++] = (byte)'T'; - bufBytes[bufPos++] = (byte)'A'; - bufBytes[bufPos++] = (byte)'['; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'!'; + _bufBytes[_bufPos++] = (byte)'['; + _bufBytes[_bufPos++] = (byte)'C'; + _bufBytes[_bufPos++] = (byte)'D'; + _bufBytes[_bufPos++] = (byte)'A'; + _bufBytes[_bufPos++] = (byte)'T'; + _bufBytes[_bufPos++] = (byte)'A'; + _bufBytes[_bufPos++] = (byte)'['; } await WriteCDataSectionAsync(text).ConfigureAwait(false); - bufBytes[bufPos++] = (byte)']'; - bufBytes[bufPos++] = (byte)']'; - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)']'; + _bufBytes[_bufPos++] = (byte)']'; + _bufBytes[_bufPos++] = (byte)'>'; - textPos = bufPos; - cdataPos = bufPos; + _textPos = _bufPos; + _cdataPos = _bufPos; } // Serialize a comment. @@ -353,16 +353,16 @@ public override async Task WriteCommentAsync(string text) CheckAsyncCall(); Debug.Assert(text != null); - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'!'; - bufBytes[bufPos++] = (byte)'-'; - bufBytes[bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'!'; + _bufBytes[_bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'-'; await WriteCommentOrPiAsync(text, '-').ConfigureAwait(false); - bufBytes[bufPos++] = (byte)'-'; - bufBytes[bufPos++] = (byte)'-'; - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'-'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize a processing instruction. @@ -372,18 +372,18 @@ public override async Task WriteProcessingInstructionAsync(string name, string t Debug.Assert(name != null && name.Length > 0); Debug.Assert(text != null); - bufBytes[bufPos++] = (byte)'<'; - bufBytes[bufPos++] = (byte)'?'; + _bufBytes[_bufPos++] = (byte)'<'; + _bufBytes[_bufPos++] = (byte)'?'; await RawTextAsync(name).ConfigureAwait(false); if (text.Length > 0) { - bufBytes[bufPos++] = (byte)' '; + _bufBytes[_bufPos++] = (byte)' '; await WriteCommentOrPiAsync(text, '?').ConfigureAwait(false); } - bufBytes[bufPos++] = (byte)'?'; - bufBytes[bufPos++] = (byte)'>'; + _bufBytes[_bufPos++] = (byte)'?'; + _bufBytes[_bufPos++] = (byte)'>'; } // Serialize an entity reference. @@ -392,16 +392,16 @@ public override async Task WriteEntityRefAsync(string name) CheckAsyncCall(); Debug.Assert(name != null && name.Length > 0); - bufBytes[bufPos++] = (byte)'&'; + _bufBytes[_bufPos++] = (byte)'&'; await RawTextAsync(name).ConfigureAwait(false); - bufBytes[bufPos++] = (byte)';'; + _bufBytes[_bufPos++] = (byte)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a character entity reference. @@ -410,24 +410,24 @@ public override async Task WriteCharEntityAsync(char ch) CheckAsyncCall(); string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo); - if (checkCharacters && !xmlCharType.IsCharData(ch)) + if (_checkCharacters && !_xmlCharType.IsCharData(ch)) { // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char throw XmlConvert.CreateInvalidCharException(ch, '\0'); } - bufBytes[bufPos++] = (byte)'&'; - bufBytes[bufPos++] = (byte)'#'; - bufBytes[bufPos++] = (byte)'x'; + _bufBytes[_bufPos++] = (byte)'&'; + _bufBytes[_bufPos++] = (byte)'#'; + _bufBytes[_bufPos++] = (byte)'x'; await RawTextAsync(strVal).ConfigureAwait(false); - bufBytes[bufPos++] = (byte)';'; + _bufBytes[_bufPos++] = (byte)';'; - if (bufPos > bufLen) + if (_bufPos > _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } - textPos = bufPos; + _textPos = _bufPos; } // Serialize a whitespace node. @@ -437,7 +437,7 @@ public override Task WriteWhitespaceAsync(string ws) CheckAsyncCall(); Debug.Assert(ws != null); - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(ws); } @@ -454,7 +454,7 @@ public override Task WriteStringAsync(string text) CheckAsyncCall(); Debug.Assert(text != null); - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(text); } @@ -471,12 +471,12 @@ public override async Task WriteSurrogateCharEntityAsync(char lowChar, char high int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar); - bufBytes[bufPos++] = (byte)'&'; - bufBytes[bufPos++] = (byte)'#'; - bufBytes[bufPos++] = (byte)'x'; + _bufBytes[_bufPos++] = (byte)'&'; + _bufBytes[_bufPos++] = (byte)'#'; + _bufBytes[_bufPos++] = (byte)'x'; await RawTextAsync(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)).ConfigureAwait(false); - bufBytes[bufPos++] = (byte)';'; - textPos = bufPos; + _bufBytes[_bufPos++] = (byte)';'; + _textPos = _bufPos; } // Serialize either attribute or element text using XML rules. @@ -489,7 +489,7 @@ public override Task WriteCharsAsync(char[] buffer, int index, int count) Debug.Assert(index >= 0); Debug.Assert(count >= 0 && index + count <= buffer.Length); - if (inAttributeValue) + if (_inAttributeValue) { return WriteAttributeTextBlockAsync(buffer, index, count); } @@ -511,7 +511,7 @@ public override async Task WriteRawAsync(char[] buffer, int index, int count) await WriteRawWithCharCheckingAsync(buffer, index, count).ConfigureAwait(false); - textPos = bufPos; + _textPos = _bufPos; } // Serialize raw data. @@ -523,7 +523,7 @@ public override async Task WriteRawAsync(string data) await WriteRawWithCharCheckingAsync(data).ConfigureAwait(false); - textPos = bufPos; + _textPos = _bufPos; } // Flush all characters in the buffer to output and call Flush() on the output object. @@ -532,9 +532,9 @@ public override async Task FlushAsync() CheckAsyncCall(); await FlushBufferAsync().ConfigureAwait(false); - if (stream != null) + if (_stream != null) { - await stream.FlushAsync().ConfigureAwait(false); + await _stream.FlushAsync().ConfigureAwait(false); } } @@ -547,41 +547,41 @@ protected virtual async Task FlushBufferAsync() try { // Output all characters (except for previous characters stored at beginning of buffer) - if (!writeToNull) + if (!_writeToNull) { - if (bufPos - 1 > 0) + if (_bufPos - 1 > 0) { - Debug.Assert(stream != null); - await stream.WriteAsync(bufBytes, 1, bufPos - 1).ConfigureAwait(false); + Debug.Assert(_stream != null); + await _stream.WriteAsync(_bufBytes.AsMemory(1, _bufPos - 1)).ConfigureAwait(false); } } } catch { // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream - writeToNull = true; + _writeToNull = true; throw; } finally { // Move last buffer character to the beginning of the buffer (so that previous character can always be determined) - bufBytes[0] = bufBytes[bufPos - 1]; + _bufBytes[0] = _bufBytes[_bufPos - 1]; - if (IsSurrogateByte(bufBytes[0])) + if (IsSurrogateByte(_bufBytes[0])) { // Last character was the first byte in a surrogate encoding, so move last three // bytes of encoding to the beginning of the buffer. - bufBytes[1] = bufBytes[bufPos]; - bufBytes[2] = bufBytes[bufPos + 1]; - bufBytes[3] = bufBytes[bufPos + 2]; + _bufBytes[1] = _bufBytes[_bufPos]; + _bufBytes[2] = _bufBytes[_bufPos + 1]; + _bufBytes[3] = _bufBytes[_bufPos + 2]; } // Reset buffer position - textPos = (textPos == bufPos) ? 1 : 0; - attrEndPos = (attrEndPos == bufPos) ? 1 : 0; - contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible - cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible - bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to + _textPos = (_textPos == _bufPos) ? 1 : 0; + _attrEndPos = (_attrEndPos == _bufPos) ? 1 : 0; + _contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible + _cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible + _bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0 } } @@ -592,20 +592,20 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) { char* pRaw = pSrc; - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -622,7 +622,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -646,7 +646,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) pDst++; break; case (char)0x9: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (byte)ch; pDst++; @@ -658,7 +658,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) } break; case (char)0xD: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (byte)ch; pDst++; @@ -670,7 +670,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) } break; case (char)0xA: - if (newLineHandling == NewLineHandling.None) + if (_newLineHandling == NewLineHandling.None) { *pDst = (byte)ch; pDst++; @@ -704,7 +704,7 @@ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd) } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -795,20 +795,20 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out needWriteNewLine = false; char* pRaw = pSrc; - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -825,7 +825,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -848,9 +848,9 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out pDst++; break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -861,7 +861,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out } break; case (char)0xD: - switch (newLineHandling) + switch (_newLineHandling) { case NewLineHandling.Replace: // Replace "\r\n", or "\r" with NewLineChars @@ -870,7 +870,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); @@ -907,9 +907,9 @@ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out } pSrc++; } - bufPos = (int)(pDst - pDstBegin); - textPos = bufPos; - contentPos = 0; + _bufPos = (int)(pDst - pDstBegin); + _textPos = _bufPos; + _contentPos = 0; } return -1; @@ -920,7 +920,7 @@ protected unsafe int WriteElementTextBlockNoFlush(char[] chars, int index, int c needWriteNewLine = false; if (count == 0) { - contentPos = 0; + _contentPos = 0; return -1; } fixed (char* pSrc = &chars[index]) @@ -936,7 +936,7 @@ protected unsafe int WriteElementTextBlockNoFlush(string text, int index, int co needWriteNewLine = false; if (count == 0) { - contentPos = 0; + _contentPos = 0; return -1; } fixed (char* pSrc = text) @@ -961,7 +961,7 @@ protected async Task WriteElementTextBlockAsync(char[] chars, int index, int cou if (needWriteNewLine) { //hit WriteNewLine - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1001,7 +1001,7 @@ private async Task _WriteElementTextBlockAsync(bool newLine, string text, int cu if (newLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1018,7 +1018,7 @@ private async Task _WriteElementTextBlockAsync(bool newLine, string text, int cu if (needWriteNewLine) { //hit WriteNewLine - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1033,18 +1033,18 @@ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd) { char* pRaw = pSrcBegin; - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; char* pSrc = pSrcBegin; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } while (pDst < pDstEnd && ((ch = *pSrc) <= 0x7F)) @@ -1064,7 +1064,7 @@ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd) // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1088,7 +1088,7 @@ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd) } } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1207,21 +1207,21 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc needWriteNewLine = false; char* pRaw = pSrcBegin; - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { char* pSrc = pSrcBegin; - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -1239,7 +1239,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1254,7 +1254,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1262,7 +1262,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1273,9 +1273,9 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1308,7 +1308,7 @@ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrc } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1357,7 +1357,7 @@ protected async Task WriteRawWithCharCheckingAsync(char[] chars, int index, int leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1381,7 +1381,7 @@ protected async Task WriteRawWithCharCheckingAsync(string text) leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1403,7 +1403,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, { char* pSrcBegin = pSrcText + index; - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { char* pSrc = pSrcBegin; @@ -1411,18 +1411,18 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, char* pSrcEnd = pSrcBegin + count; - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -1440,7 +1440,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1478,7 +1478,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1486,7 +1486,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1497,9 +1497,9 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1538,7 +1538,7 @@ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1549,7 +1549,7 @@ protected async Task WriteCommentOrPiAsync(string text, int stopChar) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } @@ -1567,7 +1567,7 @@ protected async Task WriteCommentOrPiAsync(string text, int stopChar) leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1592,7 +1592,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, { char* pSrcBegin = pSrcText + index; - fixed (byte* pDstBegin = bufBytes) + fixed (byte* pDstBegin = _bufBytes) { char* pSrc = pSrcBegin; @@ -1600,18 +1600,18 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, char* pRaw = pSrc; - byte* pDst = pDstBegin + bufPos; + byte* pDst = pDstBegin + _bufPos; int ch = 0; while (true) { byte* pDstEnd = pDst + (pSrcEnd - pSrc); - if (pDstEnd > pDstBegin + bufLen) + if (pDstEnd > pDstBegin + _bufLen) { - pDstEnd = pDstBegin + bufLen; + pDstEnd = pDstBegin + _bufLen; } - while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) + while (pDst < pDstEnd && (_xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F)) { *pDst = (byte)ch; pDst++; @@ -1629,7 +1629,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, // end of buffer if (pDst >= pDstEnd) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); return (int)(pSrc - pRaw); } @@ -1637,7 +1637,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, switch (ch) { case '>': - if (hadDoubleBracket && pDst[-1] == (byte)']') + if (_hadDoubleBracket && pDst[-1] == (byte)']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0] // The characters "]]>" were found within the CData text pDst = RawEndCData(pDst); @@ -1649,17 +1649,17 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, case ']': if (pDst[-1] == (byte)']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0] - hadDoubleBracket = true; + _hadDoubleBracket = true; } else { - hadDoubleBracket = false; + _hadDoubleBracket = false; } *pDst = (byte)']'; pDst++; break; case (char)0xD: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { // Normalize "\r\n", or "\r" to NewLineChars if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n') @@ -1667,7 +1667,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1678,9 +1678,9 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, } break; case (char)0xA: - if (newLineHandling == NewLineHandling.Replace) + if (_newLineHandling == NewLineHandling.Replace) { - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); needWriteNewLine = true; return (int)(pSrc - pRaw); } @@ -1721,7 +1721,7 @@ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, } pSrc++; } - bufPos = (int)(pDst - pDstBegin); + _bufPos = (int)(pDst - pDstBegin); } return -1; @@ -1732,7 +1732,7 @@ protected async Task WriteCDataSectionAsync(string text) { if (text.Length == 0) { - if (bufPos >= bufLen) + if (_bufPos >= _bufLen) { await FlushBufferAsync().ConfigureAwait(false); } @@ -1750,7 +1750,7 @@ protected async Task WriteCDataSectionAsync(string text) leftCount -= writeLen; if (needWriteNewLine) { - await RawTextAsync(newLineChars).ConfigureAwait(false); + await RawTextAsync(_newLineChars).ConfigureAwait(false); curIndex++; leftCount--; } @@ -1769,7 +1769,7 @@ public override async Task WriteDocTypeAsync(string name, string pubid, string s { CheckAsyncCall(); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1782,12 +1782,12 @@ public override async Task WriteStartElementAsync(string prefix, string localNam Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null); // Add indentation - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } - indentLevel++; - _mixedContentStack.PushBit(mixedContent); + _indentLevel++; + _mixedContentStack.PushBit(_mixedContent); await base.WriteStartElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1796,16 +1796,16 @@ internal override async Task WriteEndElementAsync(string prefix, string localNam { CheckAsyncCall(); // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); await base.WriteEndElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1814,16 +1814,16 @@ internal override async Task WriteFullEndElementAsync(string prefix, string loca { CheckAsyncCall(); // Add indentation - indentLevel--; - if (!mixedContent && base.contentPos != base.bufPos) + _indentLevel--; + if (!_mixedContent && base._contentPos != base._bufPos) { // There was content, so try to indent - if (base.textPos != base.bufPos) + if (base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } } - mixedContent = _mixedContentStack.PopBit(); + _mixedContent = _mixedContentStack.PopBit(); await base.WriteFullEndElementAsync(prefix, localName, ns).ConfigureAwait(false); } @@ -1833,7 +1833,7 @@ protected internal override async Task WriteStartAttributeAsync(string prefix, s { CheckAsyncCall(); // Add indentation - if (newLineOnAttributes) + if (_newLineOnAttributes) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1844,14 +1844,14 @@ protected internal override async Task WriteStartAttributeAsync(string prefix, s public override Task WriteCDataAsync(string text) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCDataAsync(text); } public override async Task WriteCommentAsync(string text) { CheckAsyncCall(); - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1862,7 +1862,7 @@ public override async Task WriteCommentAsync(string text) public override async Task WriteProcessingInstructionAsync(string target, string text) { CheckAsyncCall(); - if (!mixedContent && base.textPos != base.bufPos) + if (!_mixedContent && base._textPos != base._bufPos) { await WriteIndentAsync().ConfigureAwait(false); } @@ -1873,63 +1873,63 @@ public override async Task WriteProcessingInstructionAsync(string target, string public override Task WriteEntityRefAsync(string name) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteEntityRefAsync(name); } public override Task WriteCharEntityAsync(char ch) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCharEntityAsync(ch); } public override Task WriteSurrogateCharEntityAsync(char lowChar, char highChar) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteSurrogateCharEntityAsync(lowChar, highChar); } public override Task WriteWhitespaceAsync(string ws) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteWhitespaceAsync(ws); } public override Task WriteStringAsync(string text) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteStringAsync(text); } public override Task WriteCharsAsync(char[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteCharsAsync(buffer, index, count); } public override Task WriteRawAsync(char[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteRawAsync(buffer, index, count); } public override Task WriteRawAsync(string data) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteRawAsync(data); } public override Task WriteBase64Async(byte[] buffer, int index, int count) { CheckAsyncCall(); - mixedContent = true; + _mixedContent = true; return base.WriteBase64Async(buffer, index, count); } @@ -1937,10 +1937,10 @@ public override Task WriteBase64Async(byte[] buffer, int index, int count) private async Task WriteIndentAsync() { CheckAsyncCall(); - await RawTextAsync(base.newLineChars).ConfigureAwait(false); - for (int i = indentLevel; i > 0; i--) + await RawTextAsync(base._newLineChars).ConfigureAwait(false); + for (int i = _indentLevel; i > 0; i--) { - await RawTextAsync(indentChars).ConfigureAwait(false); + await RawTextAsync(_indentChars).ConfigureAwait(false); } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWriter.cs index d412522dd279c..07960b08492d8 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWriter.cs @@ -74,7 +74,7 @@ public abstract partial class XmlWriter : IDisposable // Writes out the DOCTYPE declaration with the specified name and optional attributes. - public abstract void WriteDocType(string name, string? pubid, string? sysid, string subset); + public abstract void WriteDocType(string name, string? pubid, string? sysid, string? subset); // Writes out the specified start tag and associates it with the given namespace. public void WriteStartElement(string localName, string? ns) @@ -146,7 +146,7 @@ public void WriteStartAttribute(string localName) // Writes out a ; block containing the specified text. - public abstract void WriteCData(string text); + public abstract void WriteCData(string? text); // Writes out a comment ; containing the specified text. @@ -170,7 +170,7 @@ public void WriteStartAttribute(string localName) // Writes out the specified text content. - public abstract void WriteString(string text); + public abstract void WriteString(string? text); // Write out the given surrogate pair as an entity reference. @@ -221,7 +221,7 @@ public virtual XmlSpace XmlSpace } // Gets the current xml:lang scope. - public virtual string XmlLang + public virtual string? XmlLang { get { @@ -282,6 +282,7 @@ public virtual void WriteValue(string? value) { return; } + WriteString(value); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReader.cs index 7a6b5928b545f..2115a780f0dd9 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReader.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using System.Text; using System.Xml.Schema; @@ -11,6 +12,7 @@ using System.Collections; using System.Collections.Generic; using System.Runtime.Versioning; +using System.Diagnostics.CodeAnalysis; namespace System.Xml { @@ -18,9 +20,9 @@ namespace System.Xml internal class AttributePSVIInfo { - internal string localName; - internal string namespaceUri; - internal object typedAttributeValue; + internal string? localName; + internal string? namespaceUri; + internal object? typedAttributeValue; internal XmlSchemaInfo attributeSchemaInfo; internal AttributePSVIInfo() @@ -55,51 +57,52 @@ private enum ValidatingReaderState EOF = 9, Error = 10, } - //Validation + + // Validation private XmlReader _coreReader; - private readonly IXmlNamespaceResolver _coreReaderNSResolver; + private readonly IXmlNamespaceResolver? _coreReaderNSResolver; private readonly IXmlNamespaceResolver _thisNSResolver; - private XmlSchemaValidator _validator; - private readonly XmlResolver _xmlResolver; - private readonly ValidationEventHandler _validationEvent; + private XmlSchemaValidator _validator = null!; + private readonly XmlResolver? _xmlResolver; + private readonly ValidationEventHandler? _validationEvent; private ValidatingReaderState _validationState; private XmlValueGetter _valueGetter; // namespace management - private readonly XmlNamespaceManager _nsManager; + private readonly XmlNamespaceManager? _nsManager; private readonly bool _manageNamespaces; private readonly bool _processInlineSchema; private bool _replayCache; - //Current Node handling - private ValidatingReaderNodeData _cachedNode; //Used to cache current node when looking ahead or default attributes - private AttributePSVIInfo _attributePSVI; + // Current Node handling + private ValidatingReaderNodeData? _cachedNode; // Used to cache current node when looking ahead or default attributes + private AttributePSVIInfo? _attributePSVI; - //Attributes - private int _attributeCount; //Total count of attributes including default + // Attributes + private int _attributeCount; // Total count of attributes including default private int _coreReaderAttributeCount; private int _currentAttrIndex; private AttributePSVIInfo[] _attributePSVINodes; private ArrayList _defaultAttributes; - //Inline Schema - private Parser _inlineSchemaParser = null; + // Inline Schema + private Parser? _inlineSchemaParser = null; - //Typed Value & PSVI - private object _atomicValue; + // Typed Value & PSVI + private object? _atomicValue; private XmlSchemaInfo _xmlSchemaInfo; // original string of the atomic value - private string _originalAtomicValueString; + private string? _originalAtomicValueString; - //cached coreReader information + // cached coreReader information private readonly XmlNameTable _coreReaderNameTable; - private XsdCachingReader _cachingReader; + private XsdCachingReader? _cachingReader; - //ReadAttributeValue TextNode - private ValidatingReaderNodeData _textNode; + // ReadAttributeValue TextNode + private ValidatingReaderNodeData? _textNode; - //To avoid SchemaNames creation + // To avoid SchemaNames creation private string _nsXmlNs; private string _nsXs; private string _nsXsi; @@ -109,20 +112,20 @@ private enum ValidatingReaderState private string _xsiSchemaLocation; private string _xsiNoNamespaceSchemaLocation; - //Underlying reader's IXmlLineInfo - private IXmlLineInfo _lineInfo; + // Underlying reader's IXmlLineInfo + private IXmlLineInfo? _lineInfo; // helpers for Read[Element]ContentAs{Base64,BinHex} methods - private ReadContentAsBinaryHelper _readBinaryHelper; + private ReadContentAsBinaryHelper? _readBinaryHelper; private ValidatingReaderState _savedState; - //Constants + // Constants private const int InitialAttributeCount = 8; - private static volatile Type s_typeOfString; + private static volatile Type s_typeOfString = null!; - //Constructor - internal XsdValidatingReader(XmlReader reader, XmlResolver xmlResolver, XmlReaderSettings readerSettings, XmlSchemaObject partialValidationType) + // Constructor + internal XsdValidatingReader(XmlReader reader, XmlResolver? xmlResolver, XmlReaderSettings readerSettings, XmlSchemaObject? partialValidationType) { _coreReader = reader; _coreReaderNSResolver = reader as IXmlNamespaceResolver; @@ -133,21 +136,11 @@ internal XsdValidatingReader(XmlReader reader, XmlResolver xmlResolver, XmlReade _nsManager = new XmlNamespaceManager(_coreReaderNameTable); _manageNamespaces = true; } + _thisNSResolver = this as IXmlNamespaceResolver; _xmlResolver = xmlResolver; _processInlineSchema = (readerSettings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0; - Init(); - SetupValidator(readerSettings, reader, partialValidationType); - _validationEvent = readerSettings.GetEventHandler(); - } - - internal XsdValidatingReader(XmlReader reader, XmlResolver xmlResolver, XmlReaderSettings readerSettings) - : - this(reader, xmlResolver, readerSettings, null) - { } - private void Init() - { _validationState = ValidatingReaderState.Init; _defaultAttributes = new ArrayList(); _currentAttrIndex = -1; @@ -156,7 +149,7 @@ private void Init() s_typeOfString = typeof(string); _xmlSchemaInfo = new XmlSchemaInfo(); - //Add common strings to be compared to NameTable + // Add common strings to be compared to NameTable _nsXmlNs = _coreReaderNameTable.Add(XmlReservedNs.NsXmlNs); _nsXs = _coreReaderNameTable.Add(XmlReservedNs.NsXs); _nsXsi = _coreReaderNameTable.Add(XmlReservedNs.NsXsi); @@ -165,20 +158,30 @@ private void Init() _xsiSchemaLocation = _coreReaderNameTable.Add("schemaLocation"); _xsiNoNamespaceSchemaLocation = _coreReaderNameTable.Add("noNamespaceSchemaLocation"); _xsdSchema = _coreReaderNameTable.Add("schema"); + + SetupValidator(readerSettings, reader, partialValidationType); + _validationEvent = readerSettings.GetEventHandler(); } - private void SetupValidator(XmlReaderSettings readerSettings, XmlReader reader, XmlSchemaObject partialValidationType) + internal XsdValidatingReader(XmlReader reader, XmlResolver? xmlResolver, XmlReaderSettings readerSettings) + : this(reader, xmlResolver, readerSettings, null) + { } + + [MemberNotNull("_validator")] + private void SetupValidator(XmlReaderSettings readerSettings, XmlReader reader, XmlSchemaObject? partialValidationType) { _validator = new XmlSchemaValidator(_coreReaderNameTable, readerSettings.Schemas, _thisNSResolver, readerSettings.ValidationFlags); _validator.XmlResolver = _xmlResolver; - _validator.SourceUri = XmlConvert.ToUri(reader.BaseURI); //Not using XmlResolver.ResolveUri as it checks for relative Uris,reader.BaseURI will be absolute file paths or string.Empty + _validator.SourceUri = XmlConvert.ToUri(reader.BaseURI); // Not using XmlResolver.ResolveUri as it checks for relative Uris,reader.BaseURI will be absolute file paths or string.Empty _validator.ValidationEventSender = this; _validator.ValidationEventHandler += readerSettings.GetEventHandler(); _validator.LineInfoProvider = _lineInfo; + if (_validator.ProcessSchemaHints) { _validator.SchemaSet.ReaderSettings.DtdProcessing = readerSettings.DtdProcessing; } + _validator.SetDtdSchemaInfo(reader.DtdInfo); if (partialValidationType != null) { @@ -195,13 +198,9 @@ public override XmlReaderSettings Settings { get { - XmlReaderSettings settings = _coreReader.Settings; - if (null != settings) - settings = settings.Clone(); - if (settings == null) - { - settings = new XmlReaderSettings(); - } + XmlReaderSettings? settings = _coreReader.Settings; + settings = settings != null ? settings.Clone() : new XmlReaderSettings(); + settings.Schemas = _validator.SchemaSet; settings.ValidationType = ValidationType.Schema; settings.ValidationFlags = _validator.ValidationFlags; @@ -219,16 +218,18 @@ public override XmlNodeType NodeType { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return _cachedNode.NodeType; } else { XmlNodeType nodeType = _coreReader.NodeType; - //Check for significant whitespace + // Check for significant whitespace if (nodeType == XmlNodeType.Whitespace && (_validator.CurrentContentType == XmlSchemaContentType.TextOnly || _validator.CurrentContentType == XmlSchemaContentType.Mixed)) { return XmlNodeType.SignificantWhitespace; } + return nodeType; } } @@ -241,13 +242,16 @@ public override string Name { if (_validationState == ValidatingReaderState.OnDefaultAttribute) { + Debug.Assert(_cachedNode != null); string prefix = _validator.GetDefaultAttributePrefix(_cachedNode.Namespace); if (prefix != null && prefix.Length != 0) { return prefix + ":" + _cachedNode.LocalName; } + return _cachedNode.LocalName; } + return _coreReader.Name; } } @@ -259,8 +263,10 @@ public override string LocalName { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return _cachedNode.LocalName; } + return _coreReader.LocalName; } } @@ -272,8 +278,10 @@ public override string NamespaceURI { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return _cachedNode.Namespace; } + return _coreReader.NamespaceURI; } } @@ -285,8 +293,10 @@ public override string Prefix { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return _cachedNode.Prefix; } + return _coreReader.Prefix; } } @@ -300,6 +310,7 @@ public override bool HasValue { return true; } + return _coreReader.HasValue; } } @@ -311,8 +322,10 @@ public override string Value { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return _cachedNode.RawValue; } + return _coreReader.Value; } } @@ -324,14 +337,16 @@ public override int Depth { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return _cachedNode.Depth; } + return _coreReader.Depth; } } // Gets the base URI of the current node. - public override string BaseURI + public override string? BaseURI { get { @@ -355,10 +370,12 @@ public override bool IsDefault get { if (_validationState == ValidatingReaderState.OnDefaultAttribute) - { //XSD default attributes + { + // XSD default attributes return true; } - return _coreReader.IsDefault; //This is DTD Default attribute + + return _coreReader.IsDefault; // This is DTD Default attribute } } @@ -407,15 +424,19 @@ public override System.Type ValueType case XmlNodeType.EndElement: if (_xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) { + Debug.Assert(_xmlSchemaInfo.SchemaType.Datatype != null); return _xmlSchemaInfo.SchemaType.Datatype.ValueType; } + goto default; case XmlNodeType.Attribute: if (_attributePSVI != null && AttributeSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) { + Debug.Assert(AttributeSchemaInfo.SchemaType.Datatype != null); return AttributeSchemaInfo.SchemaType.Datatype.ValueType; } + goto default; default: @@ -440,8 +461,9 @@ public override bool ReadContentAsBoolean() { throw CreateReadContentAsException(nameof(ReadContentAsBoolean)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -473,8 +495,9 @@ public override DateTime ReadContentAsDateTime() { throw CreateReadContentAsException(nameof(ReadContentAsDateTime)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -506,8 +529,9 @@ public override double ReadContentAsDouble() { throw CreateReadContentAsException(nameof(ReadContentAsDouble)); } - object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + + object? typedValue = InternalReadContentAsObject(); + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -539,8 +563,9 @@ public override float ReadContentAsFloat() { throw CreateReadContentAsException(nameof(ReadContentAsFloat)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -572,8 +597,9 @@ public override decimal ReadContentAsDecimal() { throw CreateReadContentAsException(nameof(ReadContentAsDecimal)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -605,8 +631,9 @@ public override int ReadContentAsInt() { throw CreateReadContentAsException(nameof(ReadContentAsInt)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -638,8 +665,10 @@ public override long ReadContentAsLong() { throw CreateReadContentAsException(nameof(ReadContentAsLong)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + try { if (xmlType != null) @@ -671,8 +700,10 @@ public override string ReadContentAsString() { throw CreateReadContentAsException(nameof(ReadContentAsString)); } + object typedValue = InternalReadContentAsObject(); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + try { if (xmlType != null) @@ -681,7 +712,7 @@ public override string ReadContentAsString() } else { - return typedValue as string; + return (typedValue as string)!; } } catch (InvalidCastException e) @@ -704,11 +735,10 @@ public override object ReadContentAs(Type returnType, IXmlNamespaceResolver name { throw CreateReadContentAsException(nameof(ReadContentAs)); } - string originalStringValue; + string originalStringValue; object typedValue = InternalReadContentAsObject(false, out originalStringValue); - - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -717,8 +747,9 @@ public override object ReadContentAs(Type returnType, IXmlNamespaceResolver name // which cannot preserve time zone, so we need to convert from the original string if (returnType == typeof(DateTimeOffset) && xmlType.Datatype is Datatype_dateTimeBase) { - typedValue = originalStringValue; + typedValue = originalStringValue!; } + return xmlType.ValueConverter.ChangeType(typedValue, returnType); } else @@ -746,9 +777,9 @@ public override object ReadElementContentAsObject() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsObject)); } - XmlSchemaType xmlType; - return InternalReadElementContentAsObject(out xmlType, true); + XmlSchemaType? xmlType; + return InternalReadElementContentAsObject(out xmlType, true)!; } public override bool ReadElementContentAsBoolean() @@ -757,9 +788,9 @@ public override bool ReadElementContentAsBoolean() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsBoolean)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -792,9 +823,9 @@ public override DateTime ReadElementContentAsDateTime() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsDateTime)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -827,9 +858,9 @@ public override double ReadElementContentAsDouble() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsDouble)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -862,9 +893,9 @@ public override float ReadElementContentAsFloat() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsFloat)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -897,9 +928,9 @@ public override decimal ReadElementContentAsDecimal() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsDecimal)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -932,9 +963,9 @@ public override int ReadElementContentAsInt() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsInt)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -967,9 +998,9 @@ public override long ReadElementContentAsLong() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsLong)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -1002,9 +1033,9 @@ public override string ReadElementContentAsString() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsString)); } - XmlSchemaType xmlType; - object typedValue = InternalReadElementContentAsObject(out xmlType); + XmlSchemaType? xmlType; + object? typedValue = InternalReadElementContentAsObject(out xmlType); try { @@ -1037,10 +1068,10 @@ public override object ReadElementContentAs(Type returnType, IXmlNamespaceResolv { throw CreateReadElementContentAsException(nameof(ReadElementContentAs)); } - XmlSchemaType xmlType; - string originalStringValue; - object typedValue = InternalReadElementContentAsObject(out xmlType, false, out originalStringValue); + XmlSchemaType? xmlType; + string? originalStringValue; + object? typedValue = InternalReadElementContentAsObject(out xmlType, false, out originalStringValue); try { @@ -1052,6 +1083,7 @@ public override object ReadElementContentAs(Type returnType, IXmlNamespaceResolv { typedValue = originalStringValue; } + return xmlType.ValueConverter.ChangeType(typedValue, returnType, namespaceResolver); } else @@ -1085,50 +1117,59 @@ public override int AttributeCount } // Gets the value of the attribute with the specified Name. - public override string GetAttribute(string name) + public override string? GetAttribute(string name) { - string attValue = _coreReader.GetAttribute(name); + string? attValue = _coreReader.GetAttribute(name); if (attValue == null && _attributeCount > 0) - { //Could be default attribute - ValidatingReaderNodeData defaultNode = GetDefaultAttribute(name, false); + { + // Could be default attribute + ValidatingReaderNodeData? defaultNode = GetDefaultAttribute(name, false); if (defaultNode != null) - { //Default found + { + // Default found attValue = defaultNode.RawValue; } } + return attValue; } // Gets the value of the attribute with the specified LocalName and NamespaceURI. - public override string GetAttribute(string name, string namespaceURI) + public override string? GetAttribute(string name, string namespaceURI) { - string attValue = _coreReader.GetAttribute(name, namespaceURI); + string? attValue = _coreReader.GetAttribute(name, namespaceURI); if (attValue == null && _attributeCount > 0) - { //Could be default attribute - namespaceURI = (namespaceURI == null) ? string.Empty : _coreReaderNameTable.Get(namespaceURI); - name = _coreReaderNameTable.Get(name); - if (name == null || namespaceURI == null) - { //Attribute not present since we did not see it + { + // Could be default attribute + string? atomizedNamespaceURI = (namespaceURI == null) ? string.Empty : _coreReaderNameTable.Get(namespaceURI); + string? atomizedName = _coreReaderNameTable.Get(name); + + if (atomizedName == null || atomizedNamespaceURI == null) + { + // Attribute not present since we did not see it return null; } - ValidatingReaderNodeData attNode = GetDefaultAttribute(name, namespaceURI, false); + + ValidatingReaderNodeData? attNode = GetDefaultAttribute(atomizedName, atomizedNamespaceURI, false); if (attNode != null) { return attNode.RawValue; } } + return attValue; } // Gets the value of the attribute with the specified index. public override string GetAttribute(int i) { - if (_attributeCount == 0) + if (i < 0 || i >= _attributeCount) { - return null; + throw new ArgumentOutOfRangeException(nameof(i)); } + if (i < _coreReaderAttributeCount) { return _coreReader.GetAttribute(i); @@ -1136,7 +1177,7 @@ public override string GetAttribute(int i) else { int defaultIndex = i - _coreReaderAttributeCount; - ValidatingReaderNodeData attNode = (ValidatingReaderNodeData)_defaultAttributes[defaultIndex]; + ValidatingReaderNodeData attNode = (ValidatingReaderNodeData)_defaultAttributes[defaultIndex]!; Debug.Assert(attNode != null); return attNode.RawValue; } @@ -1152,8 +1193,9 @@ public override bool MoveToAttribute(string name) goto Found; } else if (_attributeCount > 0) - { //Default attribute - ValidatingReaderNodeData defaultNode = GetDefaultAttribute(name, true); + { + // Default attribute + ValidatingReaderNodeData? defaultNode = GetDefaultAttribute(name, true); if (defaultNode != null) { _validationState = ValidatingReaderState.OnDefaultAttribute; @@ -1162,43 +1204,52 @@ public override bool MoveToAttribute(string name) goto Found; } } + return false; Found: if (_validationState == ValidatingReaderState.OnReadBinaryContent) { + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); _validationState = _savedState; } + return true; } // Moves to the attribute with the specified LocalName and NamespaceURI - public override bool MoveToAttribute(string name, string ns) + public override bool MoveToAttribute(string name, string? ns) { - //Check atomized local name and ns - name = _coreReaderNameTable.Get(name); + // Check atomized local name and ns + string? atomizedName = _coreReaderNameTable.Get(name); ns = ns != null ? _coreReaderNameTable.Get(ns) : string.Empty; - if (name == null || ns == null) - { //Name or ns not found in the nameTable, then attribute is not found + + if (atomizedName == null || ns == null) + { + // Name or ns not found in the nameTable, then attribute is not found return false; } - if (_coreReader.MoveToAttribute(name, ns)) + + if (_coreReader.MoveToAttribute(atomizedName, ns)) { _validationState = ValidatingReaderState.OnAttribute; if (_inlineSchemaParser == null) { - _attributePSVI = GetAttributePSVI(name, ns); + _attributePSVI = GetAttributePSVI(atomizedName, ns); Debug.Assert(_attributePSVI != null); } else - { //Parsing inline schema, no PSVI for schema attributes + { + // Parsing inline schema, no PSVI for schema attributes _attributePSVI = null; } + goto Found; } else - { //Default attribute - ValidatingReaderNodeData defaultNode = GetDefaultAttribute(name, ns, true); + { + // Default attribute + ValidatingReaderNodeData? defaultNode = GetDefaultAttribute(atomizedName, ns, true); if (defaultNode != null) { _attributePSVI = defaultNode.AttInfo; @@ -1207,13 +1258,17 @@ public override bool MoveToAttribute(string name, string ns) goto Found; } } + return false; + Found: if (_validationState == ValidatingReaderState.OnReadBinaryContent) { + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); _validationState = _savedState; } + return true; } @@ -1224,9 +1279,11 @@ public override void MoveToAttribute(int i) { throw new ArgumentOutOfRangeException(nameof(i)); } + _currentAttrIndex = i; if (i < _coreReaderAttributeCount) - { //reader attribute + { + // reader attribute _coreReader.MoveToAttribute(i); if (_inlineSchemaParser == null) { @@ -1236,17 +1293,21 @@ public override void MoveToAttribute(int i) { _attributePSVI = null; } + _validationState = ValidatingReaderState.OnAttribute; } else - { //default attribute + { + // default attribute int defaultIndex = i - _coreReaderAttributeCount; - _cachedNode = (ValidatingReaderNodeData)_defaultAttributes[defaultIndex]; + _cachedNode = (ValidatingReaderNodeData)_defaultAttributes[defaultIndex]!; _attributePSVI = _cachedNode.AttInfo; _validationState = ValidatingReaderState.OnDefaultAttribute; } + if (_validationState == ValidatingReaderState.OnReadBinaryContent) { + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); _validationState = _savedState; } @@ -1266,24 +1327,29 @@ public override bool MoveToFirstAttribute() { _attributePSVI = null; } + _validationState = ValidatingReaderState.OnAttribute; goto Found; } else if (_defaultAttributes.Count > 0) - { //check for default - _cachedNode = (ValidatingReaderNodeData)_defaultAttributes[0]; + { + // check for default + _cachedNode = (ValidatingReaderNodeData)_defaultAttributes[0]!; _attributePSVI = _cachedNode.AttInfo; _currentAttrIndex = 0; _validationState = ValidatingReaderState.OnDefaultAttribute; goto Found; } + return false; Found: if (_validationState == ValidatingReaderState.OnReadBinaryContent) { + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); _validationState = _savedState; } + return true; } @@ -1303,24 +1369,29 @@ public override bool MoveToNextAttribute() { _attributePSVI = null; } + _validationState = ValidatingReaderState.OnAttribute; goto Found; } else if (_currentAttrIndex + 1 < _attributeCount) - { //default attribute + { + // default attribute int defaultIndex = ++_currentAttrIndex - _coreReaderAttributeCount; - _cachedNode = (ValidatingReaderNodeData)_defaultAttributes[defaultIndex]; + _cachedNode = (ValidatingReaderNodeData)_defaultAttributes[defaultIndex]!; _attributePSVI = _cachedNode.AttInfo; _validationState = ValidatingReaderState.OnDefaultAttribute; goto Found; } + return false; Found: if (_validationState == ValidatingReaderState.OnReadBinaryContent) { + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); _validationState = _savedState; } + return true; } @@ -1328,11 +1399,13 @@ public override bool MoveToNextAttribute() public override bool MoveToElement() { if (_coreReader.MoveToElement() || (int)_validationState < 0) - { //states OnDefaultAttribute or OnReadAttributeValue + { + // states OnDefaultAttribute or OnReadAttributeValue _currentAttrIndex = -1; _validationState = ValidatingReaderState.ClearAttributes; return true; } + return false; } @@ -1354,6 +1427,7 @@ public override bool Read() { _validationState = ValidatingReaderState.EOF; } + return false; } @@ -1377,7 +1451,7 @@ public override bool Read() goto case ValidatingReaderState.Read; } - case ValidatingReaderState.ReadAhead: //Will enter here on calling Skip() + case ValidatingReaderState.ReadAhead: // Will enter here on calling Skip() ClearAttributesInfo(); ProcessReaderEvent(); _validationState = ValidatingReaderState.Read; @@ -1385,13 +1459,15 @@ public override bool Read() case ValidatingReaderState.OnReadBinaryContent: _validationState = _savedState; + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); return Read(); case ValidatingReaderState.Init: _validationState = ValidatingReaderState.Read; if (_coreReader.ReadState == ReadState.Interactive) - { //If the underlying reader is already positioned on a ndoe, process it + { + // If the underlying reader is already positioned on a ndoe, process it ProcessReaderEvent(); return true; } @@ -1445,26 +1521,29 @@ public override void Skip() { break; } + bool callSkipToEndElem = true; - //If union and unionValue has been parsed till EndElement, then validator.ValidateEndElement has been called - //Hence should not call SkipToEndElement as the current context has already been popped in the validator + // If union and unionValue has been parsed till EndElement, then validator.ValidateEndElement has been called + // Hence should not call SkipToEndElement as the current context has already been popped in the validator if ((_xmlSchemaInfo.IsUnionType || _xmlSchemaInfo.IsDefault) && _coreReader is XsdCachingReader) { callSkipToEndElem = false; } + _coreReader.Skip(); _validationState = ValidatingReaderState.ReadAhead; if (callSkipToEndElem) { _validator.SkipToEndElement(_xmlSchemaInfo); } + break; case XmlNodeType.Attribute: MoveToElement(); goto case XmlNodeType.Element; } - //For all other NodeTypes Skip() same as Read() + // For all other NodeTypes Skip() same as Read() Read(); return; } @@ -1479,7 +1558,7 @@ public override XmlNameTable NameTable } // Resolves a namespace prefix in the current element's scope. - public override string LookupNamespace(string prefix) + public override string? LookupNamespace(string prefix) { return _thisNSResolver.LookupNamespace(prefix); } @@ -1495,19 +1574,24 @@ public override bool ReadAttributeValue() { if (_validationState == ValidatingReaderState.OnReadBinaryContent) { + Debug.Assert(_readBinaryHelper != null); _readBinaryHelper.Finish(); _validationState = _savedState; } + if (NodeType == XmlNodeType.Attribute) { if (_validationState == ValidatingReaderState.OnDefaultAttribute) { + Debug.Assert(_cachedNode != null); _cachedNode = CreateDummyTextNode(_cachedNode.RawValue, _cachedNode.Depth + 1); _validationState = ValidatingReaderState.OnReadAttributeValue; return true; } + return _coreReader.ReadAttributeValue(); } + return false; } @@ -1537,6 +1621,7 @@ public override int ReadContentAsBase64(byte[] buffer, int index, int count) _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = _readBinaryHelper.ReadContentAsBase64(buffer, index, count); // set OnReadBinaryContent state again and return @@ -1563,6 +1648,7 @@ public override int ReadContentAsBinHex(byte[] buffer, int index, int count) _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = _readBinaryHelper.ReadContentAsBinHex(buffer, index, count); // set OnReadBinaryContent state again and return @@ -1589,6 +1675,7 @@ public override int ReadElementContentAsBase64(byte[] buffer, int index, int cou _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = _readBinaryHelper.ReadElementContentAsBase64(buffer, index, count); // set OnReadBinaryContent state again and return @@ -1615,6 +1702,7 @@ public override int ReadElementContentAsBinHex(byte[] buffer, int index, int cou _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = _readBinaryHelper.ReadElementContentAsBinHex(buffer, index, count); // set OnReadBinaryContent state again and return @@ -1637,6 +1725,7 @@ bool IXmlSchemaInfo.IsDefault { GetIsDefault(); } + return _xmlSchemaInfo.IsDefault; case XmlNodeType.EndElement: @@ -1647,11 +1736,13 @@ bool IXmlSchemaInfo.IsDefault { return AttributeSchemaInfo.IsDefault; } + break; default: break; } + return false; } } @@ -1669,6 +1760,7 @@ bool IXmlSchemaInfo.IsNil default: break; } + return false; } } @@ -1684,10 +1776,13 @@ XmlSchemaValidity IXmlSchemaInfo.Validity { return _xmlSchemaInfo.Validity; } + if (_xmlSchemaInfo.Validity == XmlSchemaValidity.Valid) - { //It might be valid for unions since we read ahead, but report notknown for consistency + { + // It might be valid for unions since we read ahead, but report notknown for consistency return XmlSchemaValidity.NotKnown; } + return _xmlSchemaInfo.Validity; case XmlNodeType.EndElement: @@ -1698,13 +1793,15 @@ XmlSchemaValidity IXmlSchemaInfo.Validity { return AttributeSchemaInfo.Validity; } + break; } + return XmlSchemaValidity.NotKnown; } } - XmlSchemaSimpleType IXmlSchemaInfo.MemberType + XmlSchemaSimpleType? IXmlSchemaInfo.MemberType { get { @@ -1715,6 +1812,7 @@ XmlSchemaSimpleType IXmlSchemaInfo.MemberType { GetMemberType(); } + return _xmlSchemaInfo.MemberType; case XmlNodeType.EndElement: @@ -1725,15 +1823,16 @@ XmlSchemaSimpleType IXmlSchemaInfo.MemberType { return AttributeSchemaInfo.MemberType; } + return null; default: - return null; //Text, PI, Comment etc + return null; // Text, PI, Comment etc } } } - XmlSchemaType IXmlSchemaInfo.SchemaType + XmlSchemaType? IXmlSchemaInfo.SchemaType { get { @@ -1748,14 +1847,16 @@ XmlSchemaType IXmlSchemaInfo.SchemaType { return AttributeSchemaInfo.SchemaType; } + return null; default: - return null; //Text, PI, Comment etc + return null; // Text, PI, Comment etc } } } - XmlSchemaElement IXmlSchemaInfo.SchemaElement + + XmlSchemaElement? IXmlSchemaInfo.SchemaElement { get { @@ -1763,11 +1864,12 @@ XmlSchemaElement IXmlSchemaInfo.SchemaElement { return _xmlSchemaInfo.SchemaElement; } + return null; } } - XmlSchemaAttribute IXmlSchemaInfo.SchemaAttribute + XmlSchemaAttribute? IXmlSchemaInfo.SchemaAttribute { get { @@ -1778,6 +1880,7 @@ XmlSchemaAttribute IXmlSchemaInfo.SchemaAttribute return AttributeSchemaInfo.SchemaAttribute; } } + return null; } } @@ -1799,6 +1902,7 @@ public int LineNumber { return _lineInfo.LineNumber; } + return 0; } } @@ -1811,6 +1915,7 @@ public int LinePosition { return _lineInfo.LinePosition; } + return 0; } } @@ -1826,11 +1931,12 @@ public int LinePosition } else { + Debug.Assert(_nsManager != null); return _nsManager.GetNamespacesInScope(scope); } } - string IXmlNamespaceResolver.LookupNamespace(string prefix) + string? IXmlNamespaceResolver.LookupNamespace(string prefix) { if (_coreReaderNSResolver != null) { @@ -1838,11 +1944,12 @@ string IXmlNamespaceResolver.LookupNamespace(string prefix) } else { + Debug.Assert(_nsManager != null); return _nsManager.LookupNamespace(prefix); } } - string IXmlNamespaceResolver.LookupPrefix(string namespaceName) + string? IXmlNamespaceResolver.LookupPrefix(string namespaceName) { if (_coreReaderNSResolver != null) { @@ -1850,11 +1957,12 @@ string IXmlNamespaceResolver.LookupPrefix(string namespaceName) } else { + Debug.Assert(_nsManager != null); return _nsManager.LookupPrefix(namespaceName); } } - //Internal / Private methods + // Internal / Private methods private object GetStringValue() { @@ -1869,7 +1977,7 @@ private XmlSchemaType ElementXmlType } } - private XmlSchemaType AttributeXmlType + private XmlSchemaType? AttributeXmlType { get { @@ -1877,6 +1985,7 @@ private XmlSchemaType AttributeXmlType { return AttributeSchemaInfo.XmlType; } + return null; } } @@ -1893,11 +2002,13 @@ private XmlSchemaInfo AttributeSchemaInfo private void ProcessReaderEvent() { if (_replayCache) - { //if in replay mode, do nothing since nodes have been validated already - //If NodeType == XmlNodeType.EndElement && if manageNamespaces, may need to pop namespace scope, since scope is not popped in ReadAheadForMemberType + { + // if in replay mode, do nothing since nodes have been validated already + // If NodeType == XmlNodeType.EndElement && if manageNamespaces, may need to pop namespace scope, since scope is not popped in ReadAheadForMemberType return; } + switch (_coreReader.NodeType) { case XmlNodeType.Element: @@ -1943,7 +2054,8 @@ private void ProcessElementEvent() _xmlSchemaInfo.Clear(); _attributeCount = _coreReaderAttributeCount = _coreReader.AttributeCount; if (!_coreReader.IsEmptyElement) - { //If its not empty schema, then parse else ignore + { + // If its not empty schema, then parse else ignore _inlineSchemaParser = new Parser(SchemaType.XSD, _coreReaderNameTable, _validator.SchemaSet.GetSchemaNames(_coreReaderNameTable), _validationEvent); _inlineSchemaParser.StartParsing(_coreReader, null); _inlineSchemaParser.ParseReaderNode(); @@ -1955,27 +2067,32 @@ private void ProcessElementEvent() } } else - { //Validate element - //Clear previous data + { + // Validate element + // Clear previous data _atomicValue = null; _originalAtomicValueString = null; _xmlSchemaInfo.Clear(); if (_manageNamespaces) { + Debug.Assert(_nsManager != null); _nsManager.PushScope(); } - //Find Xsi attributes that need to be processed before validating the element - string xsiSchemaLocation = null; - string xsiNoNamespaceSL = null; - string xsiNil = null; - string xsiType = null; + + // Find Xsi attributes that need to be processed before validating the element + string? xsiSchemaLocation = null; + string? xsiNoNamespaceSL = null; + string? xsiNil = null; + string? xsiType = null; + if (_coreReader.MoveToFirstAttribute()) { do { string objectNs = _coreReader.NamespaceURI; string objectName = _coreReader.LocalName; + if (Ref.Equal(objectNs, _nsXsi)) { if (Ref.Equal(objectName, _xsiSchemaLocation)) @@ -1995,13 +2112,16 @@ private void ProcessElementEvent() xsiNil = _coreReader.Value; } } + if (_manageNamespaces && Ref.Equal(_coreReader.NamespaceURI, _nsXmlNs)) { + Debug.Assert(_nsManager != null); _nsManager.AddNamespace(_coreReader.Prefix.Length == 0 ? string.Empty : _coreReader.LocalName, _coreReader.Value); } } while (_coreReader.MoveToNextAttribute()); _coreReader.MoveToElement(); } + _validator.ValidateElement(_coreReader.LocalName, _coreReader.NamespaceURI, _xmlSchemaInfo, xsiType, xsiNil, xsiSchemaLocation, xsiNoNamespaceSL); ValidateAttributes(); _validator.ValidateEndOfAttributes(_xmlSchemaInfo); @@ -2009,6 +2129,7 @@ private void ProcessElementEvent() { ProcessEndElementEvent(); } + _validationState = ValidatingReaderState.ClearAttributes; } } @@ -2018,10 +2139,12 @@ private void ProcessEndElementEvent() _atomicValue = _validator.ValidateEndElement(_xmlSchemaInfo); _originalAtomicValueString = GetOriginalAtomicValueStringOfElement(); if (_xmlSchemaInfo.IsDefault) - { //The atomicValue returned is a default value + { + // The atomicValue returned is a default value Debug.Assert(_atomicValue != null); int depth = _coreReader.Depth; _coreReader = GetCachingReader(); + Debug.Assert(_cachingReader != null); _cachingReader.RecordTextNode(_xmlSchemaInfo.XmlType.ValueConverter.ToString(_atomicValue), _originalAtomicValueString, depth + 1, 0, 0); _cachingReader.RecordEndElementNode(); _cachingReader.SetToReplayMode(); @@ -2029,6 +2152,7 @@ private void ProcessEndElementEvent() } else if (_manageNamespaces) { + Debug.Assert(_nsManager != null); _nsManager.PopScope(); } } @@ -2055,19 +2179,24 @@ private void ValidateAttributes() attIndex++; continue; } + attributePSVI.typedAttributeValue = _validator.ValidateAttribute(localName, ns, _valueGetter, attributePSVI.attributeSchemaInfo); if (!attributeInvalid) { attributeInvalid = attributePSVI.attributeSchemaInfo.Validity == XmlSchemaValidity.Invalid; } + attIndex++; } while (_coreReader.MoveToNextAttribute()); } + _coreReader.MoveToElement(); if (attributeInvalid) - { //If any of the attributes are invalid, Need to report element's validity as invalid + { + // If any of the attributes are invalid, Need to report element's validity as invalid _xmlSchemaInfo.Validity = XmlSchemaValidity.Invalid; } + _validator.GetUnspecifiedDefaultAttributes(_defaultAttributes, true); _attributeCount += _defaultAttributes.Count; } @@ -2081,12 +2210,14 @@ private void ClearAttributesInfo() _attributePSVI = null; } - private AttributePSVIInfo GetAttributePSVI(string name) + private AttributePSVIInfo? GetAttributePSVI(string name) { if (_inlineSchemaParser != null) - { //Parsing inline schema, no PSVI for schema attributes + { + // Parsing inline schema, no PSVI for schema attributes return null; } + string attrLocalName; string attrPrefix; string ns; @@ -2095,27 +2226,30 @@ private AttributePSVIInfo GetAttributePSVI(string name) attrLocalName = _coreReaderNameTable.Add(attrLocalName); if (attrPrefix.Length == 0) - { //empty prefix, not qualified + { + // empty prefix, not qualified ns = string.Empty; } else { - ns = _thisNSResolver.LookupNamespace(attrPrefix); + ns = _thisNSResolver.LookupNamespace(attrPrefix)!; } + return GetAttributePSVI(attrLocalName, ns); } - private AttributePSVIInfo GetAttributePSVI(string localName, string ns) + private AttributePSVIInfo? GetAttributePSVI(string localName, string ns) { Debug.Assert(_coreReaderNameTable.Get(localName) != null); Debug.Assert(_coreReaderNameTable.Get(ns) != null); - AttributePSVIInfo attInfo = null; + AttributePSVIInfo? attInfo = null; for (int i = 0; i < _coreReaderAttributeCount; i++) { attInfo = _attributePSVINodes[i]; if (attInfo != null) - { //Will be null for invalid attributes + { + // Will be null for invalid attributes if (Ref.Equal(localName, attInfo.localName) && Ref.Equal(ns, attInfo.namespaceUri)) { _currentAttrIndex = i; @@ -2123,16 +2257,17 @@ private AttributePSVIInfo GetAttributePSVI(string localName, string ns) } } } + return null; } - private ValidatingReaderNodeData GetDefaultAttribute(string name, bool updatePosition) + private ValidatingReaderNodeData? GetDefaultAttribute(string name, bool updatePosition) { string attrLocalName; string attrPrefix; ValidateNames.SplitQName(name, out attrPrefix, out attrLocalName); - //Atomize + // Atomize attrPrefix = _coreReaderNameTable.Add(attrPrefix); attrLocalName = _coreReaderNameTable.Add(attrLocalName); string ns; @@ -2142,29 +2277,32 @@ private ValidatingReaderNodeData GetDefaultAttribute(string name, bool updatePos } else { - ns = _thisNSResolver.LookupNamespace(attrPrefix); + ns = _thisNSResolver.LookupNamespace(attrPrefix)!; } + return GetDefaultAttribute(attrLocalName, ns, updatePosition); } - private ValidatingReaderNodeData GetDefaultAttribute(string attrLocalName, string ns, bool updatePosition) + private ValidatingReaderNodeData? GetDefaultAttribute(string attrLocalName, string ns, bool updatePosition) { Debug.Assert(_coreReaderNameTable.Get(attrLocalName) != null); Debug.Assert(_coreReaderNameTable.Get(ns) != null); - ValidatingReaderNodeData defaultNode = null; + ValidatingReaderNodeData? defaultNode = null; for (int i = 0; i < _defaultAttributes.Count; i++) { - defaultNode = (ValidatingReaderNodeData)_defaultAttributes[i]; + defaultNode = (ValidatingReaderNodeData)_defaultAttributes[i]!; if (Ref.Equal(defaultNode.LocalName, attrLocalName) && Ref.Equal(defaultNode.Namespace, ns)) { if (updatePosition) { _currentAttrIndex = _coreReader.AttributeCount + i; } + return defaultNode; } } + return null; } @@ -2177,18 +2315,22 @@ private AttributePSVIInfo AddAttributePSVI(int attIndex) attInfo.Reset(); return attInfo; } + if (attIndex >= _attributePSVINodes.Length - 1) - { //reached capacity of PSVIInfo array, Need to increase capacity to twice the initial + { + // reached capacity of PSVIInfo array, Need to increase capacity to twice the initial AttributePSVIInfo[] newPSVINodes = new AttributePSVIInfo[_attributePSVINodes.Length * 2]; Array.Copy(_attributePSVINodes, newPSVINodes, _attributePSVINodes.Length); _attributePSVINodes = newPSVINodes; } + attInfo = _attributePSVINodes[attIndex]; if (attInfo == null) { attInfo = new AttributePSVIInfo(); _attributePSVINodes[attIndex] = attInfo; } + return attInfo; } @@ -2207,9 +2349,11 @@ private void ProcessInlineSchema() _attributeCount = _coreReaderAttributeCount = _coreReader.AttributeCount; } else - { //Clear attributes info if nodeType is not element + { + // Clear attributes info if nodeType is not element ClearAttributesInfo(); } + if (!_inlineSchemaParser.ParseReaderNode()) { _inlineSchemaParser.FinishParsing(); @@ -2228,8 +2372,7 @@ private object InternalReadContentAsObject() private object InternalReadContentAsObject(bool unwrapTypedValue) { - string str; - return InternalReadContentAsObject(unwrapTypedValue, out str); + return InternalReadContentAsObject(unwrapTypedValue, out _); } private object InternalReadContentAsObject(bool unwrapTypedValue, out string originalStringValue) @@ -2246,10 +2389,11 @@ private object InternalReadContentAsObject(bool unwrapTypedValue, out string ori originalStringValue = (schemaAttr.DefaultValue != null) ? schemaAttr.DefaultValue : schemaAttr.FixedValue; } - return ReturnBoxedValue(_attributePSVI.typedAttributeValue, AttributeSchemaInfo.XmlType, unwrapTypedValue); + return ReturnBoxedValue(_attributePSVI.typedAttributeValue, AttributeSchemaInfo.XmlType, unwrapTypedValue)!; } else - { //return string value + { + // return string value return this.Value; } } @@ -2257,7 +2401,7 @@ private object InternalReadContentAsObject(bool unwrapTypedValue, out string ori { if (_atomicValue != null) { - originalStringValue = _originalAtomicValueString; + originalStringValue = _originalAtomicValueString!; return _atomicValue; } @@ -2269,18 +2413,19 @@ private object InternalReadContentAsObject(bool unwrapTypedValue, out string ori } } else - { //Positioned on text, CDATA, PI, Comment etc + { + // Positioned on text, CDATA, PI, Comment etc if (_validator.CurrentContentType == XmlSchemaContentType.TextOnly) - { //if current element is of simple type - object value = ReturnBoxedValue(ReadTillEndElement(), _xmlSchemaInfo.XmlType, unwrapTypedValue); - originalStringValue = _originalAtomicValueString; + { + // if current element is of simple type + object? value = ReturnBoxedValue(ReadTillEndElement(), _xmlSchemaInfo.XmlType, unwrapTypedValue)!; + originalStringValue = _originalAtomicValueString!; return value; } else { - XsdCachingReader cachingReader = _coreReader as XsdCachingReader; - if (cachingReader != null) + if (_coreReader is XsdCachingReader cachingReader) { originalStringValue = cachingReader.ReadOriginalContentAsString(); } @@ -2294,23 +2439,23 @@ private object InternalReadContentAsObject(bool unwrapTypedValue, out string ori } } - private object InternalReadElementContentAsObject(out XmlSchemaType xmlType) + private object? InternalReadElementContentAsObject(out XmlSchemaType? xmlType) { return InternalReadElementContentAsObject(out xmlType, false); } - private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, bool unwrapTypedValue) + private object? InternalReadElementContentAsObject(out XmlSchemaType? xmlType, bool unwrapTypedValue) { - string tmpString; - return InternalReadElementContentAsObject(out xmlType, unwrapTypedValue, out tmpString); + return InternalReadElementContentAsObject(out xmlType, unwrapTypedValue, out _); } - private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, bool unwrapTypedValue, out string originalString) + private object? InternalReadElementContentAsObject(out XmlSchemaType? xmlType, bool unwrapTypedValue, out string? originalString) { Debug.Assert(this.NodeType == XmlNodeType.Element); - object typedValue = null; + object? typedValue = null; xmlType = null; - //If its an empty element, can have default/fixed value + + // If its an empty element, can have default/fixed value if (this.IsEmptyElement) { if (_xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) @@ -2321,17 +2466,20 @@ private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, boo { typedValue = _atomicValue; } + originalString = _originalAtomicValueString; - xmlType = ElementXmlType; //Set this for default values + xmlType = ElementXmlType; // Set this for default values this.Read(); return typedValue; } + // move to content and read typed value this.Read(); if (this.NodeType == XmlNodeType.EndElement) - { //If IsDefault is true, the next node will be EndElement + { + // If IsDefault is true, the next node will be EndElement if (_xmlSchemaInfo.IsDefault) { if (_xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) @@ -2339,19 +2487,23 @@ private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, boo typedValue = ReturnBoxedValue(_atomicValue, _xmlSchemaInfo.XmlType, unwrapTypedValue); } else - { //anyType has default value + { + // anyType has default value typedValue = _atomicValue; } + originalString = _originalAtomicValueString; } else - { //Empty content + { + // Empty content typedValue = string.Empty; originalString = string.Empty; } } else if (this.NodeType == XmlNodeType.Element) - { //the first child is again element node + { + // the first child is again element node throw new XmlException(SR.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo); } else @@ -2364,7 +2516,8 @@ private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, boo throw new XmlException(SR.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo); } } - xmlType = ElementXmlType; //Set this as we are moving ahead to the next node + + xmlType = ElementXmlType; // Set this as we are moving ahead to the next node // move to next node this.Read(); @@ -2372,16 +2525,18 @@ private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, boo return typedValue; } - private object ReadTillEndElement() + private object? ReadTillEndElement() { if (_atomicValue == null) { while (_coreReader.Read()) { if (_replayCache) - { //If replaying nodes in the cache, they have already been validated + { + // If replaying nodes in the cache, they have already been validated continue; } + switch (_coreReader.NodeType) { case XmlNodeType.Element: @@ -2407,33 +2562,41 @@ private object ReadTillEndElement() _originalAtomicValueString = GetOriginalAtomicValueStringOfElement(); if (_manageNamespaces) { + Debug.Assert(_nsManager != null); _nsManager.PopScope(); } + goto breakWhile; } + continue; breakWhile: break; } } else - { //atomicValue != null, meaning already read ahead - Switch reader + { + // atomicValue != null, meaning already read ahead - Switch reader if (_atomicValue == this) - { //switch back invalid marker; dont need it since coreReader moved to endElement + { + // switch back invalid marker; dont need it since coreReader moved to endElement _atomicValue = null; } + SwitchReader(); } + return _atomicValue; } private void SwitchReader() { - XsdCachingReader cachingReader = _coreReader as XsdCachingReader; - if (cachingReader != null) - { //Switch back without going over the cached contents again. + if (_coreReader is XsdCachingReader cachingReader) + { + // Switch back without going over the cached contents again. _coreReader = cachingReader.GetCoreReader(); } + Debug.Assert(_coreReader.NodeType == XmlNodeType.EndElement); _replayCache = false; } @@ -2466,15 +2629,20 @@ private void ReadAheadForMemberType() _atomicValue = _validator.ValidateEndElement(_xmlSchemaInfo); //?? pop namespaceManager scope _originalAtomicValueString = GetOriginalAtomicValueStringOfElement(); if (_atomicValue == null) - { //Invalid marker + { + // Invalid marker _atomicValue = this; } else if (_xmlSchemaInfo.IsDefault) - { //The atomicValue returned is a default value + { + // The atomicValue returned is a default value + Debug.Assert(_cachingReader != null); _cachingReader.SwitchTextNodeAndEndElement(_xmlSchemaInfo.XmlType.ValueConverter.ToString(_atomicValue), _originalAtomicValueString); } + goto breakWhile; } + continue; breakWhile: break; @@ -2483,12 +2651,15 @@ private void ReadAheadForMemberType() private void GetIsDefault() { - XsdCachingReader cachedReader = _coreReader as XsdCachingReader; + XsdCachingReader? cachedReader = _coreReader as XsdCachingReader; if (cachedReader == null && _xmlSchemaInfo.HasDefaultValue) - { //Get Isdefault + { + // Get Isdefault _coreReader = GetCachingReader(); + Debug.Assert(_cachingReader != null); if (_xmlSchemaInfo.IsUnionType && !_xmlSchemaInfo.IsNil) - { //If it also union, get the memberType as well + { + // If it also union, get the memberType as well ReadAheadForMemberType(); } else @@ -2519,9 +2690,11 @@ private void GetIsDefault() _atomicValue = _validator.ValidateEndElement(_xmlSchemaInfo); //?? pop namespaceManager scope _originalAtomicValueString = GetOriginalAtomicValueStringOfElement(); if (_xmlSchemaInfo.IsDefault) - { //The atomicValue returned is a default value + { + // The atomicValue returned is a default value _cachingReader.SwitchTextNodeAndEndElement(_xmlSchemaInfo.XmlType.ValueConverter.ToString(_atomicValue), _originalAtomicValueString); } + break; default: @@ -2529,6 +2702,7 @@ private void GetIsDefault() } } } + _cachingReader.SetToReplayMode(); _replayCache = true; } @@ -2540,39 +2714,46 @@ private void GetMemberType() { return; } - XsdCachingReader cachedReader = _coreReader as XsdCachingReader; + + XsdCachingReader? cachedReader = _coreReader as XsdCachingReader; if (cachedReader == null && _xmlSchemaInfo.IsUnionType && !_xmlSchemaInfo.IsNil) { _coreReader = GetCachingReader(); + Debug.Assert(_cachingReader != null); ReadAheadForMemberType(); _cachingReader.SetToReplayMode(); _replayCache = true; } } - private object ReturnBoxedValue(object typedValue, XmlSchemaType xmlType, bool unWrap) + private object? ReturnBoxedValue(object? typedValue, XmlSchemaType xmlType, bool unWrap) { if (typedValue != null) { if (unWrap) - { //convert XmlAtomicValue[] to object[] for list of unions; The other cases return typed value of the valueType anyway + { + // convert XmlAtomicValue[] to object[] for list of unions; The other cases return typed value of the valueType anyway Debug.Assert(xmlType != null && xmlType.Datatype != null); if (xmlType.Datatype.Variety == XmlSchemaDatatypeVariety.List) { - Datatype_List listType = xmlType.Datatype as Datatype_List; + Datatype_List? listType = xmlType.Datatype as Datatype_List; + Debug.Assert(listType != null); if (listType.ItemType.Variety == XmlSchemaDatatypeVariety.Union) { typedValue = xmlType.ValueConverter.ChangeType(typedValue, xmlType.Datatype.ValueType, _thisNSResolver); } } } + return typedValue; } else - { //return the original string value of the element or attribute + { + // return the original string value of the element or attribute Debug.Assert(NodeType != XmlNodeType.Attribute); typedValue = _validator.GetConcatenatedValue(); } + return typedValue; } @@ -2586,6 +2767,7 @@ private XsdCachingReader GetCachingReader() { _cachingReader.Reset(_coreReader); } + _lineInfo = _cachingReader as IXmlLineInfo; return _cachingReader; } @@ -2596,6 +2778,7 @@ internal ValidatingReaderNodeData CreateDummyTextNode(string attributeValue, int { _textNode = new ValidatingReaderNodeData(XmlNodeType.Text); } + _textNode.Depth = depth; _textNode.RawValue = attributeValue; return _textNode; @@ -2603,7 +2786,7 @@ internal ValidatingReaderNodeData CreateDummyTextNode(string attributeValue, int internal void CachingCallBack(XsdCachingReader cachingReader) { - _coreReader = cachingReader.GetCoreReader(); //re-switch the core-reader after caching reader is done + _coreReader = cachingReader.GetCoreReader(); // re-switch the core-reader after caching reader is done _lineInfo = cachingReader.GetLineInfo(); _replayCache = false; } @@ -2622,6 +2805,7 @@ private string GetOriginalAtomicValueStringOfElement() { return _validator.GetConcatenatedValue(); } + return string.Empty; } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReaderAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReaderAsync.cs index 24b68ff01ddba..a9953d2873af4 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReaderAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XsdValidatingReaderAsync.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using System.Text; using System.Xml.Schema; @@ -23,8 +24,10 @@ public override Task GetValueAsync() { if ((int)_validationState < 0) { + Debug.Assert(_cachedNode != null); return Task.FromResult(_cachedNode.RawValue); } + return _coreReader.GetValueAsync(); } @@ -44,8 +47,9 @@ public override async Task ReadContentAsStringAsync() { throw CreateReadContentAsException(nameof(ReadContentAsString)); } + object typedValue = await InternalReadContentAsObjectAsync().ConfigureAwait(false); - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -54,7 +58,7 @@ public override async Task ReadContentAsStringAsync() } else { - return typedValue as string; + return (typedValue as string)!; } } catch (InvalidCastException e) @@ -77,6 +81,7 @@ public override async Task ReadContentAsAsync(Type returnType, IXmlNames { throw CreateReadContentAsException(nameof(ReadContentAs)); } + string originalStringValue; var tuple_0 = await InternalReadContentAsObjectTupleAsync(false).ConfigureAwait(false); @@ -84,7 +89,7 @@ public override async Task ReadContentAsAsync(Type returnType, IXmlNames object typedValue = tuple_0.Item2; - XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; + XmlSchemaType? xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; try { if (xmlType != null) @@ -95,6 +100,7 @@ public override async Task ReadContentAsAsync(Type returnType, IXmlNames { typedValue = originalStringValue; } + return xmlType.ValueConverter.ChangeType(typedValue, returnType); } else @@ -134,12 +140,13 @@ public override async Task ReadElementContentAsStringAsync() { throw CreateReadElementContentAsException(nameof(ReadElementContentAsString)); } + XmlSchemaType xmlType; - var tuple_9 = await InternalReadElementContentAsObjectAsync().ConfigureAwait(false); - xmlType = tuple_9.Item1; + var content = await InternalReadElementContentAsObjectAsync().ConfigureAwait(false); + xmlType = content.Item1; - object typedValue = tuple_9.Item2; + object typedValue = content.Item2; try { @@ -149,6 +156,7 @@ public override async Task ReadElementContentAsStringAsync() } else { + Debug.Assert(false, $"{nameof(typedValue)} should never be null"); return typedValue as string; } } @@ -172,14 +180,15 @@ public override async Task ReadElementContentAsAsync(Type returnType, IX { throw CreateReadElementContentAsException(nameof(ReadElementContentAs)); } + XmlSchemaType xmlType; string originalStringValue; - var tuple_10 = await InternalReadElementContentAsObjectTupleAsync(false).ConfigureAwait(false); - xmlType = tuple_10.Item1; - originalStringValue = tuple_10.Item2; + var content = await InternalReadElementContentAsObjectTupleAsync(false).ConfigureAwait(false); + xmlType = content.Item1; + originalStringValue = content.Item2; - object typedValue = tuple_10.Item3; + object typedValue = content.Item3; try { @@ -191,6 +200,7 @@ public override async Task ReadElementContentAsAsync(Type returnType, IX { typedValue = originalStringValue; } + return xmlType.ValueConverter.ChangeType(typedValue, returnType, namespaceResolver); } else @@ -227,6 +237,7 @@ private Task ReadAsync_Read(Task task) { _validationState = ValidatingReaderState.EOF; } + return AsyncHelper.DoneTaskFalse; } } @@ -250,6 +261,7 @@ private async Task _ReadAsync_Read(Task task) { _validationState = ValidatingReaderState.EOF; } + return false; } } @@ -302,19 +314,21 @@ public override Task ReadAsync() goto case ValidatingReaderState.Read; } - case ValidatingReaderState.ReadAhead: //Will enter here on calling Skip() + case ValidatingReaderState.ReadAhead: // Will enter here on calling Skip() ClearAttributesInfo(); Task task = ProcessReaderEventAsync(); return ReadAsync_ReadAhead(task); case ValidatingReaderState.OnReadBinaryContent: _validationState = _savedState; + Debug.Assert(_readBinaryHelper != null); return _readBinaryHelper.FinishAsync().CallBoolTaskFuncWhenFinishAsync(thisRef => thisRef.ReadAsync(), this); case ValidatingReaderState.Init: _validationState = ValidatingReaderState.Read; if (_coreReader.ReadState == ReadState.Interactive) - { //If the underlying reader is already positioned on a ndoe, process it + { + // If the underlying reader is already positioned on a ndoe, process it return ProcessReaderEventAsync().ReturnTrueTaskWhenFinishAsync(); } else @@ -342,26 +356,29 @@ public override async Task SkipAsync() { break; } + bool callSkipToEndElem = true; - //If union and unionValue has been parsed till EndElement, then validator.ValidateEndElement has been called - //Hence should not call SkipToEndElement as the current context has already been popped in the validator + // If union and unionValue has been parsed till EndElement, then validator.ValidateEndElement has been called + // Hence should not call SkipToEndElement as the current context has already been popped in the validator if ((_xmlSchemaInfo.IsUnionType || _xmlSchemaInfo.IsDefault) && _coreReader is XsdCachingReader) { callSkipToEndElem = false; } + await _coreReader.SkipAsync().ConfigureAwait(false); _validationState = ValidatingReaderState.ReadAhead; if (callSkipToEndElem) { _validator.SkipToEndElement(_xmlSchemaInfo); } + break; case XmlNodeType.Attribute: MoveToElement(); goto case XmlNodeType.Element; } - //For all other NodeTypes Skip() same as Read() + // For all other NodeTypes Skip() same as Read() await ReadAsync().ConfigureAwait(false); return; } @@ -384,6 +401,7 @@ public override async Task ReadContentAsBase64Async(byte[] buffer, int inde _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = await _readBinaryHelper.ReadContentAsBase64Async(buffer, index, count).ConfigureAwait(false); // set OnReadBinaryContent state again and return @@ -410,6 +428,7 @@ public override async Task ReadContentAsBinHexAsync(byte[] buffer, int inde _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = await _readBinaryHelper.ReadContentAsBinHexAsync(buffer, index, count).ConfigureAwait(false); // set OnReadBinaryContent state again and return @@ -436,6 +455,7 @@ public override async Task ReadElementContentAsBase64Async(byte[] buffer, i _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = await _readBinaryHelper.ReadElementContentAsBase64Async(buffer, index, count).ConfigureAwait(false); // set OnReadBinaryContent state again and return @@ -462,6 +482,7 @@ public override async Task ReadElementContentAsBinHexAsync(byte[] buffer, i _validationState = _savedState; // call to the helper + Debug.Assert(_readBinaryHelper != null); int readCount = await _readBinaryHelper.ReadElementContentAsBinHexAsync(buffer, index, count).ConfigureAwait(false); // set OnReadBinaryContent state again and return @@ -473,11 +494,13 @@ public override async Task ReadElementContentAsBinHexAsync(byte[] buffer, i private Task ProcessReaderEventAsync() { if (_replayCache) - { //if in replay mode, do nothing since nodes have been validated already - //If NodeType == XmlNodeType.EndElement && if manageNamespaces, may need to pop namespace scope, since scope is not popped in ReadAheadForMemberType + { + // if in replay mode, do nothing since nodes have been validated already + // If NodeType == XmlNodeType.EndElement && if manageNamespaces, may need to pop namespace scope, since scope is not popped in ReadAheadForMemberType return Task.CompletedTask; } + switch (_coreReader.NodeType) { case XmlNodeType.Element: @@ -523,7 +546,8 @@ private async Task ProcessElementEventAsync() _xmlSchemaInfo.Clear(); _attributeCount = _coreReaderAttributeCount = _coreReader.AttributeCount; if (!_coreReader.IsEmptyElement) - { //If its not empty schema, then parse else ignore + { + // If its not empty schema, then parse else ignore _inlineSchemaParser = new Parser(SchemaType.XSD, _coreReaderNameTable, _validator.SchemaSet.GetSchemaNames(_coreReaderNameTable), _validationEvent); await _inlineSchemaParser.StartParsingAsync(_coreReader, null).ConfigureAwait(false); _inlineSchemaParser.ParseReaderNode(); @@ -535,21 +559,25 @@ private async Task ProcessElementEventAsync() } } else - { //Validate element - //Clear previous data + { + // Validate element + // Clear previous data _atomicValue = null; _originalAtomicValueString = null; _xmlSchemaInfo.Clear(); if (_manageNamespaces) { + Debug.Assert(_nsManager != null); _nsManager.PushScope(); } - //Find Xsi attributes that need to be processed before validating the element - string xsiSchemaLocation = null; - string xsiNoNamespaceSL = null; - string xsiNil = null; - string xsiType = null; + + // Find Xsi attributes that need to be processed before validating the element + string? xsiSchemaLocation = null; + string? xsiNoNamespaceSL = null; + string? xsiNil = null; + string? xsiType = null; + if (_coreReader.MoveToFirstAttribute()) { do @@ -575,13 +603,16 @@ private async Task ProcessElementEventAsync() xsiNil = _coreReader.Value; } } + if (_manageNamespaces && Ref.Equal(_coreReader.NamespaceURI, _nsXmlNs)) { + Debug.Assert(_nsManager != null); _nsManager.AddNamespace(_coreReader.Prefix.Length == 0 ? string.Empty : _coreReader.LocalName, _coreReader.Value); } } while (_coreReader.MoveToNextAttribute()); _coreReader.MoveToElement(); } + _validator.ValidateElement(_coreReader.LocalName, _coreReader.NamespaceURI, _xmlSchemaInfo, xsiType, xsiNil, xsiSchemaLocation, xsiNoNamespaceSL); ValidateAttributes(); _validator.ValidateEndOfAttributes(_xmlSchemaInfo); @@ -589,6 +620,7 @@ private async Task ProcessElementEventAsync() { await ProcessEndElementEventAsync().ConfigureAwait(false); } + _validationState = ValidatingReaderState.ClearAttributes; } } @@ -598,10 +630,12 @@ private async Task ProcessEndElementEventAsync() _atomicValue = _validator.ValidateEndElement(_xmlSchemaInfo); _originalAtomicValueString = GetOriginalAtomicValueStringOfElement(); if (_xmlSchemaInfo.IsDefault) - { //The atomicValue returned is a default value + { + // The atomicValue returned is a default value Debug.Assert(_atomicValue != null); int depth = _coreReader.Depth; _coreReader = GetCachingReader(); + Debug.Assert(_cachingReader != null); _cachingReader.RecordTextNode(_xmlSchemaInfo.XmlType.ValueConverter.ToString(_atomicValue), _originalAtomicValueString, depth + 1, 0, 0); _cachingReader.RecordEndElementNode(); await _cachingReader.SetToReplayModeAsync().ConfigureAwait(false); @@ -609,6 +643,7 @@ private async Task ProcessEndElementEventAsync() } else if (_manageNamespaces) { + Debug.Assert(_nsManager != null); _nsManager.PopScope(); } } @@ -623,9 +658,11 @@ private async Task ProcessInlineSchemaAsync() _attributeCount = _coreReaderAttributeCount = _coreReader.AttributeCount; } else - { //Clear attributes info if nodeType is not element + { + // Clear attributes info if nodeType is not element ClearAttributesInfo(); } + if (!_inlineSchemaParser.ParseReaderNode()) { _inlineSchemaParser.FinishParsing(); @@ -644,9 +681,8 @@ private Task InternalReadContentAsObjectAsync() private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValue) { - var tuple_11 = await InternalReadContentAsObjectTupleAsync(unwrapTypedValue).ConfigureAwait(false); - - return tuple_11.Item2; + var content = await InternalReadContentAsObjectTupleAsync(unwrapTypedValue).ConfigureAwait(false); + return content.Item2; } private async Task> InternalReadContentAsObjectTupleAsync(bool unwrapTypedValue) @@ -666,11 +702,12 @@ private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValu originalStringValue = (schemaAttr.DefaultValue != null) ? schemaAttr.DefaultValue : schemaAttr.FixedValue; } - tuple = new Tuple(originalStringValue, ReturnBoxedValue(_attributePSVI.typedAttributeValue, AttributeSchemaInfo.XmlType, unwrapTypedValue)); + tuple = new Tuple(originalStringValue, ReturnBoxedValue(_attributePSVI.typedAttributeValue, AttributeSchemaInfo.XmlType, unwrapTypedValue)!); return tuple; } else - { //return string value + { + // return string value tuple = new Tuple(originalStringValue, this.Value); return tuple; } @@ -679,6 +716,7 @@ private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValu { if (_atomicValue != null) { + Debug.Assert(_originalAtomicValueString != null); originalStringValue = _originalAtomicValueString; tuple = new Tuple(originalStringValue, _atomicValue); @@ -693,10 +731,15 @@ private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValu } } else - { //Positioned on text, CDATA, PI, Comment etc + { + // Positioned on text, CDATA, PI, Comment etc if (_validator.CurrentContentType == XmlSchemaContentType.TextOnly) - { //if current element is of simple type - object value = ReturnBoxedValue(await ReadTillEndElementAsync().ConfigureAwait(false), _xmlSchemaInfo.XmlType, unwrapTypedValue); + { + // if current element is of simple type + object? value = ReturnBoxedValue(await ReadTillEndElementAsync().ConfigureAwait(false), _xmlSchemaInfo.XmlType, unwrapTypedValue)!; + Debug.Assert(value != null); + + Debug.Assert(_originalAtomicValueString != null); originalStringValue = _originalAtomicValueString; tuple = new Tuple(originalStringValue, value); @@ -704,7 +747,7 @@ private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValu } else { - XsdCachingReader cachingReader = _coreReader as XsdCachingReader; + XsdCachingReader? cachingReader = _coreReader as XsdCachingReader; if (cachingReader != null) { originalStringValue = cachingReader.ReadOriginalContentAsString(); @@ -727,71 +770,77 @@ private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValu private async Task> InternalReadElementContentAsObjectAsync(bool unwrapTypedValue) { - var tuple_13 = await InternalReadElementContentAsObjectTupleAsync(unwrapTypedValue).ConfigureAwait(false); + var content = await InternalReadElementContentAsObjectTupleAsync(unwrapTypedValue).ConfigureAwait(false); - return new Tuple(tuple_13.Item1, tuple_13.Item3); + return new Tuple(content.Item1, content.Item3); } private async Task> InternalReadElementContentAsObjectTupleAsync(bool unwrapTypedValue) { - Tuple tuple; - XmlSchemaType xmlType; + XmlSchemaType? xmlType = null; string originalString; Debug.Assert(this.NodeType == XmlNodeType.Element); - object typedValue = null; - xmlType = null; - //If its an empty element, can have default/fixed value + object typedValue; + // If its an empty element, can have default/fixed value if (this.IsEmptyElement) { if (_xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) { - typedValue = ReturnBoxedValue(_atomicValue, _xmlSchemaInfo.XmlType, unwrapTypedValue); + typedValue = ReturnBoxedValue(_atomicValue, _xmlSchemaInfo.XmlType, unwrapTypedValue)!; } else { - typedValue = _atomicValue; + typedValue = _atomicValue!; } + + Debug.Assert(_originalAtomicValueString != null); originalString = _originalAtomicValueString; - xmlType = ElementXmlType; //Set this for default values + xmlType = ElementXmlType; // Set this for default values await this.ReadAsync().ConfigureAwait(false); - tuple = new Tuple(xmlType, originalString, typedValue); - return tuple; + return new Tuple(xmlType, originalString, typedValue); } + // move to content and read typed value await this.ReadAsync().ConfigureAwait(false); if (this.NodeType == XmlNodeType.EndElement) - { //If IsDefault is true, the next node will be EndElement + { + // If IsDefault is true, the next node will be EndElement if (_xmlSchemaInfo.IsDefault) { if (_xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) { - typedValue = ReturnBoxedValue(_atomicValue, _xmlSchemaInfo.XmlType, unwrapTypedValue); + typedValue = ReturnBoxedValue(_atomicValue, _xmlSchemaInfo.XmlType, unwrapTypedValue)!; } else - { //anyType has default value - typedValue = _atomicValue; + { + // anyType has default value + typedValue = _atomicValue!; } + + Debug.Assert(_originalAtomicValueString != null); originalString = _originalAtomicValueString; } else - { //Empty content + { + // Empty content typedValue = string.Empty; originalString = string.Empty; } } else if (this.NodeType == XmlNodeType.Element) - { //the first child is again element node + { + // the first child is again element node throw new XmlException(SR.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo); } else { - var tuple_14 = await InternalReadContentAsObjectTupleAsync(unwrapTypedValue).ConfigureAwait(false); - originalString = tuple_14.Item1; + var content = await InternalReadContentAsObjectTupleAsync(unwrapTypedValue).ConfigureAwait(false); + originalString = content.Item1; - typedValue = tuple_14.Item2; + typedValue = content.Item2; // ReadElementContentAsXXX cannot be called on mixed content, if positioned on node other than EndElement, Error if (this.NodeType != XmlNodeType.EndElement) @@ -799,25 +848,27 @@ private async Task InternalReadContentAsObjectAsync(bool unwrapTypedValu throw new XmlException(SR.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo); } } - xmlType = ElementXmlType; //Set this as we are moving ahead to the next node + + xmlType = ElementXmlType; // Set this as we are moving ahead to the next node // move to next node await this.ReadAsync().ConfigureAwait(false); - tuple = new Tuple(xmlType, originalString, typedValue); - return tuple; + return new Tuple(xmlType, originalString, typedValue); } - private async Task ReadTillEndElementAsync() + private async Task ReadTillEndElementAsync() { if (_atomicValue == null) { while (await _coreReader.ReadAsync().ConfigureAwait(false)) { if (_replayCache) - { //If replaying nodes in the cache, they have already been validated + { + // If replaying nodes in the cache, they have already been validated continue; } + switch (_coreReader.NodeType) { case XmlNodeType.Element: @@ -843,23 +894,30 @@ private async Task ReadTillEndElementAsync() _originalAtomicValueString = GetOriginalAtomicValueStringOfElement(); if (_manageNamespaces) { + Debug.Assert(_nsManager != null); _nsManager.PopScope(); } + goto breakWhile; } + continue; breakWhile: break; } } else - { //atomicValue != null, meaning already read ahead - Switch reader + { + // atomicValue != null, meaning already read ahead - Switch reader if (_atomicValue == this) - { //switch back invalid marker; dont need it since coreReader moved to endElement + { + // switch back invalid marker; dont need it since coreReader moved to endElement _atomicValue = null; } + SwitchReader(); } + return _atomicValue; } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNodeReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNodeReader.cs index e8290112ad098..9d73bfa51103a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNodeReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlNodeReader.cs @@ -919,7 +919,7 @@ internal string LookupPrefix(string namespaceName) { return _nameTable.Add("xml"); } - if (namespaceName == string.Empty) + if (namespaceName.Length == 0) { return string.Empty; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/NameTable.cs b/src/libraries/System.Private.Xml/src/System/Xml/NameTable.cs index 5bb3c734340a7..0ee36591cc7d7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/NameTable.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/NameTable.cs @@ -103,7 +103,7 @@ public override string Add(char[] key, int start, int len) // Compatibility check for len < 0, just throw the same exception as new string(key, start, len) if (len < 0) { - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(len)); } int hashCode = ComputeHash32(key, start, len); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/AutoValidator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/AutoValidator.cs index 4ae13d948b817..70f9dfa5833f3 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/AutoValidator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/AutoValidator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { using System.Diagnostics; @@ -43,7 +44,7 @@ public override void Validate() public override void CompleteValidation() { } - public override object FindId(string name) + public override object? FindId(string name) { return null; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/BaseValidator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/BaseValidator.cs index c9f730028286f..237d763960885 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/BaseValidator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/BaseValidator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { using System.IO; @@ -9,25 +10,26 @@ namespace System.Xml.Schema using System.Xml; using System.Text; using System.Collections; + using System.Diagnostics.CodeAnalysis; #pragma warning disable 618 internal class BaseValidator { - private readonly XmlSchemaCollection _schemaCollection; + private readonly XmlSchemaCollection? _schemaCollection; private readonly IValidationEventHandling _eventHandling; private readonly XmlNameTable _nameTable; - private SchemaNames _schemaNames; + private SchemaNames? _schemaNames; private readonly PositionInfo _positionInfo; - private XmlResolver _xmlResolver; - private Uri _baseUri; + private XmlResolver? _xmlResolver; + private Uri? _baseUri; - protected SchemaInfo schemaInfo; + protected SchemaInfo? schemaInfo; protected XmlValidatingReaderImpl reader; protected XmlQualifiedName elementName; - protected ValidationState context; - protected StringBuilder textValue; - protected string textString; + protected ValidationState? context; + protected StringBuilder? textValue; + protected string? textString; protected bool hasSibling; protected bool checkDatatype; @@ -44,7 +46,7 @@ public BaseValidator(BaseValidator other) elementName = other.elementName; } - public BaseValidator(XmlValidatingReaderImpl reader, XmlSchemaCollection schemaCollection, IValidationEventHandling eventHandling) + public BaseValidator(XmlValidatingReaderImpl reader, XmlSchemaCollection? schemaCollection, IValidationEventHandling eventHandling) { Debug.Assert(schemaCollection == null || schemaCollection.NameTable == reader.NameTable); this.reader = reader; @@ -60,7 +62,7 @@ public XmlValidatingReaderImpl Reader get { return reader; } } - public XmlSchemaCollection SchemaCollection + public XmlSchemaCollection? SchemaCollection { get { return _schemaCollection; } } @@ -78,6 +80,7 @@ public SchemaNames SchemaNames { return _schemaNames; } + if (_schemaCollection != null) { _schemaNames = _schemaCollection.GetSchemaNames(_nameTable); @@ -86,6 +89,7 @@ public SchemaNames SchemaNames { _schemaNames = new SchemaNames(_nameTable); } + return _schemaNames; } } @@ -95,13 +99,13 @@ public PositionInfo PositionInfo get { return _positionInfo; } } - public XmlResolver XmlResolver + public XmlResolver? XmlResolver { get { return _xmlResolver; } set { _xmlResolver = value; } } - public Uri BaseUri + public Uri? BaseUri { get { return _baseUri; } set { _baseUri = value; } @@ -112,7 +116,7 @@ public ValidationEventHandler EventHandler get { return (ValidationEventHandler)_eventHandling.EventHandler; } } - public SchemaInfo SchemaInfo + public SchemaInfo? SchemaInfo { get { @@ -124,7 +128,8 @@ public SchemaInfo SchemaInfo } } - public IDtdInfo DtdInfo + [DisallowNull] + public IDtdInfo? DtdInfo { get { @@ -132,11 +137,12 @@ public IDtdInfo DtdInfo } set { - SchemaInfo tmpSchemaInfo = value as SchemaInfo; + SchemaInfo? tmpSchemaInfo = value as SchemaInfo; if (tmpSchemaInfo == null) { throw new XmlException(SR.Xml_InternalError, string.Empty); } + this.schemaInfo = tmpSchemaInfo; } } @@ -157,13 +163,14 @@ public virtual void CompleteValidation() { } - public virtual object FindId(string name) + public virtual object? FindId(string name) { return null; } public void ValidateText() { + Debug.Assert(context != null); if (context.NeedValidateChildren) { if (context.IsNill) @@ -171,6 +178,7 @@ public void ValidateText() SendValidationEvent(SR.Sch_ContentInNill, XmlSchemaValidator.QNameString(context.LocalName, context.Namespace)); return; } + ContentValidator contentValidator = context.ElementDecl.ContentValidator; XmlSchemaContentType contentType = contentValidator.ContentType; if (contentType == XmlSchemaContentType.ElementOnly) @@ -190,6 +198,7 @@ public void ValidateText() { SendValidationEvent(SR.Sch_InvalidTextInEmpty, string.Empty); } + if (checkDatatype) { SaveTextValue(reader.Value); @@ -199,6 +208,7 @@ public void ValidateText() public void ValidateWhitespace() { + Debug.Assert(context != null); if (context.NeedValidateChildren) { XmlSchemaContentType contentType = context.ElementDecl.ContentValidator.ContentType; @@ -206,10 +216,12 @@ public void ValidateWhitespace() { SendValidationEvent(SR.Sch_ContentInNill, XmlSchemaValidator.QNameString(context.LocalName, context.Namespace)); } + if (contentType == XmlSchemaContentType.Empty) { SendValidationEvent(SR.Sch_InvalidWhitespaceInEmpty, string.Empty); } + if (checkDatatype) { SaveTextValue(reader.Value); @@ -219,17 +231,20 @@ public void ValidateWhitespace() private void SaveTextValue(string value) { + Debug.Assert(textString != null); if (textString.Length == 0) { textString = value; } else { + Debug.Assert(textValue != null); if (!hasSibling) { textValue.Append(textString); hasSibling = true; } + textValue.Append(value); } } @@ -278,8 +293,8 @@ protected void SendValidationEvent(XmlSchemaException e, XmlSeverityType severit protected static void ProcessEntity(SchemaInfo sinfo, string name, object sender, ValidationEventHandler eventhandler, string baseUri, int lineNumber, int linePosition) { - SchemaEntity en; - XmlSchemaException e = null; + SchemaEntity? en; + XmlSchemaException? e = null; if (!sinfo.GeneralEntities.TryGetValue(new XmlQualifiedName(name), out en)) { // validation error, see xml spec [68] @@ -289,6 +304,7 @@ protected static void ProcessEntity(SchemaInfo sinfo, string name, object sender { e = new XmlSchemaException(SR.Sch_UnparsedEntityRef, name, baseUri, lineNumber, linePosition); } + if (e != null) { if (eventhandler != null) @@ -304,8 +320,8 @@ protected static void ProcessEntity(SchemaInfo sinfo, string name, object sender protected static void ProcessEntity(SchemaInfo sinfo, string name, IValidationEventHandling eventHandling, string baseUriStr, int lineNumber, int linePosition) { - SchemaEntity en; - string errorResId = null; + SchemaEntity? en; + string? errorResId = null; if (!sinfo.GeneralEntities.TryGetValue(new XmlQualifiedName(name), out en)) { // validation error, see xml spec [68] @@ -330,7 +346,7 @@ protected static void ProcessEntity(SchemaInfo sinfo, string name, IValidationEv } } - public static BaseValidator CreateInstance(ValidationType valType, XmlValidatingReaderImpl reader, XmlSchemaCollection schemaCollection, IValidationEventHandling eventHandling, bool processIdentityConstraints) + public static BaseValidator? CreateInstance(ValidationType valType, XmlValidatingReaderImpl reader, XmlSchemaCollection schemaCollection, IValidationEventHandling eventHandling, bool processIdentityConstraints) { switch (valType) { @@ -352,6 +368,7 @@ public static BaseValidator CreateInstance(ValidationType valType, XmlValidating default: break; } + return null; } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/XmlSchemaInferenceException.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/XmlSchemaInferenceException.cs index cdcf3fec2d59b..6a93ab0365366 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/XmlSchemaInferenceException.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/XmlSchemaInferenceException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Resources; @@ -29,15 +30,15 @@ public XmlSchemaInferenceException() : base(null) { } - public XmlSchemaInferenceException(string message) : base(message, ((Exception)null), 0, 0) + public XmlSchemaInferenceException(string message) : base(message, ((Exception?)null), 0, 0) { } - public XmlSchemaInferenceException(string message, Exception innerException) : base(message, innerException, 0, 0) + public XmlSchemaInferenceException(string message, Exception? innerException) : base(message, innerException, 0, 0) { } - public XmlSchemaInferenceException(string message, Exception innerException, int lineNumber, int linePosition) : + public XmlSchemaInferenceException(string message, Exception? innerException, int lineNumber, int linePosition) : base(message, innerException, lineNumber, linePosition) { } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaSet.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaSet.cs index c071cdaf6a699..e9d9f7e9ad91f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaSet.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaSet.cs @@ -958,7 +958,7 @@ internal XmlSchema FindSchemaByNSAndUrl(Uri schemaUri, string ns, DictionaryEntr { return schema; } - else if (tns == string.Empty) + else if (tns.Length == 0) { //There could be a chameleon for same ns // It is OK to pass in the schema we have found so far, since it must have the schemaUri we're looking for // (we found it that way above) and it must be the original chameleon schema (the one without target ns) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaType.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaType.cs index 50e33a20c7625..c70077e05c69d 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaType.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.ComponentModel; using System.Xml.Serialization; @@ -13,15 +14,15 @@ namespace System.Xml.Schema /// public class XmlSchemaType : XmlSchemaAnnotated { - private string _name; + private string? _name; private XmlSchemaDerivationMethod _final = XmlSchemaDerivationMethod.None; private XmlSchemaDerivationMethod _derivedBy; - private XmlSchemaType _baseSchemaType; - private XmlSchemaDatatype _datatype; + private XmlSchemaType? _baseSchemaType; + private XmlSchemaDatatype? _datatype; private XmlSchemaDerivationMethod _finalResolved; - private volatile SchemaElementDecl _elementDecl; + private volatile SchemaElementDecl? _elementDecl; private volatile XmlQualifiedName _qname = XmlQualifiedName.Empty; - private XmlSchemaType _redefined; + private XmlSchemaType? _redefined; //compiled information private XmlSchemaContentType _contentType; @@ -35,6 +36,7 @@ public static XmlSchemaSimpleType GetBuiltInSimpleType(XmlQualifiedName qualifie { throw new ArgumentNullException(nameof(qualifiedName)); } + return DatatypeImplementation.GetSimpleTypeFromXsdType(qualifiedName); } @@ -49,32 +51,36 @@ public static XmlSchemaSimpleType GetBuiltInSimpleType(XmlTypeCode typeCode) /// /// [To be supplied.] /// - public static XmlSchemaComplexType GetBuiltInComplexType(XmlTypeCode typeCode) + public static XmlSchemaComplexType? GetBuiltInComplexType(XmlTypeCode typeCode) { if (typeCode == XmlTypeCode.Item) { return XmlSchemaComplexType.AnyType; } + return null; } /// /// [To be supplied.] /// - public static XmlSchemaComplexType GetBuiltInComplexType(XmlQualifiedName qualifiedName) + public static XmlSchemaComplexType? GetBuiltInComplexType(XmlQualifiedName qualifiedName) { if (qualifiedName == null) { throw new ArgumentNullException(nameof(qualifiedName)); } + if (qualifiedName.Equals(XmlSchemaComplexType.AnyType.QualifiedName)) { return XmlSchemaComplexType.AnyType; } + if (qualifiedName.Equals(XmlSchemaComplexType.UntypedAnyType.QualifiedName)) { return XmlSchemaComplexType.UntypedAnyType; } + return null; } @@ -82,7 +88,7 @@ public static XmlSchemaComplexType GetBuiltInComplexType(XmlQualifiedName qualif /// [To be supplied.] /// [XmlAttribute("name")] - public string Name + public string? Name { get { return _name; } set { _name = value; } @@ -121,7 +127,7 @@ public XmlSchemaDerivationMethod FinalResolved /// [XmlIgnore] [Obsolete("This property has been deprecated. Please use BaseXmlSchemaType property that returns a strongly typed base schema type. https://go.microsoft.com/fwlink/?linkid=14202")] - public object BaseSchemaType + public object? BaseSchemaType { get { @@ -132,6 +138,7 @@ public object BaseSchemaType { return _baseSchemaType.Datatype; } + return _baseSchemaType; } } @@ -140,7 +147,7 @@ public object BaseSchemaType /// [To be supplied.] /// [XmlIgnore] - public XmlSchemaType BaseXmlSchemaType + public XmlSchemaType? BaseXmlSchemaType { get { return _baseSchemaType; } } @@ -158,7 +165,7 @@ public XmlSchemaDerivationMethod DerivedBy /// [To be supplied.] /// [XmlIgnore] - public XmlSchemaDatatype Datatype + public XmlSchemaDatatype? Datatype { get { return _datatype; } } @@ -203,7 +210,7 @@ internal XmlValueConverter ValueConverter } } - internal XmlReader Validate(XmlReader reader, XmlResolver resolver, XmlSchemaSet schemaSet, ValidationEventHandler valEventHandler) + internal XmlReader? Validate(XmlReader reader, XmlResolver resolver, XmlSchemaSet schemaSet, ValidationEventHandler valEventHandler) { if (schemaSet != null) { @@ -213,6 +220,7 @@ internal XmlReader Validate(XmlReader reader, XmlResolver resolver, XmlSchemaSet readerSettings.ValidationEventHandler += valEventHandler; return new XsdValidatingReader(reader, resolver, readerSettings, this); } + return null; } @@ -249,14 +257,14 @@ internal void SetDatatype(XmlSchemaDatatype value) _datatype = value; } - internal SchemaElementDecl ElementDecl + internal SchemaElementDecl? ElementDecl { get { return _elementDecl; } set { _elementDecl = value; } } [XmlIgnore] - internal XmlSchemaType Redefined + internal XmlSchemaType? Redefined { get { return _redefined; } set { _redefined = value; } @@ -272,7 +280,7 @@ internal void SetContentType(XmlSchemaContentType value) _contentType = value; } - public static bool IsDerivedFrom(XmlSchemaType derivedType, XmlSchemaType baseType, XmlSchemaDerivationMethod except) + public static bool IsDerivedFrom(XmlSchemaType? derivedType, XmlSchemaType? baseType, XmlSchemaDerivationMethod except) { if (derivedType == null || baseType == null) { @@ -288,17 +296,19 @@ public static bool IsDerivedFrom(XmlSchemaType derivedType, XmlSchemaType baseTy { //Not checking for restriction blocked since all types are implicitly derived by restriction from xs:anyType return true; } + do { - XmlSchemaSimpleType dt = derivedType as XmlSchemaSimpleType; - XmlSchemaSimpleType bt = baseType as XmlSchemaSimpleType; + XmlSchemaSimpleType? dt = derivedType as XmlSchemaSimpleType; + XmlSchemaSimpleType? bt = baseType as XmlSchemaSimpleType; if (bt != null && dt != null) { //SimpleTypes if (bt == DatatypeImplementation.AnySimpleType) { //Not checking block=restriction return true; } - if ((except & derivedType.DerivedBy) != 0 || !dt.Datatype.IsDerivedFrom(bt.Datatype)) + + if ((except & derivedType.DerivedBy) != 0 || !dt.Datatype!.IsDerivedFrom(bt.Datatype)) { return false; } @@ -310,6 +320,7 @@ public static bool IsDerivedFrom(XmlSchemaType derivedType, XmlSchemaType baseTy { return false; } + derivedType = derivedType.BaseXmlSchemaType; if (derivedType == baseType) { @@ -332,7 +343,7 @@ internal static bool IsDerivedFromDatatype(XmlSchemaDatatype derivedDataType, Xm } [XmlIgnore] - internal override string NameAttribute + internal override string? NameAttribute { get { return Name; } set { Name = value; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaUse.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaUse.cs index b39996f93f58b..3f320dfdd3699 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaUse.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaUse.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { using System.Xml.Serialization; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs index d751e088b866d..00f3c76b63e99 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs @@ -735,6 +735,7 @@ public void GetUnspecifiedDefaultAttributes(ArrayList defaultAttributes) { throw new ArgumentNullException(nameof(defaultAttributes)); } + CheckStateTransition(ValidatorState.Attribute, "GetUnspecifiedDefaultAttributes"); GetUnspecifiedDefaultAttributes(defaultAttributes, false); } @@ -1066,6 +1067,7 @@ internal void GetUnspecifiedDefaultAttributes(ArrayList defaultAttributes, bool continue; } } + XmlSchemaDatatype datatype = attdef.Datatype; if (createNodeData) { @@ -1090,6 +1092,7 @@ internal void GetUnspecifiedDefaultAttributes(ArrayList defaultAttributes, bool { attrValidInfo.typedAttributeValue = attdef.DefaultValueTyped; } + attSchemaInfo.IsDefault = true; attSchemaInfo.Validity = XmlSchemaValidity.Valid; attSchemaInfo.SchemaType = attdef.SchemaType; @@ -1103,6 +1106,7 @@ internal void GetUnspecifiedDefaultAttributes(ArrayList defaultAttributes, bool { defaultAttributes.Add(attdef.SchemaAttribute); } + CheckTokenizedTypes(datatype, attdef.DefaultValueTyped, true); if (HasIdentityConstraints) { @@ -1111,7 +1115,6 @@ internal void GetUnspecifiedDefaultAttributes(ArrayList defaultAttributes, bool } } } - return; } internal XmlSchemaSet SchemaSet diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidity.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidity.cs index 6c3aaa9c82c27..2902fee222562 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidity.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidity.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { public enum XmlSchemaValidity diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSeverityType.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSeverityType.cs index d5d74ec1ab190..2fc305eff8e0d 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSeverityType.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSeverityType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { //UE Atention diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTokenizedType.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTokenizedType.cs index 9277fd46ce54c..26c3b874d8a50 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTokenizedType.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTokenizedType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml { // NOTE: Absolute numbering is utilized in DtdParser. -HelenaK diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTypeCode.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTypeCode.cs index 43ad4c8e3c98d..c39a138c968c5 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTypeCode.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlTypeCode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { public enum XmlTypeCode diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDuration.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDuration.cs index 9a73084017a7c..4567d8d119911 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDuration.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDuration.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Xml.Schema { using System; @@ -40,7 +41,7 @@ public enum DurationType Duration, YearMonthDuration, DayTimeDuration, - }; + } /// /// Construct an XsdDuration from component parts. @@ -143,11 +144,12 @@ public XsdDuration(string s) : this(s, DurationType.Duration) public XsdDuration(string s, DurationType durationType) { XsdDuration result; - Exception exception = TryParse(s, durationType, out result); + Exception? exception = TryParse(s, durationType, out result); if (exception != null) { throw exception; } + _years = result.Years; _months = result.Months; _days = result.Days; @@ -159,6 +161,7 @@ public XsdDuration(string s, DurationType durationType) { _nanoseconds |= NegativeBit; } + return; } @@ -242,22 +245,23 @@ public TimeSpan ToTimeSpan() public TimeSpan ToTimeSpan(DurationType durationType) { TimeSpan result; - Exception exception = TryToTimeSpan(durationType, out result); + Exception? exception = TryToTimeSpan(durationType, out result); if (exception != null) { throw exception; } + return result; } - internal Exception TryToTimeSpan(out TimeSpan result) + internal Exception? TryToTimeSpan(out TimeSpan result) { return TryToTimeSpan(DurationType.Duration, out result); } - internal Exception TryToTimeSpan(DurationType durationType, out TimeSpan result) + internal Exception? TryToTimeSpan(DurationType durationType, out TimeSpan result) { - Exception exception = null; + Exception? exception = null; ulong ticks = 0; // Throw error if result cannot fit into a long @@ -426,14 +430,14 @@ internal string ToString(DurationType durationType) return sb.ToString(); } - internal static Exception TryParse(string s, out XsdDuration result) + internal static Exception? TryParse(string s, out XsdDuration result) { return TryParse(s, DurationType.Duration, out result); } - internal static Exception TryParse(string s, DurationType durationType, out XsdDuration result) + internal static Exception? TryParse(string s, DurationType durationType, out XsdDuration result) { - string errorCode; + string? errorCode; int length; int value, pos, numDigits; Parts parts = Parts.HasNone; @@ -605,6 +609,7 @@ internal static Exception TryParse(string s, DurationType durationType, out XsdD if ((parts & ~(XsdDuration.Parts.HasYears | XsdDuration.Parts.HasMonths)) != 0) goto InvalidFormat; } + return null; InvalidFormat: @@ -619,7 +624,7 @@ internal static Exception TryParse(string s, DurationType durationType, out XsdD /// cntDigits. The integer is returned (0 if no digits). If the digits cannot fit into an Int32: /// 1. If eatDigits is true, then additional digits will be silently discarded (don't count towards numDigits) /// 2. If eatDigits is false, an overflow exception is thrown - private static string TryParseDigits(string s, ref int offset, bool eatDigits, out int result, out int numDigits) + private static string? TryParseDigits(string s, ref int offset, bool eatDigits, out int result, out int numDigits) { int offsetStart = offset; int offsetEnd = s.Length; diff --git a/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs b/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs index 83ac7b192991c..59a5320776db9 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs +++ b/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs @@ -7,6 +7,7 @@ using System.IO; using System.Xml.Schema; using System.Collections.Generic; +using System.Text; namespace System.Xml.Tests { @@ -1150,5 +1151,219 @@ public void TotalDigitsParseValue_Succeeds() ss.Compile(); } } + + #region tests causing XmlSchemaException with Sch_WhiteSpaceRestriction1 + public static IEnumerable WhiteSpaceRestriction1_Throws_TestData + { + get + { + return new List() + { + new object[] + { +@" + + + + + + + + + + + + +" + }, + new object[] + { +@" + + + + + + + + + + + + +" + } + }; + } + } + + [Theory] + [MemberData(nameof(WhiteSpaceRestriction1_Throws_TestData))] + public void WhiteSpaceRestriction1_Throws(string schema) + { + XmlSchemaSet ss = new XmlSchemaSet(); + using (StringReader sr = new StringReader(schema)) + using (XmlReader xmlrdr = XmlReader.Create(sr)) + { + ss.Add(null, xmlrdr); + } + + Exception ex = Assert.Throws(() => ss.Compile()); + + Assert.Contains("whiteSpace", ex.Message); + Assert.Contains("collapse", ex.Message); + Assert.Contains("preserve", ex.Message); + Assert.Contains("replace", ex.Message); + } + #endregion + + #region tests causing XmlSchemaException with Sch_WhiteSpaceRestriction2 + public static IEnumerable WhiteSpaceRestriction2_Throws_TestData + { + get + { + return new List() + { + new object[] + { +@" + + + + + + + + + + + + +" + } + }; + } + } + + [Theory] + [MemberData(nameof(WhiteSpaceRestriction2_Throws_TestData))] + public void WhiteSpaceRestriction2_Throws(string schema) + { + XmlSchemaSet ss = new XmlSchemaSet(); + using (StringReader sr = new StringReader(schema)) + using (XmlReader xmlrdr = XmlReader.Create(sr)) + { + ss.Add(null, xmlrdr); + } + + Exception ex = Assert.Throws(() => ss.Compile()); + + Assert.Contains("whiteSpace", ex.Message); + Assert.DoesNotContain("collapse", ex.Message); + Assert.Contains("preserve", ex.Message); + Assert.Contains("replace", ex.Message); + } + #endregion + + #region Attribute Restriction Invalid From WildCard tests + + public static IEnumerable AttributeRestrictionInvalidFromWildCard_Throws_TestData + { + get + { + return new List() + { + new object[] + { + @" + + + + + + + + + + + +" + }, + new object[] + { + @" + + + + + + + + + + + +" + } + }; + } + } + + [Theory] + [MemberData(nameof(AttributeRestrictionInvalidFromWildCard_Throws_TestData))] + public void AttributeRestrictionInvalidFromWildCard_Throws(string schema) + { + XmlSchemaSet ss = new XmlSchemaSet(); + ss.XmlResolver = new FakeXmlResolverAttributeRestriction(); + using (StringReader sr = new StringReader(schema)) + using (XmlReader xmlrdr = XmlReader.Create(sr)) + { + ss.Add(null, xmlrdr); + } + + Exception ex = Assert.Throws(() => ss.Compile()); + + Assert.Contains("wildcard", ex.Message); + Assert.Contains("redefine", ex.Message); + } + + private class FakeXmlResolverAttributeRestriction : XmlResolver + { + public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) + { + int uriIndex = int.Parse(absoluteUri.Host); + string[] schema = { @" + + + + + + + +", +@" + + + + + + + + +" + }; + + return new MemoryStream(Encoding.UTF8.GetBytes(schema[uriIndex])); + } + } + #endregion } } diff --git a/src/libraries/System.Private.Xml/tests/XmlWriter/DisposeTests.cs b/src/libraries/System.Private.Xml/tests/XmlWriter/DisposeTests.cs index 7701003b2c186..1c1c2ef314263 100644 --- a/src/libraries/System.Private.Xml/tests/XmlWriter/DisposeTests.cs +++ b/src/libraries/System.Private.Xml/tests/XmlWriter/DisposeTests.cs @@ -255,6 +255,11 @@ public override Task WriteAsync(char[] buffer, int offset, int count) { return Task.CompletedTask; } + + public override Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } } internal class AsyncOnlyStream : MemoryStream @@ -278,6 +283,11 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati { return Task.CompletedTask; } + + public override ValueTask WriteAsync(ReadOnlyMemory source, CancellationToken cancellationToken = default) + { + return default; + } } } } diff --git a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj index daeb3ca8b239b..c48dcba448478 100644 --- a/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj +++ b/src/libraries/System.Reflection.Context/src/System.Reflection.Context.csproj @@ -1,9 +1,11 @@ - Library - SR.PlatformNotSupported_ReflectionContext netstandard2.0;netstandard1.1;netstandard2.1 + + + SR.PlatformNotSupported_ReflectionContext + diff --git a/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj b/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj index 01e43ce383df2..93cbb7fb64f94 100644 --- a/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj +++ b/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj @@ -9,9 +9,9 @@ - SR.PlatformNotSupported_ReflectionDispatchProxy + SR.PlatformNotSupported_ReflectionDispatchProxy - + - + diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj index c9ea3bff48f62..48837d6105f25 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj +++ b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/libraries/System.Reflection.Emit.Lightweight/tests/DynamicMethodDefineParameter.cs b/src/libraries/System.Reflection.Emit.Lightweight/tests/DynamicMethodDefineParameter.cs index ad32c3d0bdfca..6334f8c62b7f5 100644 --- a/src/libraries/System.Reflection.Emit.Lightweight/tests/DynamicMethodDefineParameter.cs +++ b/src/libraries/System.Reflection.Emit.Lightweight/tests/DynamicMethodDefineParameter.cs @@ -43,6 +43,15 @@ public void DefineParameter_SetsParameterCorrectly() Assert.Equal(ParameterAttributes.In, parameters[0].Attributes); Assert.Equal(ParameterAttributes.Out, parameters[1].Attributes); + + if (!PlatformDetection.IsMonoRuntime) // [ActiveIssue("https://github.com/dotnet/runtime/issues/36271")] + { + Assert.Empty(parameters[0].GetRequiredCustomModifiers()); + Assert.Empty(parameters[1].GetRequiredCustomModifiers()); + + Assert.Empty(parameters[0].GetOptionalCustomModifiers()); + Assert.Empty(parameters[1].GetOptionalCustomModifiers()); + } } } } diff --git a/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderToString.cs b/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderToString.cs index a00d42e12c25f..22ef09f782522 100644 --- a/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderToString.cs +++ b/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderToString.cs @@ -9,7 +9,6 @@ namespace System.Reflection.Emit.Tests public class ConstructorBuilderToString { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)] public void ToString_NullRequiredOptionalCustomModifiers() { TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); diff --git a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs index 920dc871b5867..5e2b570c2bbc7 100644 --- a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs +++ b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineEnum.cs @@ -161,7 +161,6 @@ public void DefineEnum_VoidUnderlyingType_ThrowsArgumentException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)] public void DefineEnum_ByRefUnderlyingType_ThrowsCOMExceptionOnCreation() { ModuleBuilder module = Helpers.DynamicModule(); diff --git a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineType.cs b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineType.cs index fe52f133e5b5c..844dcb8d18119 100644 --- a/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineType.cs +++ b/src/libraries/System.Reflection.Emit/tests/ModuleBuilder/ModuleBuilderDefineType.cs @@ -33,7 +33,6 @@ public static IEnumerable TestData() } [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)] [MemberData(nameof(TestData))] public void DefineType(string name, TypeAttributes attributes, Type parent, PackingSize packingSize, int typesize, Type[] implementedInterfaces) { diff --git a/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs b/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs index f3ca59bbca687..5464877b54c54 100644 --- a/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs +++ b/src/libraries/System.Reflection.Extensions/tests/RuntimeReflectionExtensionTests.cs @@ -165,7 +165,7 @@ public void GetRuntimeEvent() }); - Assert.Throws(null, () => + Assert.Throws("name", () => { typeof(RuntimeReflectionExtensionsTests).GetRuntimeEvent(null); }); diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index 2ace8896347f8..a60521d62461b 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -3,10 +3,13 @@ true en-US false - netstandard1.1;portable-net45+win8 $(NetCoreAppCurrent);netstandard1.1;netstandard2.0 true enable + + + + netstandard1.1;portable-net45+win8 - + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj index 21c96c0c49de0..e200da5e03283 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -1,11 +1,10 @@ - System.Reflection.MetadataLoadContext System.Reflection true $(NoWarn);CS1573 - netcoreapp3.0;netstandard2.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netcoreapp3.0;netstandard2.0 true enable diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs index ea73a31460503..b88f8a42fc3e8 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs @@ -192,9 +192,14 @@ private RoType[] ComputeInterfaceClosure() } } - // todo: use IEnumerable extension: return ifcs.ToArray() - List list = new List(ifcs); - return list.ToArray(); + if (ifcs.Count == 0) + { + return Array.Empty(); + } + + var arr = new RoType[ifcs.Count]; + ifcs.CopyTo(arr); + return arr; } private volatile RoType[]? _lazyInterfaces; diff --git a/src/libraries/System.Reflection/tests/MethodInfoTests.cs b/src/libraries/System.Reflection/tests/MethodInfoTests.cs index 9906b28601ffc..37e16ac8748cf 100644 --- a/src/libraries/System.Reflection/tests/MethodInfoTests.cs +++ b/src/libraries/System.Reflection/tests/MethodInfoTests.cs @@ -26,21 +26,41 @@ public void CreateDelegate_PublicMethod() object returnValue = ((Delegate_TC_Int)methodDelegate).DynamicInvoke(new object[] { baseClass }); Assert.Equal(baseClass.VirtualMethod(), returnValue); + Delegate genMethodDelegate = virtualMethodInfo.CreateDelegate(); + object genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { baseClass }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = privateInstanceMethodInfo.CreateDelegate(typeof(Delegate_TC_Int)); returnValue = ((Delegate_TC_Int)methodDelegate).DynamicInvoke(new object[] { baseClass }); Assert.Equal(21, returnValue); + genMethodDelegate = privateInstanceMethodInfo.CreateDelegate(); + genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { baseClass }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = virtualMethodInfo.CreateDelegate(typeof(Delegate_Void_Int), baseClass); returnValue = ((Delegate_Void_Int)methodDelegate).DynamicInvoke(null); Assert.Equal(baseClass.VirtualMethod(), returnValue); + genMethodDelegate = virtualMethodInfo.CreateDelegate(baseClass); + genReturnValue = genMethodDelegate.DynamicInvoke(null); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = publicStaticMethodInfo.CreateDelegate(typeof(Delegate_Str_Str)); returnValue = ((Delegate_Str_Str)methodDelegate).DynamicInvoke(new object[] { "85" }); Assert.Equal("85", returnValue); + genMethodDelegate = publicStaticMethodInfo.CreateDelegate(); + genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { "85" }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = publicStaticMethodInfo.CreateDelegate(typeof(Delegate_Void_Str), "93"); returnValue = ((Delegate_Void_Str)methodDelegate).DynamicInvoke(null); Assert.Equal("93", returnValue); + + genMethodDelegate = publicStaticMethodInfo.CreateDelegate("93"); + genReturnValue = genMethodDelegate.DynamicInvoke(null); + Assert.Equal(returnValue, genReturnValue); } [Fact] @@ -57,9 +77,17 @@ public void CreateDelegate_InheritedMethod() object returnValue = ((Delegate_TC_Int)methodDelegate).DynamicInvoke(new object[] { testSubClass }); Assert.Equal(testSubClass.VirtualMethod(), returnValue); + Delegate genMethodDelegate = virtualMethodInfo.CreateDelegate(); + object genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { testSubClass }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = virtualMethodInfo.CreateDelegate(typeof(Delegate_Void_Int), testSubClass); returnValue = ((Delegate_Void_Int)methodDelegate).DynamicInvoke(); Assert.Equal(testSubClass.VirtualMethod(), returnValue); + + genMethodDelegate = virtualMethodInfo.CreateDelegate(testSubClass); + genReturnValue = genMethodDelegate.DynamicInvoke(); + Assert.Equal(returnValue, genReturnValue); } [Fact] @@ -78,17 +106,33 @@ public void CreateDelegate_GenericMethod() object returnValue = ((Delegate_GC_T_T)methodDelegate).DynamicInvoke(new object[] { genericClass, "TestGeneric" }); Assert.Equal(genericClass.GenericMethod1("TestGeneric"), returnValue); + Delegate genMethodDelegate = miMethod1String.CreateDelegate>(); + object genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { genericClass, "TestGeneric" }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = miMethod1String.CreateDelegate(typeof(Delegate_T_T), genericClass); returnValue = ((Delegate_T_T)methodDelegate).DynamicInvoke(new object[] { "TestGeneric" }); Assert.Equal(genericClass.GenericMethod1("TestGeneric"), returnValue); + genMethodDelegate = miMethod1String.CreateDelegate>(genericClass); + genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { "TestGeneric" }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = miMethod2IntGeneric.CreateDelegate(typeof(Delegate_T_T)); returnValue = ((Delegate_T_T)methodDelegate).DynamicInvoke(new object[] { 58 }); Assert.Equal(58, returnValue); + genMethodDelegate = miMethod2IntGeneric.CreateDelegate>(); + genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { 58 }); + Assert.Equal(returnValue, genReturnValue); + methodDelegate = miMethod2StringGeneric.CreateDelegate(typeof(Delegate_Void_T), "firstArg"); returnValue = ((Delegate_Void_T)methodDelegate).DynamicInvoke(); Assert.Equal("firstArg", returnValue); + + genMethodDelegate = miMethod2StringGeneric.CreateDelegate>("firstArg"); + genReturnValue = genMethodDelegate.DynamicInvoke(); + Assert.Equal(returnValue, genReturnValue); } [Fact] @@ -100,6 +144,10 @@ public void CreateDelegate_ValueTypeParameters() Delegate methodDelegate = miPublicStructMethod.CreateDelegate(typeof(Delegate_DateTime_Str)); object returnValue = ((Delegate_DateTime_Str)methodDelegate).DynamicInvoke(new object[] { testClass, null }); Assert.Equal(testClass.PublicStructMethod(new DateTime()), returnValue); + + Delegate genMethodDelegate = miPublicStructMethod.CreateDelegate(); + object genReturnValue = genMethodDelegate.DynamicInvoke(new object[] { testClass, null }); + Assert.Equal(returnValue, genReturnValue); } [Theory] diff --git a/src/libraries/System.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs index 9d6d9fdbb8890..40c484c13381a 100644 --- a/src/libraries/System.Reflection/tests/TypeInfoTests.cs +++ b/src/libraries/System.Reflection/tests/TypeInfoTests.cs @@ -471,10 +471,10 @@ public static void IsEnumDefined(object value, bool expected) } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/15028", TestRuntimes.Mono)] public void IsEnumDefined_Invalid() { - AssertExtensions.Throws("", () => typeof(NonGenericClassWithNoInterfaces).GetTypeInfo().IsEnumDefined(10)); + AssertExtensions.Throws("enumType", () => typeof(NonGenericClassWithNoInterfaces).GetTypeInfo().IsEnumDefined(10)); + AssertExtensions.Throws("enumType", () => typeof(NonGenericClassWithNoInterfaces).GetTypeInfo().IsEnumDefined("10")); Assert.Throws(() => typeof(IntEnum).GetTypeInfo().IsEnumDefined(null)); Assert.Throws(() => typeof(IntEnum).GetTypeInfo().IsEnumDefined(new NonGenericClassWithNoInterfaces())); } diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs index 3dcbf43fecb9c..ffb420c4f7238 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCache.cs @@ -344,7 +344,7 @@ public MemoryCache(string name, NameValueCollection config = null) { throw new ArgumentNullException(nameof(name)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Empty_string_invalid, nameof(name)); } @@ -364,7 +364,7 @@ public MemoryCache(string name, NameValueCollection config, bool ignoreConfigSec { throw new ArgumentNullException(nameof(name)); } - if (name == string.Empty) + if (name.Length == 0) { throw new ArgumentException(SR.Empty_string_invalid, nameof(name)); } diff --git a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching.Tests.csproj b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching.Tests.csproj index d666431543e62..8259713ac2060 100644 --- a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching.Tests.csproj +++ b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-Windows_NT;$(NetFrameworkCurrent) + $(NetCoreAppCurrent);$(NetFrameworkCurrent) diff --git a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/MemoryCacheTest.cs b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/MemoryCacheTest.cs index 71254a10928ff..b114698730101 100644 --- a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/MemoryCacheTest.cs +++ b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/MemoryCacheTest.cs @@ -969,7 +969,8 @@ public void ChangeMonitors() } // Due to internal implementation details Trim has very few easily verifiable scenarios - [Fact] + // ActiveIssue: https://github.com/dotnet/runtime/issues/36488 + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArm64Process))] public void Trim() { var config = new NameValueCollection(); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs index 3ea51bf15b4cf..5129caf6dc8e8 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs @@ -132,9 +132,9 @@ public void OSVersion_ValidVersion() Assert.Contains(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Windows" : "Unix", versionString); } - // On Unix, we must parse the version from uname -r + // On non-OSX Unix, we must parse the version from uname -r [Theory] - [PlatformSpecific(TestPlatforms.AnyUnix)] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.OSX)] [InlineData("2.6.19-1.2895.fc6", 2, 6, 19, 1)] [InlineData("xxx1yyy2zzz3aaa4bbb", 1, 2, 3, 4)] [InlineData("2147483647.2147483647.2147483647.2147483647", int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue)] @@ -154,6 +154,19 @@ public void OSVersion_ParseVersion(string input, int major, int minor, int build Assert.Equal(expected, actual); } + [Fact] + [PlatformSpecific(TestPlatforms.OSX)] + public void OSVersion_ValidVersion_OSX() + { + Version version = Environment.OSVersion.Version; + + // verify that the Environment.OSVersion.Version matches the current RID + Assert.Contains(version.ToString(2), RuntimeInformation.RuntimeIdentifier); + + Assert.True(version.Build >= 0, "OSVersion Build should be non-negative"); + Assert.Equal(-1, version.Revision); // Revision is never set on OSX + } + [Fact] public void SystemPageSize_Valid() { diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs index dc0fd48a6297e..6d618f756c7ff 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs @@ -52,6 +52,7 @@ public void GetDirectoryName_CurrentDirectory() Assert.Equal(curDir, Path.GetDirectoryName(Path.Combine(curDir, "baz"))); Assert.Null(Path.GetDirectoryName(Path.GetPathRoot(curDir))); + Assert.True(Path.GetDirectoryName(Path.GetPathRoot(curDir.AsSpan())).IsEmpty); } [Fact] @@ -108,10 +109,16 @@ public void GetPathRoot_Null() public void GetPathRoot_Basic() { string cwd = Directory.GetCurrentDirectory(); - Assert.Equal(cwd.Substring(0, cwd.IndexOf(Path.DirectorySeparatorChar) + 1), Path.GetPathRoot(cwd)); + string substring = cwd.Substring(0, cwd.IndexOf(Path.DirectorySeparatorChar) + 1); + + Assert.Equal(substring, Path.GetPathRoot(cwd)); + PathAssert.Equal(substring.AsSpan(), Path.GetPathRoot(cwd.AsSpan())); + Assert.True(Path.IsPathRooted(cwd)); Assert.Equal(string.Empty, Path.GetPathRoot(@"file.exe")); + Assert.True(Path.GetPathRoot(@"file.exe".AsSpan()).IsEmpty); + Assert.False(Path.IsPathRooted("file.exe")); } @@ -417,6 +424,7 @@ public void GetInvalidPathChars() Assert.EndsWith(bad, Path.GetFullPath(bad)); } Assert.Equal(string.Empty, Path.GetPathRoot(bad)); + Assert.True(Path.GetPathRoot(bad.AsSpan()).IsEmpty); Assert.False(Path.IsPathRooted(bad)); }); } @@ -431,7 +439,7 @@ public void GetInvalidPathChars_Span() Assert.Equal(string.Empty, new string(Path.GetExtension(bad.AsSpan()))); Assert.Equal(bad, new string(Path.GetFileName(bad.AsSpan()))); Assert.Equal(bad, new string(Path.GetFileNameWithoutExtension(bad.AsSpan()))); - Assert.Equal(string.Empty, new string(Path.GetPathRoot(bad.AsSpan()))); + Assert.True(Path.GetPathRoot(bad.AsSpan()).IsEmpty); Assert.False(Path.IsPathRooted(bad.AsSpan())); }); } diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs index 39e3edb01eae8..7f57a8d659ced 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Unix.cs @@ -19,6 +19,7 @@ public static void GetPathRoot(string value, string expected) // UNCs and device paths have no special meaning in Unix _ = expected; Assert.Empty(Path.GetPathRoot(value)); + Assert.True(Path.GetPathRoot(value.AsSpan()).IsEmpty); } [Theory, @@ -115,13 +116,44 @@ public void GetFullPath_Unix_Whitespace() { @"../../../tmp/bar/..", @"/home/git", @"/tmp" }, { @"../../././tmp/..", @"/home/git", @"/" }, { @"././../../../", @"/home/git", @"/" }, + { @"../tmp/../..", @"/home", @"/" } }; [Theory, MemberData(nameof(GetFullPath_BasePath_BasicExpansions_TestData_Unix))] public static void GetFullPath_BasicExpansions_Unix(string path, string basePath, string expected) { - Assert.Equal(expected, Path.GetFullPath(path, basePath)); + string fullPath = Path.GetFullPath(path, basePath); + Assert.Equal(expected, fullPath); + } + + [Theory] + [InlineData(@"/../../.././tmp/..")] + [InlineData(@"/../../../")] + [InlineData(@"/../../../tmp/bar/..")] + [InlineData(@"/../.././././bar/../../../")] + [InlineData(@"/../../././tmp/..")] + [InlineData(@"/../../tmp/../../")] + [InlineData(@"/../../tmp/bar/..")] + [InlineData(@"/../tmp/../..")] + [InlineData(@"/././../../../../")] + [InlineData(@"/././../../../")] + [InlineData(@"/./././bar/../../../")] + [InlineData(@"/")] + [InlineData(@"/bar")] + [InlineData(@"/bar/././././../../..")] + [InlineData(@"/bar/tmp")] + [InlineData(@"/tmp/..")] + [InlineData(@"/tmp/../../../../../bar")] + [InlineData(@"/tmp/../../../bar")] + [InlineData(@"/tmp/../bar/../..")] + [InlineData(@"/tmp/bar")] + [InlineData(@"/tmp/bar/..")] + public static void GePathRoot_Unix(string path) + { + string expected = @"/"; + Assert.Equal(expected, Path.GetPathRoot(path)); + PathAssert.Equal(expected.AsSpan(), Path.GetPathRoot(path.AsSpan())); } [Fact] diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Math.cs b/src/libraries/System.Runtime.Extensions/tests/System/Math.cs index 7614d2b31555e..c2b43c8d8ec4d 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/Math.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/Math.cs @@ -1749,6 +1749,41 @@ public static void BigMul() Assert.Equal(0L, Math.BigMul(0, 0)); } + [Theory] + [InlineData(0U, 0U, "00000000000000000000000000000000")] + [InlineData(0U, 1U, "00000000000000000000000000000000")] + [InlineData(1U, 0U, "00000000000000000000000000000000")] + [InlineData(2U, 3U, "00000000000000000000000000000006")] + [InlineData(ulong.MaxValue, 2, "0000000000000001FFFFFFFFFFFFFFFE")] + [InlineData(ulong.MaxValue, 1, "0000000000000000FFFFFFFFFFFFFFFF")] + [InlineData(ulong.MaxValue, ulong.MaxValue, "FFFFFFFFFFFFFFFE0000000000000001")] + [InlineData(ulong.MaxValue, 3, "0000000000000002FFFFFFFFFFFFFFFD")] + [InlineData(0xE8FAF08929B46BB5, 0x26B442D59782BA17, "23394CF8915296631EB6255F4A612F43")] + public static void BigMul128_Unsigned(ulong a, ulong b, string result) + { + ulong high = Math.BigMul(a, b, out ulong low); + Assert.Equal(result, high.ToString("X16") + low.ToString("X16")); + } + + [Theory] + [InlineData(0L, 0L, "00000000000000000000000000000000")] + [InlineData(0L, 1L, "00000000000000000000000000000000")] + [InlineData(1L, 0L, "00000000000000000000000000000000")] + [InlineData(2L, 3L, "00000000000000000000000000000006")] + [InlineData(3L, -2L, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA")] + [InlineData(-1L, -1L, "00000000000000000000000000000001")] + [InlineData(-1L, long.MinValue, "00000000000000008000000000000000")] + [InlineData(1L, long.MinValue, "FFFFFFFFFFFFFFFF8000000000000000")] + [InlineData(0x7DD8FD06E61C42C7, 0x23B8308969A5D354, "118F366A0AEB79CDB340AA067592EE4C")] + [InlineData(0x6DACB8FC835F41B5, -0x2D90EF8C7ED29BBA, "EC7A8BB31D6035AD27742486E387AB7E")] + [InlineData(-0x166FA7C456154C28, 0x13CF93153370AB0B, "FE43855FCCDA31541A45864AC9B70248")] + [InlineData(-0x57A14FB8778E4F94, -0x33BDC4C7D41A44C9, "11B61855830A65CBA363C1FE50E7CB34")] + public static void BigMul128_Signed(long a, long b, string result) + { + long high = Math.BigMul(a, b, out long low); + Assert.Equal(result, high.ToString("X16") + low.ToString("X16")); + } + [Theory] [InlineData(1073741, 2147483647, 2000, 1647)] [InlineData(6, 13952, 2000, 1952)] diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index d2a0de7091b94..24d334cdf0f48 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -181,9 +181,9 @@ public partial class ComAwareEventInfo : System.Reflection.EventInfo public override System.Reflection.Module Module { get { throw null; } } public override string Name { get { throw null; } } public override System.Type? ReflectedType { get { throw null; } } -#pragma warning disable CS8610 +#pragma warning disable CS8765 // Nullability of parameters 'target' and 'handler' don't match overridden member public override void AddEventHandler(object target, System.Delegate handler) { } -#pragma warning restore CS8610 +#pragma warning restore CS8765 public override System.Reflection.MethodInfo? GetAddMethod(bool nonPublic) { throw null; } public override object[] GetCustomAttributes(bool inherit) { throw null; } public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; } @@ -192,9 +192,9 @@ public partial class ComAwareEventInfo : System.Reflection.EventInfo public override System.Reflection.MethodInfo? GetRaiseMethod(bool nonPublic) { throw null; } public override System.Reflection.MethodInfo? GetRemoveMethod(bool nonPublic) { throw null; } public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; } -#pragma warning disable CS8610 +#pragma warning disable CS8765 // Nullability of parameters 'target' and 'handler' don't match overridden member public override void RemoveEventHandler(object target, System.Delegate handler) { } -#pragma warning restore CS8610 +#pragma warning restore CS8765 } [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, Inherited=false)] public sealed partial class ComCompatibleVersionAttribute : System.Attribute diff --git a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs index 3985477bb627d..dced7924e7109 100644 --- a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs @@ -20,7 +20,9 @@ public ComAwareEventInfo(Type type, string eventName) _innerEventInfo = type.GetEvent(eventName)!; } +#pragma warning disable CS8765 // Nullability of parameters 'target' and 'handler' don't match overridden member public override void AddEventHandler(object target, Delegate handler) +#pragma warning restore CS8765 { if (Marshal.IsComObject(target)) { @@ -35,7 +37,9 @@ public override void AddEventHandler(object target, Delegate handler) } } +#pragma warning disable CS8765 // Nullability of parameters 'target' and 'handler' don't match overridden member public override void RemoveEventHandler(object target, Delegate handler) +#pragma warning restore CS8765 { if (Marshal.IsComObject(target)) { diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs index f3513d414c075..243133c3b3cb0 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs @@ -39,7 +39,7 @@ public void Ctor_NullType_ThrowsNullReferenceException() [Fact] public void Ctor_NullEventName_ThrowsArgumentNullException() { - AssertExtensions.Throws(null, () => new ComAwareEventInfo(typeof(NonComObject), null)); + AssertExtensions.Throws("name", () => new ComAwareEventInfo(typeof(NonComObject), null)); } [Fact] diff --git a/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs b/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs index 181e20a22c3ca..68ce7894c11b7 100644 --- a/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs +++ b/src/libraries/System.Runtime.Intrinsics.Experimental/ref/System.Runtime.Intrinsics.Experimental.cs @@ -96,6 +96,18 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector64 Add(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Add(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Add(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 AddPairwise(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 AddPairwise(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 AddPairwise(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } @@ -127,30 +139,18 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector64 AddPairwiseWideningAndAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 AddPairwiseWideningScalar(System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 AddPairwiseWideningScalar(System.Runtime.Intrinsics.Vector64 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 AddReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 AddReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 AddRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 AddRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 AddSaturate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 AddSaturate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 AddSaturate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -341,6 +341,48 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector64 CompareTest(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 DivideScalar(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 DivideScalar(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateSelectedScalarToVector64(System.Runtime.Intrinsics.Vector64 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(byte value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(short value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(int value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(sbyte value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(float value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(ushort value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(uint value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(byte value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(short value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(int value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(sbyte value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(float value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(ushort value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 DuplicateToVector64(uint value) { throw null; } public static byte Extract(System.Runtime.Intrinsics.Vector128 vector, byte index) { throw null; } public static double Extract(System.Runtime.Intrinsics.Vector128 vector, byte index) { throw null; } public static short Extract(System.Runtime.Intrinsics.Vector128 vector, byte index) { throw null; } @@ -358,18 +400,18 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static float Extract(System.Runtime.Intrinsics.Vector64 vector, byte index) { throw null; } public static ushort Extract(System.Runtime.Intrinsics.Vector64 vector, byte index) { throw null; } public static uint Extract(System.Runtime.Intrinsics.Vector64 vector, byte index) { throw null; } - public static System.Runtime.Intrinsics.Vector128 ExtractAndNarrowHigh(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector128 ExtractAndNarrowHigh(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector128 ExtractAndNarrowHigh(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector128 ExtractAndNarrowHigh(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector128 ExtractAndNarrowHigh(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector128 ExtractAndNarrowHigh(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 ExtractAndNarrowLow(System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 ExtractAndNarrowLow(System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 ExtractAndNarrowLow(System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 ExtractAndNarrowLow(System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 ExtractAndNarrowLow(System.Runtime.Intrinsics.Vector128 value) { throw null; } - public static System.Runtime.Intrinsics.Vector64 ExtractAndNarrowLow(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ExtractNarrowingLower(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ExtractNarrowingLower(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ExtractNarrowingLower(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ExtractNarrowingLower(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ExtractNarrowingLower(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ExtractNarrowingLower(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ExtractNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ExtractNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ExtractNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ExtractNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ExtractNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ExtractNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 ExtractVector128(System.Runtime.Intrinsics.Vector128 upper, System.Runtime.Intrinsics.Vector128 lower, byte index) { throw null; } public static System.Runtime.Intrinsics.Vector128 ExtractVector128(System.Runtime.Intrinsics.Vector128 upper, System.Runtime.Intrinsics.Vector128 lower, byte index) { throw null; } public static System.Runtime.Intrinsics.Vector128 ExtractVector128(System.Runtime.Intrinsics.Vector128 upper, System.Runtime.Intrinsics.Vector128 lower, byte index) { throw null; } @@ -690,6 +732,10 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector128 PolynomialMultiply(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 PolynomialMultiply(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 PolynomialMultiply(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningLower(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningLower(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningUpper(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningUpper(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 PopCount(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 PopCount(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 PopCount(System.Runtime.Intrinsics.Vector64 value) { throw null; } @@ -706,6 +752,327 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector64 ReciprocalSquareRootStep(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 ReciprocalStep(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 ReciprocalStep(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmetic(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmetic(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmetic(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmetic(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsigned(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningLower(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningLower(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningLower(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningLower(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningLower(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningLower(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningUpper(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningUpper(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningUpper(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningUpper(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningUpper(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLeftLogicalWideningUpper(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogical(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogical(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogical(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogical(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogical(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogical(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogical(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRounded(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturate(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticNarrowingSaturateUnsignedUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmeticRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRounded(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector128 addend, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAdd(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedAddScalar(System.Runtime.Intrinsics.Vector64 addend, System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SignExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SignExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SignExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SignExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SignExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SignExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 SqrtScalar(System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 SqrtScalar(System.Runtime.Intrinsics.Vector64 value) { throw null; } public unsafe static void Store(byte* address, System.Runtime.Intrinsics.Vector128 source) { } @@ -744,30 +1111,30 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector64 Subtract(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Subtract(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Subtract(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector64 SubtractReturningRoundedHighNarrowLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } - public static System.Runtime.Intrinsics.Vector128 SubtractReturningRoundedHighNarrowUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 SubtractRoundedHighNarrowingLower(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SubtractRoundedHighNarrowingUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 SubtractSaturate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 SubtractSaturate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 SubtractSaturate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -836,6 +1203,18 @@ public abstract partial class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector64 Xor(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Xor(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Xor(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningLower(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) { throw null; } public new abstract partial class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64 { internal Arm64() { } @@ -933,6 +1312,12 @@ public new abstract partial class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase. public static System.Runtime.Intrinsics.Vector128 Divide(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Divide(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Divide(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateSelectedScalarToVector128(System.Runtime.Intrinsics.Vector128 value, byte index) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(double value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(long value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DuplicateToVector128(ulong value) { throw null; } public static System.Runtime.Intrinsics.Vector128 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector128 acc, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 FusedMultiplySubtract(System.Runtime.Intrinsics.Vector128 acc, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Max(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -1024,6 +1409,57 @@ public new abstract partial class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase. public static System.Runtime.Intrinsics.Vector128 ReverseElementBits(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 ReverseElementBits(System.Runtime.Intrinsics.Vector64 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 ReverseElementBits(System.Runtime.Intrinsics.Vector64 value) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftArithmeticSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLeftLogicalSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalRoundedSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftLogicalSaturateScalar(System.Runtime.Intrinsics.Vector64 value, System.Runtime.Intrinsics.Vector64 count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticNarrowingSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, byte count) { throw null; } public static System.Runtime.Intrinsics.Vector128 Sqrt(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 Sqrt(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector64 Sqrt(System.Runtime.Intrinsics.Vector64 value) { throw null; } @@ -1151,6 +1587,10 @@ public abstract partial class Aes : System.Runtime.Intrinsics.Arm.ArmBase public static System.Runtime.Intrinsics.Vector128 Encrypt(System.Runtime.Intrinsics.Vector128 value, System.Runtime.Intrinsics.Vector128 roundKey) { throw null; } public static System.Runtime.Intrinsics.Vector128 InverseMixColumns(System.Runtime.Intrinsics.Vector128 value) { throw null; } public static System.Runtime.Intrinsics.Vector128 MixColumns(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningLower(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningLower(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningUpper(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningUpper(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } } [System.CLSCompliantAttribute(false)] public abstract partial class ArmBase @@ -1161,7 +1601,6 @@ public abstract partial class ArmBase public static int LeadingZeroCount(uint value) { throw null; } public static int ReverseElementBits(int value) { throw null; } public static uint ReverseElementBits(uint value) { throw null; } - public abstract partial class Arm64 { internal Arm64() { } @@ -1170,7 +1609,7 @@ public abstract partial class Arm64 public static int LeadingSignCount(long value) { throw null; } public static int LeadingZeroCount(long value) { throw null; } public static int LeadingZeroCount(ulong value) { throw null; } - public static long ReverseElementBits(long value) { throw null; } + public static long ReverseElementBits(long value) { throw null; } public static ulong ReverseElementBits(ulong value) { throw null; } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index 123453cdfaf21..494b0531dcb36 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -1477,7 +1477,7 @@ public string ToString(string? format, IFormatProvider? provider) return BigNumber.FormatBigInteger(this, format, NumberFormatInfo.GetInstance(provider)); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) // TODO: change format to ReadOnlySpan + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) { return BigNumber.TryFormatBigInteger(this, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten); } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs index 845a0686ad232..8570965d0272c 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs @@ -1614,9 +1614,9 @@ internal TypeLoadExceptionHolder(string? typeName) internal static class SerializationInfoExtensions { private static readonly Action s_updateValue = - (Action)typeof(SerializationInfo) + typeof(SerializationInfo) .GetMethod("UpdateValue", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)! - .CreateDelegate(typeof(Action)); + .CreateDelegate>(); public static void UpdateValue(this SerializationInfo si, string name, object value, Type type) => s_updateValue(si, name, value, type); diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs index bd194c39816dd..7eb55502786bb 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs @@ -82,7 +82,7 @@ private static void InvokeOnDelegate(object obj, StreamingContext context, List< { foreach (MethodInfo m in methods) { - SerializationEventHandler onDeserialized = (SerializationEventHandler)m.CreateDelegate(typeof(SerializationEventHandler), obj); + SerializationEventHandler onDeserialized = m.CreateDelegate(obj); handler = (SerializationEventHandler)Delegate.Combine(handler, onDeserialized); } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SurrogateSelector.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SurrogateSelector.cs index 0b73a24dc39e3..940d5e7c37ead 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SurrogateSelector.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SurrogateSelector.cs @@ -213,9 +213,10 @@ internal SurrogateHashtable(int size) : base(size) // is a subset of the context for which the serialization selector is provided (presentContext) // Note: This is done by overriding KeyEquals rather than overriding Equals() in the SurrogateKey // class because Equals() method must be commutative. -#pragma warning disable CS8610 + // n.b. 'key' and 'item' parameter positions swapped from base method! +#pragma warning disable CS8765 // Nullability of parameter 'key' doesn't match overridden member protected override bool KeyEquals(object key, object item) -#pragma warning restore CS8610 +#pragma warning restore CS8765 { SurrogateKey givenValue = (SurrogateKey)item; SurrogateKey presentValue = (SurrogateKey)key; diff --git a/src/libraries/System.Runtime.WindowsRuntime/src/System/IO/StreamOperationsImplementation.cs b/src/libraries/System.Runtime.WindowsRuntime/src/System/IO/StreamOperationsImplementation.cs index 9414d9f042cc2..5fd829c8ed949 100644 --- a/src/libraries/System.Runtime.WindowsRuntime/src/System/IO/StreamOperationsImplementation.cs +++ b/src/libraries/System.Runtime.WindowsRuntime/src/System/IO/StreamOperationsImplementation.cs @@ -111,7 +111,7 @@ internal static class StreamOperationsImplementation try { // Read asynchronously: - bytesRead = await stream.ReadAsync(data!, offset + bytesCompleted, bytesRequested - bytesCompleted, cancelToken) + bytesRead = await stream.ReadAsync(data!.AsMemory(offset + bytesCompleted, bytesRequested - bytesCompleted), cancelToken) .ConfigureAwait(continueOnCapturedContext: false); // We will continue here on a different thread when read async completed: @@ -181,7 +181,7 @@ internal static class StreamOperationsImplementation int bytesToWrite = (int)buffer.Length; - await stream.WriteAsync(data, offset, bytesToWrite, cancelToken).ConfigureAwait(continueOnCapturedContext: false); + await stream.WriteAsync(data.AsMemory(offset, bytesToWrite), cancelToken).ConfigureAwait(continueOnCapturedContext: false); if (progressListener != null) progressListener.Report((uint)bytesToWrite); diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 040f2cbeed453..2aac15f3deca6 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -354,7 +354,7 @@ public abstract partial class Array : System.Collections.ICollection, System.Col public static int LastIndexOf(T[] array, T value) { throw null; } public static int LastIndexOf(T[] array, T value, int startIndex) { throw null; } public static int LastIndexOf(T[] array, T value, int startIndex, int count) { throw null; } - public static void Resize([System.Diagnostics.CodeAnalysis.NotNullAttribute] ref T[]? array, int newSize) { } + public static void Resize([System.Diagnostics.CodeAnalysis.NotNullAttribute] ref T[]? array, int newSize) { throw null; } public static void Reverse(System.Array array) { } public static void Reverse(System.Array array, int index, int length) { } public static void Reverse(T[] array) { } @@ -384,15 +384,15 @@ public abstract partial class Array : System.Collections.ICollection, System.Col public static void Sort(TKey[] keys, TValue[]? items, System.Collections.Generic.IComparer? comparer) { } public static void Sort(TKey[] keys, TValue[]? items, int index, int length) { } public static void Sort(TKey[] keys, TValue[]? items, int index, int length, System.Collections.Generic.IComparer? comparer) { } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } void System.Collections.IList.Clear() { } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } void System.Collections.IList.RemoveAt(int index) { } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } public static bool TrueForAll(T[] array, System.Predicate match) { throw null; } } @@ -625,21 +625,21 @@ public static partial class BitConverter public System.TypeCode GetTypeCode() { throw null; } public static System.Boolean Parse(System.ReadOnlySpan value) { throw null; } public static System.Boolean Parse(string value) { throw null; } - System.Boolean System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + System.Boolean System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public System.Boolean TryFormat(System.Span destination, out int charsWritten) { throw null; } @@ -673,21 +673,21 @@ public static partial class Buffer public static System.Byte Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.Byte Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.Byte Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + System.Byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -754,21 +754,21 @@ public partial class CannotUnloadAppDomainException : System.SystemException public static bool IsWhiteSpace(System.Char c) { throw null; } public static bool IsWhiteSpace(string s, int index) { throw null; } public static System.Char Parse(string s) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - System.Char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + System.Char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public static System.Char ToLower(System.Char c) { throw null; } public static System.Char ToLower(System.Char c, System.Globalization.CultureInfo culture) { throw null; } public static System.Char ToLowerInvariant(System.Char c) { throw null; } @@ -1344,21 +1344,21 @@ public static partial class Convert public static System.DateTime SpecifyKind(System.DateTime value, System.DateTimeKind kind) { throw null; } public System.TimeSpan Subtract(System.DateTime value) { throw null; } public System.DateTime Subtract(System.TimeSpan value) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public long ToBinary() { throw null; } public long ToFileTime() { throw null; } @@ -1461,8 +1461,8 @@ public enum DateTimeKind public static System.DateTimeOffset ParseExact(string input, string[] formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles) { throw null; } public System.TimeSpan Subtract(System.DateTimeOffset value) { throw null; } public System.DateTimeOffset Subtract(System.TimeSpan value) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + int System.IComparable.CompareTo(object? obj) { throw null; } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public long ToFileTime() { throw null; } public System.DateTimeOffset ToLocalTime() { throw null; } @@ -1500,21 +1500,21 @@ public sealed partial class DBNull : System.IConvertible, System.Runtime.Seriali public static readonly System.DBNull Value; public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public System.TypeCode GetTypeCode() { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } } @@ -1615,22 +1615,22 @@ public sealed partial class DBNull : System.IConvertible, System.Runtime.Seriali public static System.Decimal Round(System.Decimal d, int decimals, System.MidpointRounding mode) { throw null; } public static System.Decimal Round(System.Decimal d, System.MidpointRounding mode) { throw null; } public static System.Decimal Subtract(System.Decimal d1, System.Decimal d2) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } public static byte ToByte(System.Decimal value) { throw null; } public static double ToDouble(System.Decimal d) { throw null; } public static short ToInt16(System.Decimal value) { throw null; } @@ -1734,21 +1734,21 @@ public partial class DivideByZeroException : System.ArithmeticException public static System.Double Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.Double Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.Double Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - System.Double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + System.Double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -1792,21 +1792,21 @@ public abstract partial class Enum : System.ValueType, System.IComparable, Syste public static object Parse(System.Type enumType, string value, bool ignoreCase) { throw null; } public static TEnum Parse(string value) where TEnum : struct { throw null; } public static TEnum Parse(string value, bool ignoreCase) where TEnum : struct { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public static object ToObject(System.Type enumType, byte value) { throw null; } public static object ToObject(System.Type enumType, short value) { throw null; } public static object ToObject(System.Type enumType, int value) { throw null; } @@ -2000,7 +2000,7 @@ public abstract partial class FormattableString : System.IFormattable public abstract object? GetArgument(int index); public abstract object?[] GetArguments(); public static string Invariant(System.FormattableString formattable) { throw null; } - string System.IFormattable.ToString(string ignored, System.IFormatProvider formatProvider) { throw null; } + string System.IFormattable.ToString(string? ignored, System.IFormatProvider? formatProvider) { throw null; } public override string ToString() { throw null; } public abstract string ToString(System.IFormatProvider? formatProvider); } @@ -2281,21 +2281,21 @@ public sealed partial class InsufficientMemoryException : System.OutOfMemoryExce public static System.Int16 Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.Int16 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.Int16 Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - System.Int16 System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + System.Int16 System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -2322,21 +2322,21 @@ public sealed partial class InsufficientMemoryException : System.OutOfMemoryExce public static System.Int32 Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.Int32 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.Int32 Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - System.Int32 System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + System.Int32 System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -2363,21 +2363,21 @@ public sealed partial class InsufficientMemoryException : System.OutOfMemoryExce public static System.Int64 Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.Int64 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.Int64 Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - System.Int64 System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + System.Int64 System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -2548,6 +2548,9 @@ public static partial class Math public static double Atan2(double y, double x) { throw null; } public static double Atanh(double d) { throw null; } public static long BigMul(int a, int b) { throw null; } + [System.CLSCompliantAttribute(false)] + public static ulong BigMul(ulong a, ulong b, out ulong low) { throw null; } + public static long BigMul(long a, long b, out long low) { throw null; } public static double BitDecrement(double x) { throw null; } public static double BitIncrement(double x) { throw null; } public static double Cbrt(double d) { throw null; } @@ -3150,21 +3153,21 @@ public partial struct RuntimeTypeHandle : System.Runtime.Serialization.ISerializ public static System.SByte Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.SByte Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.SByte Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - System.SByte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + System.SByte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -3214,21 +3217,21 @@ public sealed partial class SerializableAttribute : System.Attribute public static System.Single Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.Single Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.Single Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - System.Single System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + System.Single System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -3449,21 +3452,21 @@ public sealed partial class String : System.Collections.Generic.IEnumerable System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public char[] ToCharArray() { throw null; } public char[] ToCharArray(int startIndex, int length) { throw null; } public System.String ToLower() { throw null; } @@ -3687,7 +3690,7 @@ public sealed partial class TimeZoneInfo : System.IEquatable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable @@ -3721,7 +3724,7 @@ public sealed partial class AdjustmentRule : System.IEquatable : System.Collections.IStructuralComparable, Syste int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple @@ -3853,10 +3856,10 @@ public partial class Tuple : System.Collections.IStructuralComparable, S int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple @@ -3869,10 +3872,10 @@ public partial class Tuple : System.Collections.IStructuralComparabl int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple @@ -3886,10 +3889,10 @@ public partial class Tuple : System.Collections.IStructuralCompa int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple @@ -3904,10 +3907,10 @@ public partial class Tuple : System.Collections.IStructuralC int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple @@ -3923,10 +3926,10 @@ public partial class Tuple : System.Collections.IStructu int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple @@ -3943,10 +3946,10 @@ public partial class Tuple : System.Collections.IStr int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public partial class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple where TRest : notnull @@ -3964,10 +3967,10 @@ public partial class Tuple : System.Collectio int System.Runtime.CompilerServices.ITuple.Length { get { throw null; } } public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object obj) { throw null; } + int System.IComparable.CompareTo(object? obj) { throw null; } public override string ToString() { throw null; } } public abstract partial class Type : System.Reflection.MemberInfo, System.Reflection.IReflect @@ -4244,21 +4247,21 @@ public partial class TypeUnloadedException : System.SystemException public static System.UInt16 Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.UInt16 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.UInt16 Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -4286,21 +4289,21 @@ public partial class TypeUnloadedException : System.SystemException public static System.UInt32 Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.UInt32 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.UInt32 Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + ulong System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -4328,21 +4331,21 @@ public partial class TypeUnloadedException : System.SystemException public static System.UInt64 Parse(string s, System.Globalization.NumberStyles style) { throw null; } public static System.UInt64 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } public static System.UInt64 Parse(string s, System.IFormatProvider? provider) { throw null; } - bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; } - byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; } - char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; } - System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; } - decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; } - double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; } - short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; } - int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; } - long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; } - sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; } - float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; } - object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; } - ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; } - uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; } - System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; } + bool System.IConvertible.ToBoolean(System.IFormatProvider? provider) { throw null; } + byte System.IConvertible.ToByte(System.IFormatProvider? provider) { throw null; } + char System.IConvertible.ToChar(System.IFormatProvider? provider) { throw null; } + System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider? provider) { throw null; } + decimal System.IConvertible.ToDecimal(System.IFormatProvider? provider) { throw null; } + double System.IConvertible.ToDouble(System.IFormatProvider? provider) { throw null; } + short System.IConvertible.ToInt16(System.IFormatProvider? provider) { throw null; } + int System.IConvertible.ToInt32(System.IFormatProvider? provider) { throw null; } + long System.IConvertible.ToInt64(System.IFormatProvider? provider) { throw null; } + sbyte System.IConvertible.ToSByte(System.IFormatProvider? provider) { throw null; } + float System.IConvertible.ToSingle(System.IFormatProvider? provider) { throw null; } + object System.IConvertible.ToType(System.Type type, System.IFormatProvider? provider) { throw null; } + ushort System.IConvertible.ToUInt16(System.IFormatProvider? provider) { throw null; } + uint System.IConvertible.ToUInt32(System.IFormatProvider? provider) { throw null; } + System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider? provider) { throw null; } public override string ToString() { throw null; } public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString(string? format) { throw null; } @@ -4617,10 +4620,10 @@ public partial struct ValueTuple : System.Collections.IStructuralComparable, Sys public override bool Equals(object? obj) { throw null; } public bool Equals(System.ValueTuple other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable>, System.IEquatable>, System.Runtime.CompilerServices.ITuple @@ -4633,10 +4636,10 @@ public partial struct ValueTuple : System.Collections.IStructuralComparable, public override bool Equals(object? obj) { throw null; } public bool Equals(System.ValueTuple other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2)>, System.IEquatable<(T1, T2)>, System.Runtime.CompilerServices.ITuple @@ -4650,10 +4653,10 @@ public partial struct ValueTuple : System.Collections.IStructuralCompara public override bool Equals(object? obj) { throw null; } public bool Equals((T1, T2) other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3)>, System.IEquatable<(T1, T2, T3)>, System.Runtime.CompilerServices.ITuple @@ -4668,10 +4671,10 @@ public partial struct ValueTuple : System.Collections.IStructuralCom public override bool Equals(object? obj) { throw null; } public bool Equals((T1, T2, T3) other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4)>, System.IEquatable<(T1, T2, T3, T4)>, System.Runtime.CompilerServices.ITuple @@ -4687,10 +4690,10 @@ public partial struct ValueTuple : System.Collections.IStructura public override bool Equals(object? obj) { throw null; } public bool Equals((T1, T2, T3, T4) other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4, T5)>, System.IEquatable<(T1, T2, T3, T4, T5)>, System.Runtime.CompilerServices.ITuple @@ -4707,10 +4710,10 @@ public partial struct ValueTuple : System.Collections.IStruc public override bool Equals(object? obj) { throw null; } public bool Equals((T1, T2, T3, T4, T5) other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4, T5, T6)>, System.IEquatable<(T1, T2, T3, T4, T5, T6)>, System.Runtime.CompilerServices.ITuple @@ -4728,10 +4731,10 @@ public partial struct ValueTuple : System.Collections.IS public override bool Equals(object? obj) { throw null; } public bool Equals((T1, T2, T3, T4, T5, T6) other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4, T5, T6, T7)>, System.IEquatable<(T1, T2, T3, T4, T5, T6, T7)>, System.Runtime.CompilerServices.ITuple @@ -4750,10 +4753,10 @@ public partial struct ValueTuple : System.Collection public override bool Equals(object? obj) { throw null; } public bool Equals((T1, T2, T3, T4, T5, T6, T7) other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public partial struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable>, System.IEquatable>, System.Runtime.CompilerServices.ITuple where TRest : struct @@ -4773,10 +4776,10 @@ public partial struct ValueTuple : System.Col public override bool Equals(object? obj) { throw null; } public bool Equals(System.ValueTuple other) { throw null; } public override int GetHashCode() { throw null; } - int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; } + int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } + bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - int System.IComparable.CompareTo(object other) { throw null; } + int System.IComparable.CompareTo(object? other) { throw null; } public override string ToString() { throw null; } } public abstract partial class ValueType @@ -5300,11 +5303,11 @@ public partial class Collection : System.Collections.Generic.ICollection, protected virtual void SetItem(int index, T item) { } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.IList.Add(object value) { throw null; } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + int System.Collections.IList.Add(object? value) { throw null; } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } } public partial class ReadOnlyCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { @@ -5330,12 +5333,12 @@ public partial class ReadOnlyCollection : System.Collections.Generic.ICollect void System.Collections.Generic.IList.RemoveAt(int index) { } void System.Collections.ICollection.CopyTo(System.Array array, int index) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } void System.Collections.IList.Clear() { } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } void System.Collections.IList.RemoveAt(int index) { } } } @@ -5698,6 +5701,13 @@ public sealed class MemberNotNullWhenAttribute : System.Attribute public bool ReturnValue { get { throw null; } } public string[] Members { get { throw null; } } } + [System.AttributeUsageAttribute(System.AttributeTargets.Method | System.AttributeTargets.Constructor, Inherited = false)] + public sealed class RequiresUnreferencedCodeAttribute : System.Attribute + { + public RequiresUnreferencedCodeAttribute(string message) { } + public string Message { get { throw null; } } + public string? Url { get { throw null; } set { } } + } [System.AttributeUsageAttribute(System.AttributeTargets.All, Inherited=false, AllowMultiple=true)] [System.Diagnostics.ConditionalAttribute("CODE_ANALYSIS")] public sealed partial class SuppressMessageAttribute : System.Attribute @@ -5872,7 +5882,7 @@ public sealed partial class CompareInfo : System.Runtime.Serialization.IDeserial public int LastIndexOf(string source, string value, int startIndex, int count, System.Globalization.CompareOptions options) { throw null; } public int LastIndexOf(System.ReadOnlySpan source, System.ReadOnlySpan value, System.Globalization.CompareOptions options = System.Globalization.CompareOptions.None) { throw null; } public int LastIndexOf(System.ReadOnlySpan source, System.Text.Rune value, System.Globalization.CompareOptions options = System.Globalization.CompareOptions.None) { throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } public override string ToString() { throw null; } } [System.FlagsAttribute] @@ -6495,7 +6505,7 @@ public sealed partial class TextInfo : System.ICloneable, System.Runtime.Seriali public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } public static System.Globalization.TextInfo ReadOnly(System.Globalization.TextInfo textInfo) { throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } public char ToLower(char c) { throw null; } public string ToLower(string str) { throw null; } public override string ToString() { throw null; } @@ -8117,6 +8127,8 @@ public abstract partial class MethodInfo : System.Reflection.MethodBase public abstract System.Reflection.ICustomAttributeProvider ReturnTypeCustomAttributes { get; } public virtual System.Delegate CreateDelegate(System.Type delegateType) { throw null; } public virtual System.Delegate CreateDelegate(System.Type delegateType, object? target) { throw null; } + public T CreateDelegate() where T : System.Delegate { throw null; } + public T CreateDelegate(object? target) where T : System.Delegate { throw null; } public override bool Equals(object? obj) { throw null; } public abstract System.Reflection.MethodInfo GetBaseDefinition(); public override System.Type[] GetGenericArguments() { throw null; } @@ -8379,7 +8391,7 @@ public partial class StrongNameKeyPair : System.Runtime.Serialization.IDeseriali protected StrongNameKeyPair(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public StrongNameKeyPair(string keyPairContainer) { } public byte[] PublicKey { get { throw null; } } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object? sender) { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } public partial class TargetException : System.ApplicationException diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj index 95118ff34a34c..69f4de93591a8 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj @@ -70,7 +70,7 @@ - + @@ -156,6 +156,7 @@ + diff --git a/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs index c0832946be83e..d93235c129929 100644 --- a/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs @@ -14,7 +14,7 @@ public static class ArgumentExceptionTests public static void Ctor_Empty() { var exception = new ArgumentException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, validateMessage: false); Assert.Null(exception.ParamName); } @@ -23,7 +23,7 @@ public static void Ctor_String() { string message = "the argument is wrong"; var exception = new ArgumentException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, message: message); Assert.Null(exception.ParamName); } @@ -33,7 +33,7 @@ public static void Ctor_String_Exception() string message = "the argument is wrong"; var innerException = new Exception("Inner exception"); var exception = new ArgumentException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, innerException: innerException, message: message); Assert.Null(exception.ParamName); } @@ -43,7 +43,7 @@ public static void Ctor_String_String() string message = "the argument is wrong"; string argumentName = "theArgument"; var exception = new ArgumentException(message, argumentName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, validateMessage: false); Assert.Equal(argumentName, exception.ParamName); Assert.Contains(message, exception.Message); Assert.Contains(argumentName, exception.Message); @@ -56,7 +56,7 @@ public static void Ctor_String_String_Exception() string argumentName = "theArgument"; var innerException = new Exception("Inner exception"); var exception = new ArgumentException(message, argumentName, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, innerException: innerException, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENT, innerException: innerException, validateMessage: false); Assert.Equal(argumentName, exception.ParamName); Assert.Contains(message, exception.Message); Assert.Contains(argumentName, exception.Message); diff --git a/src/libraries/System.Runtime/tests/System/ArgumentNullExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArgumentNullExceptionTests.cs index f872b36d441dc..91520e0a93669 100644 --- a/src/libraries/System.Runtime/tests/System/ArgumentNullExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArgumentNullExceptionTests.cs @@ -14,7 +14,7 @@ public static class ArgumentNullExceptionTests public static void Ctor_Empty() { var exception = new ArgumentNullException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_POINTER, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_POINTER, validateMessage: false); Assert.Null(exception.ParamName); } @@ -23,7 +23,7 @@ public static void Ctor_String() { string argumentName = "theNullArgument"; var exception = new ArgumentNullException(argumentName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_POINTER, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_POINTER, validateMessage: false); Assert.Contains(argumentName, exception.Message); } @@ -33,7 +33,7 @@ public static void Ctor_String_Exception() string message = "the argument is null"; var innerException = new Exception("Inner exception"); var exception = new ArgumentNullException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_POINTER, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_POINTER, innerException: innerException, message: message); Assert.Null(exception.ParamName); } @@ -43,7 +43,7 @@ public static void Ctor_String_String() string message = "the argument is null"; string argumentName = "theNullArgument"; var exception = new ArgumentNullException(argumentName, message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_POINTER, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_POINTER, validateMessage: false); Assert.Equal(argumentName, exception.ParamName); Assert.Contains(message, exception.Message); Assert.Contains(argumentName, exception.Message); diff --git a/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs index d3785552eb390..ba14619ae82f1 100644 --- a/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArgumentOutOfRangeExceptionTests.cs @@ -14,7 +14,7 @@ public static class ArgumentOutOfRangeExceptionTests public static void Ctor_Empty() { var exception = new ArgumentOutOfRangeException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); Assert.Null(exception.ParamName); Assert.Null(exception.ActualValue); } @@ -24,7 +24,7 @@ public static void Ctor_String() { string argumentName = "theArgument"; var exception = new ArgumentOutOfRangeException(argumentName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); Assert.Equal(argumentName, exception.ParamName); Assert.Null(exception.ActualValue); } @@ -35,7 +35,7 @@ public static void Ctor_String_Exception() string message = "the argument is out of range"; var innerException = new Exception("Inner exception"); var exception = new ArgumentOutOfRangeException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, innerException: innerException, message: message); Assert.Null(exception.ParamName); Assert.Null(exception.ActualValue); } @@ -46,7 +46,7 @@ public static void Ctor_String_String() string message = "the argument is out of range"; string argumentName = "theArgument"; var exception = new ArgumentOutOfRangeException(argumentName, message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); Assert.Equal(argumentName, exception.ParamName); Assert.Null(exception.ActualValue); Assert.Contains(message, exception.Message); @@ -60,7 +60,7 @@ public static void Ctor_String_Object_String() string argumentName = "theArgument"; int argumentValue = Int32.MaxValue; var exception = new ArgumentOutOfRangeException(argumentName, argumentValue, message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARGUMENTOUTOFRANGE, validateMessage: false); Assert.Equal(argumentName, exception.ParamName); Assert.Contains(message, exception.Message); Assert.Contains(argumentName, exception.Message); diff --git a/src/libraries/System.Runtime/tests/System/ArithmeticExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArithmeticExceptionTests.cs index bd1ede2f2656e..7a8eb22dc97bb 100644 --- a/src/libraries/System.Runtime/tests/System/ArithmeticExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArithmeticExceptionTests.cs @@ -14,7 +14,7 @@ public static class ArithmeticExceptionTests public static void Ctor_Empty() { var exception = new ArithmeticException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARITHMETIC, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARITHMETIC, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "arithmetic operation error"; var exception = new ArithmeticException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARITHMETIC, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARITHMETIC, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "arithmetic operation error"; var innerException = new Exception("Inner exception"); var exception = new ArithmeticException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARITHMETIC, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARITHMETIC, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/ArrayTypeMismatchExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArrayTypeMismatchExceptionTests.cs index d017250e38711..d59b91470d3ad 100644 --- a/src/libraries/System.Runtime/tests/System/ArrayTypeMismatchExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArrayTypeMismatchExceptionTests.cs @@ -14,7 +14,7 @@ public static class ArrayTypeMismatchExceptionTests public static void Ctor_Empty() { var exception = new ArrayTypeMismatchException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARRAYTYPEMISMATCH, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARRAYTYPEMISMATCH, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "array type mismatch"; var exception = new ArrayTypeMismatchException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARRAYTYPEMISMATCH, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARRAYTYPEMISMATCH, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "array type mismatch"; var innerException = new Exception("Inner exception"); var exception = new ArrayTypeMismatchException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_ARRAYTYPEMISMATCH, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_ARRAYTYPEMISMATCH, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/Attributes.cs b/src/libraries/System.Runtime/tests/System/Attributes.cs index d56a39850df29..f30464ca65ae6 100644 --- a/src/libraries/System.Runtime/tests/System/Attributes.cs +++ b/src/libraries/System.Runtime/tests/System/Attributes.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. // -// AttributeTest.cs - NUnit Test Cases for the System.Attribute class +// AttributeTest.cs - Unit Test Cases for the System.Attribute class // // Authors: // Duco Fijma (duco@lorentz.xs4all.nl) @@ -81,6 +81,12 @@ public void IsDefined_PropertyInfo_Override() Assert.False(Attribute.IsDefined(pi, typeof(ComVisibleAttribute), false)); Assert.False(Attribute.IsDefined(pi, typeof(ComVisibleAttribute), true)); } + + [Fact] + public void IsDefined_Interface() + { + Assert.True(typeof(ExampleWithAttribute).IsDefined(typeof(INameable), false)); + } } public static class AttributeGetCustomAttributes @@ -206,6 +212,12 @@ public static void MultipleAttributesTest() Assert.Equal("System.Tests.MyCustomAttribute System.Tests.MyCustomAttribute", string.Join(" ", typeof(MultipleAttributes).GetCustomAttributes(inherit: false))); Assert.Equal("System.Tests.MyCustomAttribute System.Tests.MyCustomAttribute", string.Join(" ", typeof(MultipleAttributes).GetCustomAttributes(inherit: true))); } + + [Fact] + public static void GetCustomAttributes_Interface() + { + Assert.True(typeof(ExampleWithAttribute).GetCustomAttributes(typeof(INameable), inherit: false)[0] is NameableAttribute); + } } public static class GetCustomAttribute @@ -798,4 +810,18 @@ public override string PropBase3 class MultipleAttributes { } + + public interface INameable + { + string Name { get; } + } + + [AttributeUsage (AttributeTargets.All, AllowMultiple = true)] + public class NameableAttribute : Attribute, INameable + { + string INameable.Name => "Nameable"; + } + + [Nameable] + public class ExampleWithAttribute { } } diff --git a/src/libraries/System.Runtime/tests/System/BadImageFormatExceptionTests.cs b/src/libraries/System.Runtime/tests/System/BadImageFormatExceptionTests.cs index 497f515f6e1cb..70be2d0677899 100644 --- a/src/libraries/System.Runtime/tests/System/BadImageFormatExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/BadImageFormatExceptionTests.cs @@ -14,7 +14,7 @@ public static class BadImageFormatExceptionTests public static void Ctor_Empty() { var exception = new BadImageFormatException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, validateMessage: false); Assert.Null(exception.FileName); } @@ -23,7 +23,7 @@ public static void Ctor_String() { string message = "this is not the file you're looking for"; var exception = new BadImageFormatException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, message: message); Assert.Null(exception.FileName); } @@ -33,7 +33,7 @@ public static void Ctor_String_Exception() string message = "this is not the file you're looking for"; var innerException = new Exception("Inner exception"); var exception = new BadImageFormatException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, innerException: innerException, message: message); Assert.Null(exception.FileName); } @@ -43,7 +43,7 @@ public static void Ctor_String_String() string message = "this is not the file you're looking for"; string fileName = "file.txt"; var exception = new BadImageFormatException(message, fileName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, message: message); Assert.Equal(fileName, exception.FileName); } @@ -54,7 +54,7 @@ public static void Ctor_String_String_Exception() string fileName = "file.txt"; var innerException = new Exception("Inner exception"); var exception = new BadImageFormatException(message, fileName, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_BADIMAGEFORMAT, innerException: innerException, message: message); Assert.Equal(fileName, exception.FileName); } diff --git a/src/libraries/System.Runtime/tests/System/Collections/Generic/KeyNotFoundExceptionTests.cs b/src/libraries/System.Runtime/tests/System/Collections/Generic/KeyNotFoundExceptionTests.cs index c3cf6a6c4e491..e3013ab165a33 100644 --- a/src/libraries/System.Runtime/tests/System/Collections/Generic/KeyNotFoundExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/Collections/Generic/KeyNotFoundExceptionTests.cs @@ -16,7 +16,7 @@ public static class KeyNotFoundExceptionTests public static void Ctor_Empty() { var exception = new KeyNotFoundException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_KEYNOTFOUND, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_KEYNOTFOUND, validateMessage: false); } [Fact] @@ -24,7 +24,7 @@ public static void Ctor_String() { string message = "this is not the key you're looking for"; var exception = new KeyNotFoundException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_KEYNOTFOUND, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_KEYNOTFOUND, message: message); } [Fact] @@ -33,7 +33,7 @@ public static void Ctor_String_Exception() string message = "this is not the key you're looking for"; var innerException = new Exception("Inner exception"); var exception = new KeyNotFoundException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_KEYNOTFOUND, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_KEYNOTFOUND, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.cs b/src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.cs index d62cb75547c15..0d146b4cd2c6f 100644 --- a/src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.cs +++ b/src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.cs @@ -357,8 +357,8 @@ public static void AddYears(DateTimeOffset dateTimeOffset, int years, DateTimeOf [Fact] public static void AddYears_NewDateOutOfRange_ThrowsArgumentOutOfRangeException() { - AssertExtensions.Throws("years", () => DateTimeOffset.Now.AddYears(10001)); - AssertExtensions.Throws("years", () => DateTimeOffset.Now.AddYears(-10001)); + AssertExtensions.Throws("value", () => DateTimeOffset.Now.AddYears(10001)); + AssertExtensions.Throws("value", () => DateTimeOffset.Now.AddYears(-10001)); AssertExtensions.Throws("months", () => DateTimeOffset.MaxValue.AddYears(1)); AssertExtensions.Throws("months", () => DateTimeOffset.MinValue.AddYears(-1)); diff --git a/src/libraries/System.Runtime/tests/System/DateTimeTests.cs b/src/libraries/System.Runtime/tests/System/DateTimeTests.cs index 654a103cc9af0..c1d68a264deec 100644 --- a/src/libraries/System.Runtime/tests/System/DateTimeTests.cs +++ b/src/libraries/System.Runtime/tests/System/DateTimeTests.cs @@ -383,8 +383,8 @@ public void AddYears_Invoke_ReturnsExpected(DateTime dateTime, int years, DateTi public static IEnumerable AddYears_OutOfRange_TestData() { - yield return new object[] { DateTime.Now, 10001, "years" }; - yield return new object[] { DateTime.Now, -10001, "years" }; + yield return new object[] { DateTime.Now, 10001, "value" }; + yield return new object[] { DateTime.Now, -10001, "value" }; yield return new object[] { DateTime.MaxValue, 1, "months" }; yield return new object[] { DateTime.MinValue, -1, "months" }; } diff --git a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/DynamicDependencyAttributeTests.cs b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/DynamicDependencyAttributeTests.cs index 2b475906acfc5..337af64fdd342 100644 --- a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/DynamicDependencyAttributeTests.cs +++ b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/DynamicDependencyAttributeTests.cs @@ -6,7 +6,7 @@ namespace System.Diagnostics.CodeAnalysis.Tests { - public class DynamicDependencyAttributeTestsTests + public class DynamicDependencyAttributeTests { [Theory] [InlineData("Foo()")] diff --git a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttributeTests.cs b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttributeTests.cs new file mode 100644 index 0000000000000..044fc78deec0b --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttributeTests.cs @@ -0,0 +1,35 @@ +// 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 Xunit; + +namespace System.Diagnostics.CodeAnalysis.Tests +{ + public class RequiresUnreferencedCodeAttributeTests + { + [Fact] + public void TestConstructor() + { + var attr = new RequiresUnreferencedCodeAttribute("User Message"); + + Assert.Equal("User Message", attr.Message); + Assert.Null(attr.Url); + } + + [Theory] + [InlineData("https://dot.net")] + [InlineData("")] + [InlineData(null)] + public void TestSetUrl(string url) + { + var attr = new RequiresUnreferencedCodeAttribute("User Message") + { + Url = url + }; + + Assert.Equal("User Message", attr.Message); + Assert.Equal(url, attr.Url); + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/DivideByZeroExceptionTests.cs b/src/libraries/System.Runtime/tests/System/DivideByZeroExceptionTests.cs index 0e86ae49b4b86..a9117b7083338 100644 --- a/src/libraries/System.Runtime/tests/System/DivideByZeroExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/DivideByZeroExceptionTests.cs @@ -14,7 +14,7 @@ public static class DivideByZeroExceptionTests public static void Ctor_Empty() { var exception = new DivideByZeroException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_DIVIDEBYZERO, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_DIVIDEBYZERO, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "divide by zero"; var exception = new DivideByZeroException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_DIVIDEBYZERO, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_DIVIDEBYZERO, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "divide by zero"; var innerException = new Exception("Inner exception"); var exception = new DivideByZeroException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_DIVIDEBYZERO, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_DIVIDEBYZERO, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/Exceptions.Utility.cs b/src/libraries/System.Runtime/tests/System/Exception.Helpers.cs similarity index 96% rename from src/libraries/System.Runtime/tests/System/Exceptions.Utility.cs rename to src/libraries/System.Runtime/tests/System/Exception.Helpers.cs index d7d0967c94dca..a39cd04998828 100644 --- a/src/libraries/System.Runtime/tests/System/Exceptions.Utility.cs +++ b/src/libraries/System.Runtime/tests/System/Exception.Helpers.cs @@ -7,7 +7,7 @@ namespace System.Tests { - public static class ExceptionUtility + public static class ExceptionHelpers { public static void ValidateExceptionProperties(Exception e, int hResult, diff --git a/src/libraries/System.Runtime/tests/System/ExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ExceptionTests.cs index 6d663486205a3..4704368e6b9a5 100644 --- a/src/libraries/System.Runtime/tests/System/ExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ExceptionTests.cs @@ -21,7 +21,7 @@ public static class ExceptionTests public static void Ctor_Empty() { var exception = new Exception(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_EXCEPTION, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_EXCEPTION, validateMessage: false); } [Fact] @@ -29,7 +29,7 @@ public static void Ctor_String() { string message = "something went wrong"; var exception = new Exception(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_EXCEPTION, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_EXCEPTION, message: message); } [Fact] @@ -38,7 +38,7 @@ public static void Ctor_String_Exception() string message = "something went wrong"; var innerException = new Exception("Inner exception"); var exception = new Exception(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_EXCEPTION, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_EXCEPTION, innerException: innerException, message: message); } [Fact] diff --git a/src/libraries/System.Runtime/tests/System/FormatExceptionTests.cs b/src/libraries/System.Runtime/tests/System/FormatExceptionTests.cs index 79924d6b53b5b..a5f78ae97a36e 100644 --- a/src/libraries/System.Runtime/tests/System/FormatExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/FormatExceptionTests.cs @@ -14,7 +14,7 @@ public static class FormatExceptionTests public static void Ctor_Empty() { var exception = new FormatException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_FORMAT, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_FORMAT, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "bad format"; var exception = new FormatException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_FORMAT, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_FORMAT, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "bad format"; var innerException = new Exception("Inner exception"); var exception = new FormatException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_FORMAT, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_FORMAT, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/GCTests.cs b/src/libraries/System.Runtime/tests/System/GCTests.cs index 097f2dcac805b..4c8c309167735 100644 --- a/src/libraries/System.Runtime/tests/System/GCTests.cs +++ b/src/libraries/System.Runtime/tests/System/GCTests.cs @@ -25,7 +25,7 @@ public static void AddMemoryPressure_InvalidBytesAllocated_ThrowsArgumentOutOfRa if (s_is32Bits) { - AssertExtensions.Throws("pressure", () => GC.AddMemoryPressure((long)int.MaxValue + 1)); // Bytes allocated > int.MaxValue on 32 bit platforms + AssertExtensions.Throws("bytesAllocated", () => GC.AddMemoryPressure((long)int.MaxValue + 1)); // Bytes allocated > int.MaxValue on 32 bit platforms } } diff --git a/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundException.InteropTests.cs b/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundException.InteropTests.cs index 37c4c89c4ba93..5a1a533ba0702 100644 --- a/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundException.InteropTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundException.InteropTests.cs @@ -19,7 +19,7 @@ public static void From_HR(int hr) DirectoryNotFoundException exception = Assert.IsAssignableFrom(Marshal.GetExceptionForHR(hr, new IntPtr(-1))); // Don't validate the message. Currently .NET Native does not produce HR-specific messages - ExceptionUtility.ValidateExceptionProperties(exception, hResult: hr, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: hr, validateMessage: false); } } } diff --git a/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundExceptionTests.cs index 229acd4b0d2d4..f510afd9d1ca0 100644 --- a/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/DirectoryNotFoundExceptionTests.cs @@ -15,7 +15,7 @@ public static class DirectoryNotFoundExceptionTests public static void Ctor_Empty() { var exception = new DirectoryNotFoundException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_DIRECTORYNOTFOUND, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_DIRECTORYNOTFOUND, validateMessage: false); } [Fact] @@ -23,7 +23,7 @@ public static void Ctor_String() { string message = "That page was missing from the directory."; var exception = new DirectoryNotFoundException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_DIRECTORYNOTFOUND, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_DIRECTORYNOTFOUND, message: message); } [Fact] @@ -32,7 +32,7 @@ public static void Ctor_String_Exception() string message = "That page was missing from the directory."; var innerException = new Exception("Inner exception"); var exception = new DirectoryNotFoundException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_DIRECTORYNOTFOUND, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_DIRECTORYNOTFOUND, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/IO/FileLoadException.InteropTests.cs b/src/libraries/System.Runtime/tests/System/IO/FileLoadException.InteropTests.cs index 6cb7e62e7542d..4072851e06706 100644 --- a/src/libraries/System.Runtime/tests/System/IO/FileLoadException.InteropTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/FileLoadException.InteropTests.cs @@ -44,7 +44,7 @@ public static void Fom_HR(int hr) Assert.NotNull(fileLoadException); // Don't validate the message. Currently .NET Native does not produce HR-specific messages - ExceptionUtility.ValidateExceptionProperties(fileLoadException, hResult: hr, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(fileLoadException, hResult: hr, validateMessage: false); Assert.Null(fileLoadException.FileName); } } diff --git a/src/libraries/System.Runtime/tests/System/IO/FileLoadExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IO/FileLoadExceptionTests.cs index 9d4549742e8a1..b7479e868dadd 100644 --- a/src/libraries/System.Runtime/tests/System/IO/FileLoadExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/FileLoadExceptionTests.cs @@ -13,7 +13,7 @@ public static class FileLoadExceptionTests public static void Ctor_Empty() { var exception = new FileLoadException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, validateMessage: false); Assert.Null(exception.FileName); } @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "this is not the file you're looking for"; var exception = new FileLoadException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, message: message); Assert.Null(exception.FileName); } @@ -32,7 +32,7 @@ public static void Ctor_String_Exception() string message = "this is not the file you're looking for"; var innerException = new Exception("Inner exception"); var exception = new FileLoadException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, innerException: innerException, message: message); Assert.Null(exception.FileName); } @@ -42,7 +42,7 @@ public static void Ctor_String_String() string message = "this is not the file you're looking for"; string fileName = "file.txt"; var exception = new FileLoadException(message, fileName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, message: message); Assert.Equal(fileName, exception.FileName); } @@ -53,7 +53,7 @@ public static void Ctor_String_String_Exception() string fileName = "file.txt"; var innerException = new Exception("Inner exception"); var exception = new FileLoadException(message, fileName, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILELOAD, innerException: innerException, message: message); Assert.Equal(fileName, exception.FileName); } diff --git a/src/libraries/System.Runtime/tests/System/IO/FileNotFoundException.InteropTests.cs b/src/libraries/System.Runtime/tests/System/IO/FileNotFoundException.InteropTests.cs index bd6887359f06a..5ccc505f93a16 100644 --- a/src/libraries/System.Runtime/tests/System/IO/FileNotFoundException.InteropTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/FileNotFoundException.InteropTests.cs @@ -18,7 +18,7 @@ public static void From_HR(int hr) FileNotFoundException exception = Assert.IsAssignableFrom(Marshal.GetExceptionForHR(hr, new IntPtr(-1))); // Don't validate the message. Currently .NET Native does not produce HR-specific messages - ExceptionUtility.ValidateExceptionProperties(exception, hResult: hr, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: hr, validateMessage: false); } } } diff --git a/src/libraries/System.Runtime/tests/System/IO/FileNotFoundExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IO/FileNotFoundExceptionTests.cs index c9e8ae9368f9c..73f39702f1655 100644 --- a/src/libraries/System.Runtime/tests/System/IO/FileNotFoundExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/FileNotFoundExceptionTests.cs @@ -13,7 +13,7 @@ public static class FileNotFoundExceptionTests public static void Ctor_Empty() { var exception = new FileNotFoundException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, validateMessage: false); Assert.Null(exception.FileName); } @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "this is not the file you're looking for"; var exception = new FileNotFoundException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, message: message); Assert.Null(exception.FileName); } @@ -32,7 +32,7 @@ public static void Ctor_String_Exception() string message = "this is not the file you're looking for"; var innerException = new Exception("Inner exception"); var exception = new FileNotFoundException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, innerException: innerException, message: message); Assert.Null(exception.FileName); } @@ -42,7 +42,7 @@ public static void Ctor_String_String() string message = "this is not the file you're looking for"; string fileName = "file.txt"; var exception = new FileNotFoundException(message, fileName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, message: message); Assert.Equal(fileName, exception.FileName); } @@ -53,7 +53,7 @@ public static void Ctor_String_String_Exception() string fileName = "file.txt"; var innerException = new Exception("Inner exception"); var exception = new FileNotFoundException(message, fileName, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_FILENOTFOUND, innerException: innerException, message: message); Assert.Equal(fileName, exception.FileName); } diff --git a/src/libraries/System.Runtime/tests/System/IO/IOExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IO/IOExceptionTests.cs index ab5258c266857..14b769eb1f360 100644 --- a/src/libraries/System.Runtime/tests/System/IO/IOExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/IOExceptionTests.cs @@ -16,7 +16,7 @@ public static class IOExceptionTests public static void Ctor_Empty() { var exception = new IOException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_IO, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_IO, validateMessage: false); } [Fact] @@ -24,7 +24,7 @@ public static void Ctor_String() { string message = "IO failure"; var exception = new IOException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_IO, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_IO, message: message); } [Fact] @@ -33,7 +33,7 @@ public static void Ctor_String_Exception() string message = "IO failure"; var innerException = new Exception("Inner exception"); var exception = new IOException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_IO, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_IO, innerException: innerException, message: message); } [Fact] @@ -42,7 +42,7 @@ public static void Ctor_String_Int32() string message = "IO failure"; int hResult = unchecked((int)0x80424242); var exception = new IOException(message, hResult); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: hResult, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: hResult, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/IO/PathTooLongException.InteropTests.cs b/src/libraries/System.Runtime/tests/System/IO/PathTooLongException.InteropTests.cs index 1a21cad4a34ed..11c93f5fcf54d 100644 --- a/src/libraries/System.Runtime/tests/System/IO/PathTooLongException.InteropTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/PathTooLongException.InteropTests.cs @@ -15,7 +15,7 @@ public static void From_HR() { int hr = HResults.COR_E_PATHTOOLONG; PathTooLongException exception = Assert.IsAssignableFrom(Marshal.GetExceptionForHR(hr, new IntPtr(-1))); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: hr, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: hr, validateMessage: false); } } } diff --git a/src/libraries/System.Runtime/tests/System/IO/PathTooLongExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IO/PathTooLongExceptionTests.cs index 8bf3dd2ab5f1f..5d05b283cbedb 100644 --- a/src/libraries/System.Runtime/tests/System/IO/PathTooLongExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IO/PathTooLongExceptionTests.cs @@ -16,7 +16,7 @@ public static class PathTooLongExceptionTests public static void Ctor_Empty() { var exception = new PathTooLongException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_PATHTOOLONG, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_PATHTOOLONG, validateMessage: false); } [Fact] @@ -24,7 +24,7 @@ public static void Ctor_String() { string message = "This path is too long to hike in a single day."; var exception = new PathTooLongException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_PATHTOOLONG, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_PATHTOOLONG, message: message); } [Fact] @@ -33,7 +33,7 @@ public static void Ctor_String_Exception() string message = "This path is too long to hike in a single day."; var innerException = new Exception("Inner exception"); var exception = new PathTooLongException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: HResults.COR_E_PATHTOOLONG, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: HResults.COR_E_PATHTOOLONG, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/IndexOutOfRangeExceptionTests.cs b/src/libraries/System.Runtime/tests/System/IndexOutOfRangeExceptionTests.cs index 69d83851efcda..98314f591f501 100644 --- a/src/libraries/System.Runtime/tests/System/IndexOutOfRangeExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/IndexOutOfRangeExceptionTests.cs @@ -14,7 +14,7 @@ public static class IndexOutOfRangeExceptionTests public static void Ctor_Empty() { var exception = new IndexOutOfRangeException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INDEXOUTOFRANGE, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INDEXOUTOFRANGE, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "out of range"; var exception = new IndexOutOfRangeException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INDEXOUTOFRANGE, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INDEXOUTOFRANGE, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "out of range"; var innerException = new Exception("Inner exception"); var exception = new IndexOutOfRangeException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INDEXOUTOFRANGE, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INDEXOUTOFRANGE, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/InvalidCastExceptionTests.cs b/src/libraries/System.Runtime/tests/System/InvalidCastExceptionTests.cs index ac0bb5ae408f6..291d5137a7e2b 100644 --- a/src/libraries/System.Runtime/tests/System/InvalidCastExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/InvalidCastExceptionTests.cs @@ -14,7 +14,7 @@ public static class InvalidCastExceptionTests public static void Ctor_Empty() { var exception = new InvalidCastException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDCAST, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDCAST, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "wrong type"; var exception = new InvalidCastException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDCAST, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDCAST, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "wrong type"; var innerException = new Exception("Inner exception"); var exception = new InvalidCastException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDCAST, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDCAST, innerException: innerException, message: message); } [Fact] @@ -40,7 +40,7 @@ public static void Ctor_String_Int32() string message = "wrong type"; int errorCode = unchecked((int)0x80424242); var exception = new InvalidCastException(message, errorCode); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: errorCode, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: errorCode, message: message); } } diff --git a/src/libraries/System.Runtime/tests/System/InvalidOperationExceptionTests.cs b/src/libraries/System.Runtime/tests/System/InvalidOperationExceptionTests.cs index d1a877aca2516..7448b5bb8e25e 100644 --- a/src/libraries/System.Runtime/tests/System/InvalidOperationExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/InvalidOperationExceptionTests.cs @@ -14,7 +14,7 @@ public static class InvalidOperationExceptionTests public static void Ctor_Empty() { var exception = new InvalidOperationException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDOPERATION, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDOPERATION, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "invalid operation"; var exception = new InvalidOperationException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDOPERATION, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDOPERATION, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "invalid operation"; var innerException = new Exception("Inner exception"); var exception = new InvalidOperationException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDOPERATION, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDOPERATION, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/InvalidProgramExceptionTests.cs b/src/libraries/System.Runtime/tests/System/InvalidProgramExceptionTests.cs index 17488ceb1e40e..98ae359537af2 100644 --- a/src/libraries/System.Runtime/tests/System/InvalidProgramExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/InvalidProgramExceptionTests.cs @@ -14,7 +14,7 @@ public static class InvalidProgramExceptionTests public static void Ctor_Empty() { var exception = new InvalidProgramException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDPROGRAM, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDPROGRAM, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "bad program"; var exception = new InvalidProgramException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDPROGRAM, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDPROGRAM, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "bad program"; var innerException = new Exception("Inner exception"); var exception = new InvalidProgramException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDPROGRAM, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_INVALIDPROGRAM, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/MemberAccessExceptionTests.cs b/src/libraries/System.Runtime/tests/System/MemberAccessExceptionTests.cs index 6ffc2912009f6..46b268ff311e4 100644 --- a/src/libraries/System.Runtime/tests/System/MemberAccessExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/MemberAccessExceptionTests.cs @@ -14,7 +14,7 @@ public static class MemberAccessExceptionTests public static void Ctor_Empty() { var exception = new MemberAccessException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_MEMBERACCESS, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_MEMBERACCESS, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "you cannot access this member"; var exception = new MemberAccessException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_MEMBERACCESS, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_MEMBERACCESS, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "you cannot access this member"; var innerException = new Exception("Inner exception"); var exception = new MemberAccessException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_MEMBERACCESS, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_MEMBERACCESS, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/NotImplementedExceptionTests.cs b/src/libraries/System.Runtime/tests/System/NotImplementedExceptionTests.cs index f2a19dddafedf..dfc8ab299a9f0 100644 --- a/src/libraries/System.Runtime/tests/System/NotImplementedExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/NotImplementedExceptionTests.cs @@ -14,7 +14,7 @@ public static class NotImplementedExceptionTests public static void Ctor_Empty() { var exception = new NotImplementedException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_NOTIMPL, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_NOTIMPL, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "not implemented"; var exception = new NotImplementedException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_NOTIMPL, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_NOTIMPL, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "not implemented"; var innerException = new Exception("Inner exception"); var exception = new NotImplementedException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: E_NOTIMPL, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: E_NOTIMPL, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/NotSupportedExceptionTests.cs b/src/libraries/System.Runtime/tests/System/NotSupportedExceptionTests.cs index a5aa0905d74b0..6aa28beffbd87 100644 --- a/src/libraries/System.Runtime/tests/System/NotSupportedExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/NotSupportedExceptionTests.cs @@ -14,7 +14,7 @@ public static class NotSupportedExceptionTests public static void Ctor_Empty() { var exception = new NotSupportedException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_NOTSUPPORTED, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_NOTSUPPORTED, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "not supported"; var exception = new NotSupportedException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_NOTSUPPORTED, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_NOTSUPPORTED, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "not supported"; var innerException = new Exception("Inner exception"); var exception = new NotSupportedException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_NOTSUPPORTED, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_NOTSUPPORTED, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/ObjectDisposedExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ObjectDisposedExceptionTests.cs index 8345a782fe7bc..4334b9f29c690 100644 --- a/src/libraries/System.Runtime/tests/System/ObjectDisposedExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ObjectDisposedExceptionTests.cs @@ -15,7 +15,7 @@ public static void Ctor_String() { string objectName = "theObject"; var exception = new ObjectDisposedException(objectName); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OBJECTDISPOSED, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OBJECTDISPOSED, validateMessage: false); Assert.Contains(objectName, exception.Message); var exceptionNullObjectName = new ObjectDisposedException(null); @@ -28,7 +28,7 @@ public static void Ctor_String_Exception() string message = "object disposed"; var innerException = new Exception("Inner exception"); var exception = new ObjectDisposedException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OBJECTDISPOSED, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OBJECTDISPOSED, innerException: innerException, message: message); Assert.Equal("", exception.ObjectName); } @@ -38,7 +38,7 @@ public static void Ctor_String_String() string message = "object disposed"; string objectName = "theObject"; var exception = new ObjectDisposedException(objectName, message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OBJECTDISPOSED, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OBJECTDISPOSED, validateMessage: false); Assert.Equal(objectName, exception.ObjectName); Assert.Contains(message, exception.Message); Assert.Contains(objectName, exception.Message); diff --git a/src/libraries/System.Runtime/tests/System/OutOfMemoryExceptionTests.cs b/src/libraries/System.Runtime/tests/System/OutOfMemoryExceptionTests.cs index 39c3fd1e9b6a2..7585bceb30528 100644 --- a/src/libraries/System.Runtime/tests/System/OutOfMemoryExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/OutOfMemoryExceptionTests.cs @@ -14,7 +14,7 @@ public static class OutOfMemoryExceptionTests public static void Ctor_Empty() { var exception = new OutOfMemoryException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OUTOFMEMORY, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OUTOFMEMORY, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "out of memory"; var exception = new OutOfMemoryException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OUTOFMEMORY, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OUTOFMEMORY, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "out of memory"; var innerException = new Exception("Inner exception"); var exception = new OutOfMemoryException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OUTOFMEMORY, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OUTOFMEMORY, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/OverflowExceptionTests.cs b/src/libraries/System.Runtime/tests/System/OverflowExceptionTests.cs index 2c239b180c6a3..348fc7b15aa99 100644 --- a/src/libraries/System.Runtime/tests/System/OverflowExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/OverflowExceptionTests.cs @@ -14,7 +14,7 @@ public static class OverflowExceptionTests public static void Ctor_Empty() { var exception = new OverflowException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OVERFLOW, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OVERFLOW, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "overflow"; var exception = new OverflowException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OVERFLOW, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OVERFLOW, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "overflow"; var innerException = new Exception("Inner exception"); var exception = new OverflowException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_OVERFLOW, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_OVERFLOW, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/PlatformNotSupportedExceptionTests.cs b/src/libraries/System.Runtime/tests/System/PlatformNotSupportedExceptionTests.cs index 1e0fc9452e969..0897004bd2cce 100644 --- a/src/libraries/System.Runtime/tests/System/PlatformNotSupportedExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/PlatformNotSupportedExceptionTests.cs @@ -14,7 +14,7 @@ public static class PlatformNotSupportedExceptionTests public static void Ctor_Empty() { var exception = new PlatformNotSupportedException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_PLATFORMNOTSUPPORTED, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_PLATFORMNOTSUPPORTED, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "platform not supported"; var exception = new PlatformNotSupportedException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_PLATFORMNOTSUPPORTED, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_PLATFORMNOTSUPPORTED, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "platform not supported"; var innerException = new Exception("Inner exception"); var exception = new PlatformNotSupportedException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_PLATFORMNOTSUPPORTED, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_PLATFORMNOTSUPPORTED, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/RankExceptionTests.cs b/src/libraries/System.Runtime/tests/System/RankExceptionTests.cs index 6a3bad220dcdd..6da6e3f614f58 100644 --- a/src/libraries/System.Runtime/tests/System/RankExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/RankExceptionTests.cs @@ -14,7 +14,7 @@ public static class RankExceptionTests public static void Ctor_Empty() { var exception = new RankException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_RANK, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_RANK, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "bad rank"; var exception = new RankException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_RANK, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_RANK, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "bad rank"; var innerException = new Exception("Inner exception"); var exception = new RankException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_RANK, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_RANK, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/Security/SecurityExceptionTests.cs b/src/libraries/System.Runtime/tests/System/Security/SecurityExceptionTests.cs index 57596cb863b8b..f6462cb5ca332 100644 --- a/src/libraries/System.Runtime/tests/System/Security/SecurityExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/Security/SecurityExceptionTests.cs @@ -17,7 +17,7 @@ public static class SecurityExceptionTests public static void Ctor_Empty() { var exception = new SecurityException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, validateMessage: false); } [Fact] @@ -25,7 +25,7 @@ public static void Ctor_String() { string message = "security problem"; var exception = new SecurityException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, message: message); } [Fact] @@ -34,7 +34,7 @@ public static void Ctor_String_Exception() string message = "security problem"; var innerException = new Exception("Inner exception"); var exception = new SecurityException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, innerException: innerException, message: message); } [Fact] @@ -42,7 +42,7 @@ public static void Ctor_String_Type() { string message = "security problem"; var exception = new SecurityException(message, typeof(SecurityExceptionTests)); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, message: message); Assert.Equal(typeof(SecurityExceptionTests), exception.PermissionType); } @@ -51,7 +51,7 @@ public static void Ctor_String_Type_String() { string message = "security problem"; var exception = new SecurityException(message, typeof(SecurityExceptionTests), "permission state"); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_SECURITY, message: message); Assert.Equal(typeof(SecurityExceptionTests), exception.PermissionType); Assert.Equal("permission state", exception.PermissionState); } diff --git a/src/libraries/System.Runtime/tests/System/TimeoutExceptionTests.cs b/src/libraries/System.Runtime/tests/System/TimeoutExceptionTests.cs index 652fe1f0b238e..3a4a9722441b8 100644 --- a/src/libraries/System.Runtime/tests/System/TimeoutExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeoutExceptionTests.cs @@ -14,7 +14,7 @@ public static class TimeoutExceptionTests public static void Ctor_Empty() { var exception = new TimeoutException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_TIMEOUT, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_TIMEOUT, validateMessage: false); } [Fact] @@ -22,7 +22,7 @@ public static void Ctor_String() { string message = "timeout"; var exception = new TimeoutException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_TIMEOUT, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_TIMEOUT, message: message); } [Fact] @@ -31,7 +31,7 @@ public static void Ctor_String_Exception() string message = "timeout"; var innerException = new Exception("Inner exception"); var exception = new TimeoutException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_TIMEOUT, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_TIMEOUT, innerException: innerException, message: message); } } } diff --git a/src/libraries/System.Runtime/tests/System/Type/TypeTests.Get.cs b/src/libraries/System.Runtime/tests/System/Type/TypeTests.Get.cs index 124687962d0f0..9e3e3d2c2372d 100644 --- a/src/libraries/System.Runtime/tests/System/Type/TypeTests.Get.cs +++ b/src/libraries/System.Runtime/tests/System/Type/TypeTests.Get.cs @@ -71,7 +71,7 @@ public void GetInterface_Invoke_ReturnsExpected(Type type, string name, bool ign [Fact] public void GetInterface_NullName_ThrowsArgumentNullException() { - AssertExtensions.Throws(null, () => typeof(int).GetInterface(null)); + AssertExtensions.Throws("fullname", () => typeof(int).GetInterface(null)); } [Fact] @@ -91,12 +91,6 @@ public void GetInterface_MixedCaseAmbiguity_ThrowsAmbiguousMatchException() { Assert.Throws(() => typeof(ClassWithMixedCaseInterfaces).GetInterface("mixedinterface", ignoreCase: true)); } - - [Fact] - public void GetCustomAttributes_Interface() - { - Assert.True(typeof(ExampleWithAttribute).GetCustomAttributes(typeof(INameable), inherit: false)[0] is NameableAttribute); - } } public class ClassWithNoInterfaces { } @@ -122,20 +116,6 @@ public interface Interface1 { } public interface Interface2 { } public interface Interface3 { } } - - public interface INameable - { - string Name { get; } - } - - [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] - public class NameableAttribute : Attribute, INameable - { - string INameable.Name => "Nameable"; - } - - [Nameable] - public class ExampleWithAttribute { } } public interface Interface1 { } diff --git a/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs b/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs index 7f8cd6368d03c..d45b52c90c57c 100644 --- a/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs +++ b/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs @@ -688,6 +688,8 @@ public static IEnumerable GetInterfaceMap_TestData() [Theory] [MemberData(nameof(GetInterfaceMap_TestData))] + // Android-only, change to TestPlatforms.Android once arcade dependency is updated + [ActiveIssue("https://github.com/dotnet/runtime/issues/36653", TestRuntimes.Mono)] public void GetInterfaceMap(Type interfaceType, Type classType, Tuple[] expectedMap) { InterfaceMapping actualMapping = classType.GetInterfaceMap(interfaceType); diff --git a/src/libraries/System.Runtime/tests/System/TypeLoadExceptionTests.cs b/src/libraries/System.Runtime/tests/System/TypeLoadExceptionTests.cs index 2fe5e13fd7649..31e80b39ef20e 100644 --- a/src/libraries/System.Runtime/tests/System/TypeLoadExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/TypeLoadExceptionTests.cs @@ -15,7 +15,7 @@ public static class TypeLoadExceptionTests public static void Ctor_Empty() { var exception = new TypeLoadException(); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_TYPELOAD, validateMessage: false); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_TYPELOAD, validateMessage: false); Assert.Equal("", exception.TypeName); } @@ -24,7 +24,7 @@ public static void Ctor_String() { string message = "type failed to load"; var exception = new TypeLoadException(message); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_TYPELOAD, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_TYPELOAD, message: message); Assert.Equal("", exception.TypeName); } @@ -34,7 +34,7 @@ public static void Ctor_String_Exception() string message = "type failed to load"; var innerException = new Exception("Inner exception"); var exception = new TypeLoadException(message, innerException); - ExceptionUtility.ValidateExceptionProperties(exception, hResult: COR_E_TYPELOAD, innerException: innerException, message: message); + ExceptionHelpers.ValidateExceptionProperties(exception, hResult: COR_E_TYPELOAD, innerException: innerException, message: message); Assert.Equal("", exception.TypeName); } } diff --git a/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/CommonObjectSecurity.cs b/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/CommonObjectSecurity.cs index 1ff7c7c416486..a1665aa92070c 100644 --- a/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/CommonObjectSecurity.cs +++ b/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/CommonObjectSecurity.cs @@ -336,7 +336,7 @@ protected override bool ModifyAccess(AccessControlModification modification, Acc else { Debug.Fail("rule.AccessControlType unrecognized"); - throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)rule.AccessControlType), "rule.AccessControlType"); + throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)rule.AccessControlType), nameof(rule)); } modified = result; diff --git a/src/libraries/System.Security.Claims/src/ILLinkTrim.xml b/src/libraries/System.Security.Claims/src/ILLinkTrim_LibraryBuild.xml similarity index 100% rename from src/libraries/System.Security.Claims/src/ILLinkTrim.xml rename to src/libraries/System.Security.Claims/src/ILLinkTrim_LibraryBuild.xml diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Helpers.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Helpers.cs index 5ca3a10cf788f..1d3c1db2b877c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Helpers.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Helpers.cs @@ -39,21 +39,6 @@ public static byte[] GenerateRandom(int count) return buffer; } - // encodes the integer i into a 4-byte array, in big endian. - public static void WriteInt(uint i, byte[] arr, int offset) - { - unchecked - { - Debug.Assert(arr != null); - Debug.Assert(arr.Length >= offset + sizeof(uint)); - - arr[offset] = (byte)(i >> 24); - arr[offset + 1] = (byte)(i >> 16); - arr[offset + 2] = (byte)(i >> 8); - arr[offset + 3] = (byte)i; - } - } - public static byte[] FixupKeyParity(this byte[] key) { byte[] oddParityKey = new byte[key.Length]; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx index 76aed28615e9a..6e731527ea232 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx @@ -199,10 +199,10 @@ Input string does not contain a valid encoding of the '{0}' '{1}' parameter. - The specified Characteristic2 curve parameters are not valid. Polynomial, A, B, G.X, G.Y, and Order are required. A, B, G.X, G.Y must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Seed, Cofactor and Hash are optional. Other parameters are not allowed. + The specified Characteristic2 curve parameters are not valid. Polynomial, A, B, G.X, G.Y, and Order are required. A, B, G.X, G.Y must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Cofactor is required. Seed and Hash are optional. Other parameters are not allowed. - The specified prime curve parameters are not valid. Prime, A, B, G.X, G.Y and Order are required and must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Seed, Cofactor and Hash are optional. Other parameters are not allowed. + The specified prime curve parameters are not valid. Prime, A, B, G.X, G.Y and Order are required and must be the same length, and the same length as Q.X, Q.Y and D if those are specified. Cofactor is required. Seed and Hash are optional. Other parameters are not allowed. The specified named curve parameters are not valid. Only the Oid parameter must be set. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index 0a126fc83ceb2..da598436fea91 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -477,8 +477,8 @@ Link="Common\System\Security\Cryptography\RSAOpenSsl.cs" /> - - + + diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs index 3d9583c02f76f..3614db5655489 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs @@ -38,8 +38,6 @@ public class CryptoConfig private static readonly ConcurrentDictionary appNameHT = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary appOidHT = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - private static readonly char[] SepArray = { '.' }; // valid ASN.1 separators - // .NET Core does not support AllowOnlyFipsAlgorithms public static bool AllowOnlyFipsAlgorithms => false; @@ -503,7 +501,7 @@ public static byte[] EncodeOID(string str) if (str == null) throw new ArgumentNullException(nameof(str)); - string[] oidString = str.Split(SepArray); + string[] oidString = str.Split('.'); // valid ASN.1 separator uint[] oidNums = new uint[oidString.Length]; for (int i = 0; i < oidString.Length; i++) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DES.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DES.cs index 443cc84d79b75..8ad67820c8fde 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DES.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DES.cs @@ -4,6 +4,7 @@ using Internal.Cryptography; using System.ComponentModel; +using System.Buffers.Binary; namespace System.Security.Cryptography { @@ -65,7 +66,7 @@ public static bool IsWeakKey(byte[] rgbKey) throw new CryptographicException(SR.Cryptography_InvalidKeySize); byte[] rgbOddParityKey = rgbKey.FixupKeyParity(); - ulong key = QuadWordFromBigEndian(rgbOddParityKey); + ulong key = BinaryPrimitives.ReadUInt64BigEndian(rgbOddParityKey); if ((key == 0x0101010101010101) || (key == 0xfefefefefefefefe) || (key == 0x1f1f1f1f0e0e0e0e) || @@ -83,7 +84,7 @@ public static bool IsSemiWeakKey(byte[] rgbKey) throw new CryptographicException(SR.Cryptography_InvalidKeySize); byte[] rgbOddParityKey = rgbKey.FixupKeyParity(); - ulong key = QuadWordFromBigEndian(rgbOddParityKey); + ulong key = BinaryPrimitives.ReadUInt64BigEndian(rgbOddParityKey); if ((key == 0x01fe01fe01fe01fe) || (key == 0xfe01fe01fe01fe01) || (key == 0x1fe01fe00ef10ef1) || @@ -111,17 +112,6 @@ private static bool IsLegalKeySize(byte[]? rgbKey) return false; } - private static ulong QuadWordFromBigEndian(byte[] block) - { - ulong x = ( - (((ulong)block[0]) << 56) | (((ulong)block[1]) << 48) | - (((ulong)block[2]) << 40) | (((ulong)block[3]) << 32) | - (((ulong)block[4]) << 24) | (((ulong)block[5]) << 16) | - (((ulong)block[6]) << 8) | ((ulong)block[7]) - ); - return x; - } - private static readonly KeySizes[] s_legalBlockSizes = { new KeySizes(minSize: 64, maxSize: 64, skipSize: 0) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Xml.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Xml.cs index cfa242d50fb96..f32e384c70e94 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Xml.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Xml.cs @@ -127,10 +127,12 @@ public override string ToXmlString(bool includePrivateParameters) { if (keyParameters.X == null) { +#pragma warning disable CA2208 // Instantiate argument exceptions correctly // .NET Framework compat when a 3rd party type lets X be null when // includePrivateParameters is true // (the exception would have been from Convert.ToBase64String) throw new ArgumentNullException("inArray"); +#pragma warning restore CA2208 } XmlKeyHelper.WriteCryptoBinary(nameof(DSAParameters.X), keyParameters.X, builder); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs index 61c4fa1bd8dc6..42c67d78f91b8 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Buffers.Binary; using System.Text; using System.Diagnostics; @@ -258,7 +259,7 @@ private void Initialize() // where i is the block number. private void Func() { - Helpers.WriteInt(_block, _salt, _salt.Length - sizeof(uint)); + BinaryPrimitives.WriteUInt32BigEndian(_salt.AsSpan(_salt.Length - sizeof(uint)), _block); Debug.Assert(_blockSize == _buffer.Length); // The biggest _blockSize we have is from SHA512, which is 64 bytes. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/XmlKeyHelper.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/XmlKeyHelper.cs index 9012886b3ed08..a8d3460c1369b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/XmlKeyHelper.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/XmlKeyHelper.cs @@ -267,12 +267,12 @@ private static class Functions { private static readonly Type s_xDocument = Type.GetType("System.Xml.Linq.XDocument, System.Private.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51")!; private static readonly Func s_xDocumentCreate = - (Func)s_xDocument.GetMethod( + s_xDocument.GetMethod( "Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, - null)!.CreateDelegate(typeof(Func)); + null)!.CreateDelegate>(); private static readonly PropertyInfo s_docRootProperty = s_xDocument.GetProperty("Root")!; private static readonly MethodInfo s_getElementsMethod = s_docRootProperty.PropertyType.GetMethod( "Elements", diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs index 8deeddfc746a0..983fbd9ac26f8 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.Windows.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Buffers.Binary; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; @@ -750,7 +751,7 @@ private static void ValidateCspFlags(CspProviderFlags flags) // check that this is indeed an RSA/DSS key. byte[] algid = CapiHelper.GetKeyParameter(hKey, Constants.CLR_ALGID); - int dwAlgId = (algid[0] | (algid[1] << 8) | (algid[2] << 16) | (algid[3] << 24)); + int dwAlgId = BinaryPrimitives.ReadInt32LittleEndian(algid); if ((keyType == CspAlgorithmType.Rsa && dwAlgId != CALG_RSA_KEYX && dwAlgId != CALG_RSA_SIGN) || (keyType == CspAlgorithmType.Dss && dwAlgId != CALG_DSS_SIGN)) diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs index ed51902db8a0f..567ce989bd7a5 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Windows.cs @@ -2,6 +2,7 @@ // 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.Buffers.Binary; using System.Diagnostics; using System.IO; using Internal.NativeCrypto; @@ -200,7 +201,7 @@ public override int KeySize get { byte[] keySize = CapiHelper.GetKeyParameter(SafeKeyHandle, Constants.CLR_KEYLEN); - _keySize = (keySize[0] | (keySize[1] << 8) | (keySize[2] << 16) | (keySize[3] << 24)); + _keySize = BinaryPrimitives.ReadInt32LittleEndian(keySize); return _keySize; } } diff --git a/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.OSX.cs b/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.OSX.cs index ee9cbb6c5b9a9..fb055ca797c13 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.OSX.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.OSX.cs @@ -67,6 +67,16 @@ private static bool ShouldUseCache(OidGroup oidGroup) private static readonly Dictionary s_extraOidToFriendlyName = InvertWithDefaultComparer(s_extraFriendlyNameToOid); + private static Dictionary InvertWithDefaultComparer(Dictionary source) + { + var result = new Dictionary(source.Count); + foreach (KeyValuePair item in source) + { + result.Add(item.Value, item.Key); + } + return result; + } + #if DEBUG static partial void ExtraStaticDebugValidation() { diff --git a/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.cs b/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.cs index ca743d28adbcf..e852b14a020ad 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/src/Internal/Cryptography/OidLookup.cs @@ -94,132 +94,16 @@ internal static partial class OidLookup } /// Expected size of . - private const int FriendlyNameToOidCount = 103; + private const int FriendlyNameToOidCount = 110; + + /// Expected size of . + private const int OidToFriendlyNameCount = 103; - // This table was originally built by extracting every szOID #define out of wincrypt.h, - // and running them through new Oid(string) on Windows 10. Then, take the list of everything - // which produced a FriendlyName value, and run it through two other languages. If all 3 agree - // on the mapping, consider the value to be non-localized. - // - // This original list was produced on English (Win10), cross-checked with Spanish (Win8.1) and - // Japanese (Win10). - // - // Sometimes wincrypt.h has more than one OID which results in the same name. The OIDs whose value - // doesn't roundtrip (new Oid(new Oid(value).FriendlyName).Value) are contained in s_compatOids. - // - // X-Plat: The names (and casing) in this table come from Windows. Part of the intent of this table - // is to prevent issues wherein an identifier is different between Windows and Unix; - // since any existing code would be using the Windows identifier, it is the de facto standard. private static readonly Dictionary s_friendlyNameToOid = - new Dictionary(FriendlyNameToOidCount, StringComparer.OrdinalIgnoreCase) - { - { "3des", "1.2.840.113549.3.7" }, - { "aes128", "2.16.840.1.101.3.4.1.2" }, - { "aes128wrap", "2.16.840.1.101.3.4.1.5" }, - { "aes192", "2.16.840.1.101.3.4.1.22" }, - { "aes192wrap", "2.16.840.1.101.3.4.1.25" }, - { "aes256", "2.16.840.1.101.3.4.1.42" }, - { "aes256wrap", "2.16.840.1.101.3.4.1.45" }, - { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" }, - { "brainpoolP160t1", "1.3.36.3.3.2.8.1.1.2" }, - { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" }, - { "brainpoolP192t1", "1.3.36.3.3.2.8.1.1.4" }, - { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" }, - { "brainpoolP224t1", "1.3.36.3.3.2.8.1.1.6" }, - { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" }, - { "brainpoolP256t1", "1.3.36.3.3.2.8.1.1.8" }, - { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" }, - { "brainpoolP320t1", "1.3.36.3.3.2.8.1.1.10" }, - { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11" }, - { "brainpoolP384t1", "1.3.36.3.3.2.8.1.1.12" }, - { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13" }, - { "brainpoolP512t1", "1.3.36.3.3.2.8.1.1.14" }, - { "C", "2.5.4.6" }, - { "CMS3DESwrap", "1.2.840.113549.1.9.16.3.6" }, - { "CMSRC2wrap", "1.2.840.113549.1.9.16.3.7" }, - { "CN", "2.5.4.3" }, - { "CPS", "1.3.6.1.5.5.7.2.1" }, - { "DC", "0.9.2342.19200300.100.1.25" }, - { "des", "1.3.14.3.2.7" }, - { "Description", "2.5.4.13" }, - { "DH", "1.2.840.10046.2.1" }, - { "dnQualifier", "2.5.4.46" }, - { "DSA", "1.2.840.10040.4.1" }, - { "dsaSHA1", "1.3.14.3.2.27" }, - { "E", "1.2.840.113549.1.9.1" }, - { "ec192wapi", "1.2.156.11235.1.1.2.1" }, - { "ECC", "1.2.840.10045.2.1" }, - { "ECDH_STD_SHA1_KDF", "1.3.133.16.840.63.0.2" }, - { "ECDH_STD_SHA256_KDF", "1.3.132.1.11.1" }, - { "ECDH_STD_SHA384_KDF", "1.3.132.1.11.2" }, - { "ECDSA_P256", "1.2.840.10045.3.1.7" }, - { "ECDSA_P384", "1.3.132.0.34" }, - { "ECDSA_P521", "1.3.132.0.35" }, - { "ESDH", "1.2.840.113549.1.9.16.3.5" }, - { "G", "2.5.4.42" }, - { "I", "2.5.4.43" }, - { "L", "2.5.4.7" }, - { "md2", "1.2.840.113549.2.2" }, - { "md2RSA", "1.2.840.113549.1.1.2" }, - { "md4", "1.2.840.113549.2.4" }, - { "md4RSA", "1.2.840.113549.1.1.3" }, - { "md5", "1.2.840.113549.2.5" }, - { "md5RSA", "1.2.840.113549.1.1.4" }, - { "mgf1", "1.2.840.113549.1.1.8" }, - { "mosaicKMandUpdSig", "2.16.840.1.101.2.1.1.20" }, - { "mosaicUpdatedSig", "2.16.840.1.101.2.1.1.19" }, - { "nistP192", "1.2.840.10045.3.1.1" }, - { "nistP224", "1.3.132.0.33" }, - { "NO_SIGN", "1.3.6.1.5.5.7.6.2" }, - { "O", "2.5.4.10" }, - { "OU", "2.5.4.11" }, - { "Phone", "2.5.4.20" }, - { "POBox", "2.5.4.18" }, - { "PostalCode", "2.5.4.17" }, - { "rc2", "1.2.840.113549.3.2" }, - { "rc4", "1.2.840.113549.3.4" }, - { "RSA", "1.2.840.113549.1.1.1" }, - { "RSAES_OAEP", "1.2.840.113549.1.1.7" }, - { "RSASSA-PSS", "1.2.840.113549.1.1.10" }, - { "S", "2.5.4.8" }, - { "secP160k1", "1.3.132.0.9" }, - { "secP160r1", "1.3.132.0.8" }, - { "secP160r2", "1.3.132.0.30" }, - { "secP192k1", "1.3.132.0.31" }, - { "secP224k1", "1.3.132.0.32" }, - { "secP256k1", "1.3.132.0.10" }, - { "SERIALNUMBER", "2.5.4.5" }, - { "sha1", "1.3.14.3.2.26" }, - { "sha1DSA", "1.2.840.10040.4.3" }, - { "sha1ECDSA", "1.2.840.10045.4.1" }, - { "sha1RSA", "1.2.840.113549.1.1.5" }, - { "sha256", "2.16.840.1.101.3.4.2.1" }, - { "sha256ECDSA", "1.2.840.10045.4.3.2" }, - { "sha256RSA", "1.2.840.113549.1.1.11" }, - { "sha384", "2.16.840.1.101.3.4.2.2" }, - { "sha384ECDSA", "1.2.840.10045.4.3.3" }, - { "sha384RSA", "1.2.840.113549.1.1.12" }, - { "sha512", "2.16.840.1.101.3.4.2.3" }, - { "sha512ECDSA", "1.2.840.10045.4.3.4" }, - { "sha512RSA", "1.2.840.113549.1.1.13" }, - { "SN", "2.5.4.4" }, - { "specifiedECDSA", "1.2.840.10045.4.3" }, - { "STREET", "2.5.4.9" }, - { "T", "2.5.4.12" }, - { "TPMManufacturer", "2.23.133.2.1" }, - { "TPMModel", "2.23.133.2.2" }, - { "TPMVersion", "2.23.133.2.3" }, - { "wtls9", "2.23.43.1.4.9" }, - { "X21Address", "2.5.4.24" }, - { "x962P192v2", "1.2.840.10045.3.1.2" }, - { "x962P192v3", "1.2.840.10045.3.1.3" }, - { "x962P239v1", "1.2.840.10045.3.1.4" }, - { "x962P239v2", "1.2.840.10045.3.1.5" }, - { "x962P239v3", "1.2.840.10045.3.1.6" }, - }; + new Dictionary(FriendlyNameToOidCount, StringComparer.OrdinalIgnoreCase); private static readonly Dictionary s_oidToFriendlyName = - InvertWithDefaultComparer(s_friendlyNameToOid); + new Dictionary(OidToFriendlyNameCount, StringComparer.Ordinal); private static readonly Dictionary s_compatOids = new Dictionary @@ -237,29 +121,155 @@ internal static partial class OidLookup { "1.3.14.7.2.3.1", "md2RSA" }, }; - private static Dictionary InvertWithDefaultComparer(Dictionary source) - { - var result = new Dictionary(source.Count); - foreach (KeyValuePair item in source) - { - result.Add(item.Value, item.Key); - } - return result; - } - -#if DEBUG static OidLookup() { + InitializeLookupDictionaries(); +#if DEBUG // Validate we hardcoded the right dictionary size Debug.Assert(s_friendlyNameToOid.Count == FriendlyNameToOidCount, $"Expected {nameof(s_friendlyNameToOid)}.{nameof(s_friendlyNameToOid.Count)} == {FriendlyNameToOidCount}, got {s_friendlyNameToOid.Count}"); - Debug.Assert(s_oidToFriendlyName.Count == FriendlyNameToOidCount, - $"Expected {nameof(s_oidToFriendlyName)}.{nameof(s_oidToFriendlyName.Count)} == {FriendlyNameToOidCount}, got {s_oidToFriendlyName.Count}"); + Debug.Assert(s_oidToFriendlyName.Count == OidToFriendlyNameCount, + $"Expected {nameof(s_oidToFriendlyName)}.{nameof(s_oidToFriendlyName.Count)} == {OidToFriendlyNameCount}, got {s_oidToFriendlyName.Count}"); ExtraStaticDebugValidation(); +#endif + } + + private static void InitializeLookupDictionaries() + { + void AddEntry(string oid, string primaryFriendlyName, string[]? additionalFriendlyNames = null) + { + s_oidToFriendlyName.Add(oid, primaryFriendlyName); + s_friendlyNameToOid.Add(primaryFriendlyName, oid); + + if (additionalFriendlyNames != null) + { + foreach (var additionalName in additionalFriendlyNames) + { + s_friendlyNameToOid.Add(additionalName, oid); + } + } + } + + // This lookup was originally built by extracting every szOID #define out of wincrypt.h, + // and running them through new Oid(string) on Windows 10. Then, take the list of everything + // which produced a FriendlyName value, and run it through two other languages. If all 3 agree + // on the mapping, consider the value to be non-localized. + // + // This original list was produced on English (Win10), cross-checked with Spanish (Win8.1) and + // Japanese (Win10). + // + // Sometimes wincrypt.h has more than one OID which results in the same name. The OIDs whose value + // doesn't roundtrip (new Oid(new Oid(value).FriendlyName).Value) are contained in s_compatOids. + // + // X-Plat: The names (and casing) in this table come from Windows. Part of the intent of this table + // is to prevent issues wherein an identifier is different between Windows and Unix; + // since any existing code would be using the Windows identifier, it is the de facto standard. + AddEntry("1.2.840.113549.3.7", "3des"); + AddEntry("2.16.840.1.101.3.4.1.2", "aes128"); + AddEntry("2.16.840.1.101.3.4.1.5", "aes128wrap"); + AddEntry("2.16.840.1.101.3.4.1.22", "aes192"); + AddEntry("2.16.840.1.101.3.4.1.25", "aes192wrap"); + AddEntry("2.16.840.1.101.3.4.1.42", "aes256"); + AddEntry("2.16.840.1.101.3.4.1.45", "aes256wrap"); + AddEntry("1.3.36.3.3.2.8.1.1.1", "brainpoolP160r1"); + AddEntry("1.3.36.3.3.2.8.1.1.2", "brainpoolP160t1"); + AddEntry("1.3.36.3.3.2.8.1.1.3", "brainpoolP192r1"); + AddEntry("1.3.36.3.3.2.8.1.1.4", "brainpoolP192t1"); + AddEntry("1.3.36.3.3.2.8.1.1.5", "brainpoolP224r1"); + AddEntry("1.3.36.3.3.2.8.1.1.6", "brainpoolP224t1"); + AddEntry("1.3.36.3.3.2.8.1.1.7", "brainpoolP256r1"); + AddEntry("1.3.36.3.3.2.8.1.1.8", "brainpoolP256t1"); + AddEntry("1.3.36.3.3.2.8.1.1.9", "brainpoolP320r1"); + AddEntry("1.3.36.3.3.2.8.1.1.10", "brainpoolP320t1"); + AddEntry("1.3.36.3.3.2.8.1.1.11", "brainpoolP384r1"); + AddEntry("1.3.36.3.3.2.8.1.1.12", "brainpoolP384t1"); + AddEntry("1.3.36.3.3.2.8.1.1.13", "brainpoolP512r1"); + AddEntry("1.3.36.3.3.2.8.1.1.14", "brainpoolP512t1"); + AddEntry("2.5.4.6", "C"); + AddEntry("1.2.840.113549.1.9.16.3.6", "CMS3DESwrap"); + AddEntry("1.2.840.113549.1.9.16.3.7", "CMSRC2wrap"); + AddEntry("2.5.4.3", "CN"); + AddEntry("1.3.6.1.5.5.7.2.1", "CPS"); + AddEntry("0.9.2342.19200300.100.1.25", "DC"); + AddEntry("1.3.14.3.2.7", "des"); + AddEntry("2.5.4.13", "Description"); + AddEntry("1.2.840.10046.2.1", "DH"); + AddEntry("2.5.4.46", "dnQualifier"); + AddEntry("1.2.840.10040.4.1", "DSA"); + AddEntry("1.3.14.3.2.27", "dsaSHA1"); + AddEntry("1.2.840.113549.1.9.1", "E"); + AddEntry("1.2.156.11235.1.1.2.1", "ec192wapi"); + AddEntry("1.2.840.10045.2.1", "ECC"); + AddEntry("1.3.133.16.840.63.0.2", "ECDH_STD_SHA1_KDF"); + AddEntry("1.3.132.1.11.1", "ECDH_STD_SHA256_KDF"); + AddEntry("1.3.132.1.11.2", "ECDH_STD_SHA384_KDF"); + AddEntry("1.2.840.10045.3.1.7", "ECDSA_P256", new[] { "nistP256", "secP256r1", "x962P256v1" } ); + AddEntry("1.3.132.0.34", "ECDSA_P384", new[] { "nistP384", "secP384r1" }); + AddEntry("1.3.132.0.35", "ECDSA_P521", new[] { "nistP521", "secP521r1" }); + AddEntry("1.2.840.113549.1.9.16.3.5", "ESDH"); + AddEntry("2.5.4.42", "G"); + AddEntry("2.5.4.43", "I"); + AddEntry("2.5.4.7", "L"); + AddEntry("1.2.840.113549.2.2", "md2"); + AddEntry("1.2.840.113549.1.1.2", "md2RSA"); + AddEntry("1.2.840.113549.2.4", "md4"); + AddEntry("1.2.840.113549.1.1.3", "md4RSA"); + AddEntry("1.2.840.113549.2.5", "md5"); + AddEntry("1.2.840.113549.1.1.4", "md5RSA"); + AddEntry("1.2.840.113549.1.1.8", "mgf1"); + AddEntry("2.16.840.1.101.2.1.1.20", "mosaicKMandUpdSig"); + AddEntry("2.16.840.1.101.2.1.1.19", "mosaicUpdatedSig"); + AddEntry("1.2.840.10045.3.1.1", "nistP192"); + AddEntry("1.3.132.0.33", "nistP224"); + AddEntry("1.3.6.1.5.5.7.6.2", "NO_SIGN"); + AddEntry("2.5.4.10", "O"); + AddEntry("2.5.4.11", "OU"); + AddEntry("2.5.4.20", "Phone"); + AddEntry("2.5.4.18", "POBox"); + AddEntry("2.5.4.17", "PostalCode"); + AddEntry("1.2.840.113549.3.2", "rc2"); + AddEntry("1.2.840.113549.3.4", "rc4"); + AddEntry("1.2.840.113549.1.1.1", "RSA"); + AddEntry("1.2.840.113549.1.1.7", "RSAES_OAEP"); + AddEntry("1.2.840.113549.1.1.10", "RSASSA-PSS"); + AddEntry("2.5.4.8", "S"); + AddEntry("1.3.132.0.9", "secP160k1"); + AddEntry("1.3.132.0.8", "secP160r1"); + AddEntry("1.3.132.0.30", "secP160r2"); + AddEntry("1.3.132.0.31", "secP192k1"); + AddEntry("1.3.132.0.32", "secP224k1"); + AddEntry("1.3.132.0.10", "secP256k1"); + AddEntry("2.5.4.5", "SERIALNUMBER"); + AddEntry("1.3.14.3.2.26", "sha1"); + AddEntry("1.2.840.10040.4.3", "sha1DSA"); + AddEntry("1.2.840.10045.4.1", "sha1ECDSA"); + AddEntry("1.2.840.113549.1.1.5", "sha1RSA"); + AddEntry("2.16.840.1.101.3.4.2.1", "sha256"); + AddEntry("1.2.840.10045.4.3.2", "sha256ECDSA"); + AddEntry("1.2.840.113549.1.1.11", "sha256RSA"); + AddEntry("2.16.840.1.101.3.4.2.2", "sha384"); + AddEntry("1.2.840.10045.4.3.3", "sha384ECDSA"); + AddEntry("1.2.840.113549.1.1.12", "sha384RSA"); + AddEntry("2.16.840.1.101.3.4.2.3", "sha512"); + AddEntry("1.2.840.10045.4.3.4", "sha512ECDSA"); + AddEntry("1.2.840.113549.1.1.13", "sha512RSA"); + AddEntry("2.5.4.4", "SN"); + AddEntry("1.2.840.10045.4.3", "specifiedECDSA"); + AddEntry("2.5.4.9", "STREET"); + AddEntry("2.5.4.12", "T"); + AddEntry("2.23.133.2.1", "TPMManufacturer"); + AddEntry("2.23.133.2.2", "TPMModel"); + AddEntry("2.23.133.2.3", "TPMVersion"); + AddEntry("2.23.43.1.4.9", "wtls9"); + AddEntry("2.5.4.24", "X21Address"); + AddEntry("1.2.840.10045.3.1.2", "x962P192v2"); + AddEntry("1.2.840.10045.3.1.3", "x962P192v3"); + AddEntry("1.2.840.10045.3.1.4", "x962P239v1"); + AddEntry("1.2.840.10045.3.1.5", "x962P239v2"); + AddEntry("1.2.840.10045.3.1.6", "x962P239v3"); } static partial void ExtraStaticDebugValidation(); -#endif } } diff --git a/src/libraries/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/PemEncoding.cs b/src/libraries/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/PemEncoding.cs index 7232a72205c9c..711b323136b08 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/PemEncoding.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/PemEncoding.cs @@ -88,7 +88,7 @@ public static bool TryFind(ReadOnlySpan pemData, out PemFields fields) // must be a white space character. if (preebIndex > 0 && !IsWhiteSpaceCharacter(pemData[preebIndex - 1])) { - areaOffset += labelStartIndex; + areaOffset = labelStartIndex; continue; } @@ -150,16 +150,16 @@ public static bool TryFind(ReadOnlySpan pemData, out PemFields fields) return true; NextAfterLabel: - if (preebEndIndex <= 0) + if (preebEndIndex <= areaOffset) { // We somehow ended up in a situation where we will advance - // 0 or -1 characters, which means we'll probably end up here again, - // advancing 0 or -1 characters, in a loop. To avoid getting stuck, + // backward or not at all, which means we'll probably end up here again, + // advancing backward, in a loop. To avoid getting stuck, // detect this situation and return. fields = default; return false; } - areaOffset += preebEndIndex; + areaOffset = preebEndIndex; } fields = default; @@ -178,6 +178,7 @@ static ReadOnlySpan WritePostEB(ReadOnlySpan label, Span desti private static int IndexOfByOffset(this ReadOnlySpan str, ReadOnlySpan value, int startPosition) { + Debug.Assert(startPosition <= str.Length); int index = str.Slice(startPosition).IndexOf(value); return index == -1 ? -1 : index + startPosition; } @@ -438,7 +439,7 @@ static int WriteBase64(ReadOnlySpan bytes, Span dest, int offset) if (!success) { Debug.Fail("Convert.TryToBase64Chars failed with a pre-sized buffer"); - throw new ArgumentException(); + throw new ArgumentException(null, nameof(destination)); } return base64Written; @@ -528,7 +529,7 @@ public static char[] Write(ReadOnlySpan label, ReadOnlySpan data) if (!TryWrite(label, data, buffer, out int charsWritten)) { Debug.Fail("TryWrite failed with a pre-sized buffer"); - throw new ArgumentException(); + throw new ArgumentException(null, nameof(data)); } Debug.Assert(charsWritten == encodedSize); diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.cs b/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.cs index 6a86f1572952e..1dbb67d6fe1cf 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; using Test.Cryptography; using Xunit; @@ -182,5 +183,48 @@ public static void InvalidConformanceLevel_ShouldThrowArgumentOutOfRangeExceptio public static IEnumerable EncodedValueInputs => CborReaderTests.SampleCborValues.Select(x => new[] { x }); public static IEnumerable EncodedValueInvalidInputs => CborReaderTests.InvalidCborValues.Select(x => new[] { x }); + + [Theory] + [InlineData("a501020326200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + "65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d", + "1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + "SHA256", "ECDSA_P256")] + [InlineData("a501020338222002215830ed57d8608c5734a5ed5d22026bad8700636823e45297306479beb61a5bd6b04688c34a2f0de51d91064355eef7548bdd22583024376b4fee60ba65db61de54234575eec5d37e1184fbafa1f49d71e1795bba6bda9cbe2ebb815f9b49b371486b38fa1b", + "ed57d8608c5734a5ed5d22026bad8700636823e45297306479beb61a5bd6b04688c34a2f0de51d91064355eef7548bdd", + "24376b4fee60ba65db61de54234575eec5d37e1184fbafa1f49d71e1795bba6bda9cbe2ebb815f9b49b371486b38fa1b", + "SHA384", "ECDSA_P384")] + [InlineData("a50102033823200321584200b03811bef65e330bb974224ec3ab0a5469f038c92177b4171f6f66f91244d4476e016ee77cf7e155a4f73567627b5d72eaf0cb4a6036c6509a6432d7cd6a3b325c2258420114b597b6c271d8435cfa02e890608c93f5bc118ca7f47bf191e9f9e49a22f8a15962315f0729781e1d78b302970c832db2fa8f7f782a33f8e1514950dc7499035f", + "00b03811bef65e330bb974224ec3ab0a5469f038c92177b4171f6f66f91244d4476e016ee77cf7e155a4f73567627b5d72eaf0cb4a6036c6509a6432d7cd6a3b325c", + "0114b597b6c271d8435cfa02e890608c93f5bc118ca7f47bf191e9f9e49a22f8a15962315f0729781e1d78b302970c832db2fa8f7f782a33f8e1514950dc7499035f", + "SHA512", "ECDSA_P521")] + [InlineData("a40102200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + "65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d", + "1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + null, "ECDSA_P256")] + public static void CoseKeyHelpers_ECDsaParseCosePublicKey_HappyPath(string hexEncoding, string hexExpectedQx, string hexExpectedQy, string? expectedHashAlgorithmName, string curveFriendlyName) + { + ECPoint q = new ECPoint() { X = hexExpectedQx.HexToByteArray(), Y = hexExpectedQy.HexToByteArray() }; + (ECDsa ecDsa, HashAlgorithmName? name) = CborCoseKeyHelpers.ParseECDsaPublicKey(hexEncoding.HexToByteArray()); + + using ECDsa _ = ecDsa; + + ECParameters ecParams = ecDsa.ExportParameters(includePrivateParameters: false); + + string? expectedCurveFriendlyName = NormalizeCurveForPlatform(curveFriendlyName).Oid.FriendlyName; + + Assert.True(ecParams.Curve.IsNamed); + Assert.Equal(expectedCurveFriendlyName, ecParams.Curve.Oid.FriendlyName); + Assert.Equal(q.X, ecParams.Q.X); + Assert.Equal(q.Y, ecParams.Q.Y); + Assert.Equal(expectedHashAlgorithmName, name?.Name); + + static ECCurve NormalizeCurveForPlatform(string friendlyName) + { + ECCurve namedCurve = ECCurve.CreateFromFriendlyName(friendlyName); + using ECDsa ecDsa = ECDsa.Create(namedCurve); + ECParameters platformParams = ecDsa.ExportParameters(includePrivateParameters: false); + return platformParams.Curve; + } + } } } diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborWriterTests.cs b/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborWriterTests.cs index c6db6b5b991b4..50999b4f8e1be 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborWriterTests.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborWriterTests.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; using Test.Cryptography; using Xunit; @@ -253,5 +254,38 @@ public static void EncodeIndefiniteLengths_UnsupportedConformanceLevel_ShouldThr public static IEnumerable EncodedValueInputs => CborReaderTests.SampleCborValues.Select(x => new [] { x }); public static IEnumerable EncodedValueBadInputs => CborReaderTests.InvalidCborValues.Select(x => new[] { x }); + + [Theory] + [InlineData("a501020326200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + "65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d", + "1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + "SHA256", "ECDSA_P256")] + [InlineData("a501020338222002215830ed57d8608c5734a5ed5d22026bad8700636823e45297306479beb61a5bd6b04688c34a2f0de51d91064355eef7548bdd22583024376b4fee60ba65db61de54234575eec5d37e1184fbafa1f49d71e1795bba6bda9cbe2ebb815f9b49b371486b38fa1b", + "ed57d8608c5734a5ed5d22026bad8700636823e45297306479beb61a5bd6b04688c34a2f0de51d91064355eef7548bdd", + "24376b4fee60ba65db61de54234575eec5d37e1184fbafa1f49d71e1795bba6bda9cbe2ebb815f9b49b371486b38fa1b", + "SHA384", "ECDSA_P384")] + [InlineData("a50102033823200321584200b03811bef65e330bb974224ec3ab0a5469f038c92177b4171f6f66f91244d4476e016ee77cf7e155a4f73567627b5d72eaf0cb4a6036c6509a6432d7cd6a3b325c2258420114b597b6c271d8435cfa02e890608c93f5bc118ca7f47bf191e9f9e49a22f8a15962315f0729781e1d78b302970c832db2fa8f7f782a33f8e1514950dc7499035f", + "00b03811bef65e330bb974224ec3ab0a5469f038c92177b4171f6f66f91244d4476e016ee77cf7e155a4f73567627b5d72eaf0cb4a6036c6509a6432d7cd6a3b325c", + "0114b597b6c271d8435cfa02e890608c93f5bc118ca7f47bf191e9f9e49a22f8a15962315f0729781e1d78b302970c832db2fa8f7f782a33f8e1514950dc7499035f", + "SHA512", "ECDSA_P521")] + [InlineData("a40102200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + "65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d", + "1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + null, "ECDSA_P256")] + public static void CoseKeyHelpers_ECDsaExportCosePublicKey_HappyPath(string expectedHexEncoding, string hexQx, string hexQy, string? hashAlgorithmName, string curveFriendlyName) + { + byte[] expectedEncoding = expectedHexEncoding.HexToByteArray(); + var hashAlgName = hashAlgorithmName != null ? new HashAlgorithmName(hashAlgorithmName) : (HashAlgorithmName?)null; + var ecParameters = new ECParameters() + { + Curve = ECCurve.CreateFromFriendlyName(curveFriendlyName), + Q = new ECPoint() { X = hexQx.HexToByteArray(), Y = hexQy.HexToByteArray() }, + }; + + using ECDsa ecDsa = ECDsa.Create(ecParameters); + + byte[] coseKeyEncoding = CborCoseKeyHelpers.ExportECDsaPublicKey(ecDsa, hashAlgName); + AssertHelper.HexEqual(expectedEncoding, coseKeyEncoding); + } } } diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CoseKeyHelpers.cs b/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CoseKeyHelpers.cs new file mode 100644 index 0000000000000..a87d7c7706478 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CoseKeyHelpers.cs @@ -0,0 +1,319 @@ +// 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. + +#nullable enable +using System.Diagnostics; +using System.Security.Cryptography; + +// Provides a reference implementation for serializing ECDsa public keys to the COSE_Key format +// according to https://tools.ietf.org/html/rfc8152#section-8.1 + +namespace System.Formats.Cbor.Tests +{ + public static class CborCoseKeyHelpers + { + public static byte[] ExportECDsaPublicKey(ECDsa ecDsa, HashAlgorithmName? hashAlgName) + { + ECParameters ecParams = ecDsa.ExportParameters(includePrivateParameters: false); + using var writer = new CborWriter(CborConformanceLevel.Ctap2Canonical); + WriteECParametersAsCosePublicKey(writer, ecParams, hashAlgName); + return writer.GetEncoding(); + } + + public static (ECDsa ecDsa, HashAlgorithmName? hashAlgName) ParseECDsaPublicKey(byte[] coseKey) + { + var reader = new CborReader(coseKey, CborConformanceLevel.Ctap2Canonical); + (ECParameters ecParams, HashAlgorithmName? hashAlgName) = ReadECParametersAsCosePublicKey(reader); + return (ECDsa.Create(ecParams), hashAlgName); + } + + private static void WriteECParametersAsCosePublicKey(CborWriter writer, ECParameters ecParams, HashAlgorithmName? algorithmName) + { + Debug.Assert(writer.ConformanceLevel == CborConformanceLevel.Ctap2Canonical); + + if (ecParams.Q.X is null || ecParams.Q.Y is null) + { + throw new ArgumentException("does not specify a public key point.", nameof(ecParams)); + } + + // run these first to perform necessary validation + (CoseKeyType kty, CoseCrvId crv) = MapECCurveToCoseKtyAndCrv(ecParams.Curve); + CoseKeyAlgorithm? alg = (algorithmName != null) ? MapHashAlgorithmNameToCoseKeyAlg(algorithmName.Value) : (CoseKeyAlgorithm?)null; + + // Begin writing a CBOR object + writer.WriteStartMap(); + + // NB labels should be sorted according to CTAP2 canonical encoding rules. + // While the CborWriter will attempt to sort the encodings on its own, + // it is generally more efficient if keys are written in sorted order to begin with. + + WriteCoseKeyLabel(writer, CoseKeyLabel.Kty); + writer.WriteInt32((int)kty); + + if (alg != null) + { + WriteCoseKeyLabel(writer, CoseKeyLabel.Alg); + writer.WriteInt32((int)alg); + } + + WriteCoseKeyLabel(writer, CoseKeyLabel.EcCrv); + writer.WriteInt32((int)crv); + + WriteCoseKeyLabel(writer, CoseKeyLabel.EcX); + writer.WriteByteString(ecParams.Q.X); + + WriteCoseKeyLabel(writer, CoseKeyLabel.EcY); + writer.WriteByteString(ecParams.Q.Y); + + writer.WriteEndMap(); + + static (CoseKeyType, CoseCrvId) MapECCurveToCoseKtyAndCrv(ECCurve curve) + { + if (!curve.IsNamed) + { + throw new ArgumentException("EC COSE keys only support named curves.", nameof(curve)); + } + + if (MatchesOid(ECCurve.NamedCurves.nistP256)) + { + return (CoseKeyType.EC2, CoseCrvId.P256); + } + + if (MatchesOid(ECCurve.NamedCurves.nistP384)) + { + return (CoseKeyType.EC2, CoseCrvId.P384); + } + + if (MatchesOid(ECCurve.NamedCurves.nistP521)) + { + return (CoseKeyType.EC2, CoseCrvId.P521); + } + + throw new ArgumentException("Unrecognized named curve", curve.Oid.Value); + + bool MatchesOid(ECCurve namedCurve) => curve.Oid.Value == namedCurve.Oid.Value; + } + + static CoseKeyAlgorithm MapHashAlgorithmNameToCoseKeyAlg(HashAlgorithmName name) + { + if (MatchesName(HashAlgorithmName.SHA256)) + { + return CoseKeyAlgorithm.ES256; + } + + if (MatchesName(HashAlgorithmName.SHA384)) + { + return CoseKeyAlgorithm.ES384; + } + + if (MatchesName(HashAlgorithmName.SHA512)) + { + return CoseKeyAlgorithm.ES512; + } + + throw new ArgumentException("Unrecognized hash algorithm name.", nameof(HashAlgorithmName)); + + bool MatchesName(HashAlgorithmName candidate) => name.Name == candidate.Name; + } + + static void WriteCoseKeyLabel(CborWriter writer, CoseKeyLabel label) + { + writer.WriteInt32((int)label); + } + } + + private static (ECParameters, HashAlgorithmName?) ReadECParametersAsCosePublicKey(CborReader reader) + { + Debug.Assert(reader.ConformanceLevel == CborConformanceLevel.Ctap2Canonical); + + // CTAP2 conformance mode requires that fields are sorted by key encoding. + // We take advantage of this by reading keys in that order. + // NB1. COSE labels are not sorted according to canonical integer ordering, + // negative labels must always follow positive labels. + // NB2. Any unrecognized keys will result in the reader failing. + // NB3. in order to support optional fields, we need to store the latest read label. + CoseKeyLabel? latestReadLabel = null; + + int? remainingKeys = reader.ReadStartMap(); + Debug.Assert(remainingKeys != null); // guaranteed by CTAP2 conformance + + try + { + var ecParams = new ECParameters(); + + ReadCoseKeyLabel(CoseKeyLabel.Kty); + CoseKeyType kty = (CoseKeyType)reader.ReadInt32(); + + HashAlgorithmName? algName = null; + if (TryReadCoseKeyLabel(CoseKeyLabel.Alg)) + { + CoseKeyAlgorithm alg = (CoseKeyAlgorithm)reader.ReadInt32(); + algName = MapCoseKeyAlgToHashAlgorithmName(alg); + } + + if (TryReadCoseKeyLabel(CoseKeyLabel.KeyOps)) + { + // No-op, simply tolerate potential key_ops labels + reader.SkipValue(validateConformance: true); + } + + ReadCoseKeyLabel(CoseKeyLabel.EcCrv); + CoseCrvId crv = (CoseCrvId)reader.ReadInt32(); + + if (IsValidKtyCrvCombination(kty, crv)) + { + ecParams.Curve = MapCoseCrvToECCurve(crv); + } + else + { + throw new FormatException("Invalid kty/crv combination in COSE key."); + } + + ReadCoseKeyLabel(CoseKeyLabel.EcX); + ecParams.Q.X = reader.ReadByteString(); + + ReadCoseKeyLabel(CoseKeyLabel.EcY); + ecParams.Q.Y = reader.ReadByteString(); + + if (TryReadCoseKeyLabel(CoseKeyLabel.EcD)) + { + throw new FormatException("COSE key encodes a private key."); + } + + if (remainingKeys > 0) + { + throw new FormatException("COSE_key contains unrecognized trailing data."); + } + + reader.ReadEndMap(); + + return (ecParams, algName); + } + catch (InvalidOperationException e) + { + throw new FormatException("Invalid COSE_key format in CBOR document", e); + } + + static bool IsValidKtyCrvCombination(CoseKeyType kty, CoseCrvId crv) + { + return (kty, crv) switch + { + (CoseKeyType.EC2, CoseCrvId.P256 or CoseCrvId.P384 or CoseCrvId.P521) => true, + (CoseKeyType.OKP, CoseCrvId.X255519 or CoseCrvId.X448 or CoseCrvId.Ed25519 or CoseCrvId.Ed448) => true, + _ => false, + }; + ; + } + + static ECCurve MapCoseCrvToECCurve(CoseCrvId crv) + { + return crv switch + { + CoseCrvId.P256 => ECCurve.NamedCurves.nistP256, + CoseCrvId.P384 => ECCurve.NamedCurves.nistP384, + CoseCrvId.P521 => ECCurve.NamedCurves.nistP521, + CoseCrvId.X255519 or + CoseCrvId.X448 or + CoseCrvId.Ed25519 or + CoseCrvId.Ed448 => throw new NotImplementedException("OKP type curves not implemented."), + _ => throw new FormatException("Unrecognized COSE crv value."), + }; + } + + static HashAlgorithmName MapCoseKeyAlgToHashAlgorithmName(CoseKeyAlgorithm alg) + { + return alg switch + { + CoseKeyAlgorithm.ES256 => HashAlgorithmName.SHA256, + CoseKeyAlgorithm.ES384 => HashAlgorithmName.SHA384, + CoseKeyAlgorithm.ES512 => HashAlgorithmName.SHA512, + _ => throw new FormatException("Unrecognized COSE alg value."), + }; + } + + // Handles optional labels + bool TryReadCoseKeyLabel(CoseKeyLabel expectedLabel) + { + // The `currentLabel` parameter can hold a label that + // was read when handling a previous optional field. + // We only need to read the next label if uninhabited. + if (latestReadLabel == null) + { + // check that we have not reached the end of the COSE key object + if (remainingKeys == 0) + { + return false; + } + + latestReadLabel = (CoseKeyLabel)reader.ReadInt32(); + } + + if (expectedLabel != latestReadLabel.Value) + { + return false; + } + + // read was successful, vacate the `currentLabel` parameter to advance reads. + latestReadLabel = null; + remainingKeys--; + return true; + } + + // Handles required labels + void ReadCoseKeyLabel(CoseKeyLabel expectedLabel) + { + if (!TryReadCoseKeyLabel(expectedLabel)) + { + throw new FormatException("Unexpected COSE key label."); + } + } + } + + private enum CoseKeyLabel : int + { + // cf. https://tools.ietf.org/html/rfc8152#section-7.1 table 3 + Kty = 1, + Kid = 2, + Alg = 3, + KeyOps = 4, + BaseIv = 5, + + // cf. https://tools.ietf.org/html/rfc8152#section-13.1.1 table 23 + EcCrv = -1, + EcX = -2, + EcY = -3, + EcD = -4, + }; + + private enum CoseCrvId : int + { + // cf. https://tools.ietf.org/html/rfc8152#section-13.1 table 22 + P256 = 1, + P384 = 2, + P521 = 3, + X255519 = 4, + X448 = 5, + Ed25519 = 6, + Ed448 = 7, + } + + private enum CoseKeyType : int + { + // cf. https://tools.ietf.org/html/rfc8152#section-13 table 21 + OKP = 1, + EC2 = 2, + + Symmetric = 4, + Reserved = 0, + } + + private enum CoseKeyAlgorithm : int + { + // cf. https://tools.ietf.org/html/rfc8152#section-8.1 table 5 + ES256 = -7, + ES384 = -35, + ES512 = -36, + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/Oid.cs b/src/libraries/System.Security.Cryptography.Encoding/tests/Oid.cs index 6e6b04f6549df..cafaa03caed90 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/tests/Oid.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/Oid.cs @@ -330,6 +330,21 @@ public static void LookupOidByFriendlyName_Method_UnixOnly() Assert.Equal(ObsoleteSmime3desWrap_Name, oid.FriendlyName); } + [Theory] + [InlineData("nistP256", "1.2.840.10045.3.1.7")] + [InlineData("secP256r1", "1.2.840.10045.3.1.7")] + [InlineData("x962P256v1", "1.2.840.10045.3.1.7")] + [InlineData("nistP384", "1.3.132.0.34")] + [InlineData("secP384r1", "1.3.132.0.34")] + [InlineData("nistP521", "1.3.132.0.35")] + [InlineData("secP521r1", "1.3.132.0.35")] + public static void LookupOidByFriendlyName_AdditionalNames(string friendlyName, string expectedOid) + { + Oid oid = Oid.FromFriendlyName(friendlyName, OidGroup.All); + Assert.Equal(friendlyName, oid.FriendlyName); + Assert.Equal(expectedOid, oid.Value); + } + public static IEnumerable ValidOidFriendlyNamePairs { get diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/PemEncodingFindTests.cs b/src/libraries/System.Security.Cryptography.Encoding/tests/PemEncodingFindTests.cs index 874b862cd4cf8..fe9e3723672f1 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/tests/PemEncodingFindTests.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/PemEncodingFindTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Security.Cryptography; +using System.Text; using Xunit; namespace System.Security.Cryptography.Encoding.Tests @@ -260,12 +261,46 @@ public void Find_Success_FindsPemAfterPemWithInvalidLabel() Assert.Equal("Zm9v", content[fields.Base64Data]); } + [Fact] + public void TryFind_Success_AfterSuccessiveInvalidBase64() + { + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < 100; i++) + { + builder.Append($"-----BEGIN CERTIFICATE-----\n${i:000}\n-----END CERTIFICATE-----\n"); + } + + builder.Append($"-----BEGIN CERTIFICATE-----\nZm9v\n-----END CERTIFICATE-----"); + + AssertPemFound(builder.ToString(), + expectedLocation: 5900..5958, + expectedBase64: 5928..5932, + expectedLabel: 5911..5922); + } + [Fact] public void Find_Fail_Empty() { AssertNoPemFound(string.Empty); } + [Fact] + public void Find_Fail_InvalidBase64_MultipleInvalid_WithSurroundingText() + { + string content = @" +CN=Intermediate1 +-----BEGIN CERTIFICATE----- +MII +-----END CERTIFICATE----- +CN=Intermediate2 +-----BEGIN CERTIFICATE----- +MII +-----END CERTIFICATE----- +"; + AssertNoPemFound(content); + } + [Fact] public void Find_Fail_PostEbBeforePreEb() { diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj b/src/libraries/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj index 8ca393597862f..e89c8cf8318ff 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj @@ -76,5 +76,6 @@ + diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj index 0f70b59154c8e..cc4944963eddd 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj +++ b/src/libraries/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj @@ -1,6 +1,6 @@ - netcoreapp3.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netcoreapp3.0 true enable diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj b/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj index 4f7eff09e987c..03996c4a2fbdf 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj +++ b/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj @@ -1,7 +1,7 @@ true - netcoreapp3.0-Unix;netcoreapp3.0;netstandard2.0;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent) + $(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent);netcoreapp3.0-Unix;netcoreapp3.0;netstandard2.0 true enable @@ -104,7 +104,7 @@ - + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.csproj index 87ca3d5be2561..07a5f1e62c220 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.csproj @@ -1,6 +1,6 @@ - netcoreapp3.0;netstandard2.1;net461;$(NetFrameworkCurrent);$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netcoreapp3.0;netstandard2.1;net461;$(NetFrameworkCurrent) true true enable diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx index 117980b01ba6e..aa366d559ef7d 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -57,8 +58,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - String cannot be empty or null. + + The `{0}` string cannot be empty or null. Only single dimensional arrays are supported for the requested action. @@ -214,10 +215,10 @@ New Pkcs12SafeBag values cannot be added to a Pkcs12SafeContents that was read from existing data. - This decryption operation applies to 'Pkcs12ConfidentialityMode.{0}', but the target object is in 'Pkcs12ConfidentialityMode.{1}'. + This decryption operation applies to 'Pkcs12ConfidentialityMode.{0}', but the target object is in 'Pkcs12ConfidentialityMode.{1}'. - This verification operation applies to 'Pkcs12IntegrityMode.{0}', but the target object is in 'Pkcs12IntegrityMode.{1}'. + This verification operation applies to 'Pkcs12IntegrityMode.{0}', but the target object is in 'Pkcs12IntegrityMode.{1}'. Invalid signature paramters. @@ -294,4 +295,4 @@ Certificate already present in the collection. - + \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs12Builder.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs12Builder.cs index 4290deb59336b..be3874b32d4bb 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs12Builder.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs12Builder.cs @@ -41,7 +41,7 @@ public sealed class Pkcs12Builder if (pbeParameters == null) throw new ArgumentNullException(nameof(pbeParameters)); if (pbeParameters.IterationCount < 1) - throw new ArgumentOutOfRangeException(nameof(pbeParameters.IterationCount)); + throw new ArgumentOutOfRangeException(nameof(pbeParameters)); if (safeContents.ConfidentialityMode != Pkcs12ConfidentialityMode.None) throw new ArgumentException(SR.Cryptography_Pkcs12_CannotProcessEncryptedSafeContents, nameof(safeContents)); if (IsSealed) @@ -89,7 +89,7 @@ public sealed class Pkcs12Builder if (pbeParameters == null) throw new ArgumentNullException(nameof(pbeParameters)); if (pbeParameters.IterationCount < 1) - throw new ArgumentOutOfRangeException(nameof(pbeParameters.IterationCount)); + throw new ArgumentOutOfRangeException(nameof(pbeParameters)); if (safeContents.ConfidentialityMode != Pkcs12ConfidentialityMode.None) throw new ArgumentException(SR.Cryptography_Pkcs12_CannotProcessEncryptedSafeContents, nameof(safeContents)); if (IsSealed) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs9AttributeObject.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs9AttributeObject.cs index 11bb644cafa87..cb86b388484ea 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs9AttributeObject.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/Pkcs9AttributeObject.cs @@ -32,12 +32,12 @@ public Pkcs9AttributeObject(AsnEncodedData asnEncodedData) : base(asnEncodedData) { if (asnEncodedData.Oid == null) - throw new ArgumentNullException(nameof(asnEncodedData.Oid)); + throw new ArgumentException(SR.Format(SR.Arg_EmptyOrNullString_Named, "asnEncodedData.Oid"), nameof(asnEncodedData)); string? szOid = base.Oid!.Value; if (szOid == null) - throw new ArgumentNullException("oid.Value"); + throw new ArgumentException(SR.Format(SR.Arg_EmptyOrNullString_Named, "oid.Value"), nameof(asnEncodedData)); if (szOid.Length == 0) - throw new ArgumentException(SR.Arg_EmptyOrNullString, "oid.Value"); + throw new ArgumentException(SR.Format(SR.Arg_EmptyOrNullString_Named, "oid.Value"), nameof(asnEncodedData)); } internal Pkcs9AttributeObject(Oid oid) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs index d45d274e7639b..74646c7186cd3 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs @@ -45,7 +45,7 @@ public SignedCms(SubjectIdentifierType signerIdentifierType, ContentInfo content if (contentInfo == null) throw new ArgumentNullException(nameof(contentInfo)); if (contentInfo.Content == null) - throw new ArgumentNullException("contentInfo.Content"); + throw new ArgumentException(SR.Format(SR.Arg_EmptyOrNullString_Named, "contentInfo.Content"), nameof(contentInfo)); // Normalize the subject identifier type the same way as .NET Framework. // This value is only used in the zero-argument ComputeSignature overload, diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs index 9247ae50b14bf..3d1e349f52985 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs @@ -358,9 +358,7 @@ public void RemoveCounterSignature(int index) { if (index < 0) { - // In .NET Framework RemoveCounterSignature doesn't bounds check, but the helper it calls does. - // In the helper the argument is called "childIndex". - throw new ArgumentOutOfRangeException("childIndex"); + throw new ArgumentOutOfRangeException(nameof(index)); } // The SignerInfo class is a projection of data contained within the SignedCms. diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs index 9591a1bce1a5b..79aa1a42805f5 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs @@ -24,7 +24,7 @@ public static void Pkcs9AttributeAsnEncodedDataCtorNullOid() { AsnEncodedData a = new AsnEncodedData(new byte[3]); object ign; - Assert.Throws(() => ign = new Pkcs9AttributeObject(a)); + AssertExtensions.Throws("asnEncodedData", "asnEncodedData.Oid", () => ign = new Pkcs9AttributeObject(a)); } [Fact] @@ -112,7 +112,7 @@ public static void Pkcs9AttributeAsnEncodedDataCtorNullOidValue() AsnEncodedData a = new AsnEncodedData(oid, new byte[3]); object ign; - Assert.Throws(() => ign = new Pkcs9AttributeObject(a)); + AssertExtensions.Throws("asnEncodedData", "oid.Value", () => ign = new Pkcs9AttributeObject(a)); } [Fact] @@ -123,7 +123,7 @@ public static void Pkcs9AttributeAsnEncodedDataCtorEmptyOidValue() AsnEncodedData a = new AsnEncodedData(oid, new byte[3]); object ign; - AssertExtensions.Throws("oid.Value", () => ign = new Pkcs9AttributeObject(a)); + AssertExtensions.Throws("asnEncodedData", "oid.Value", () => ign = new Pkcs9AttributeObject(a)); } [Fact] diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs index 34a48544a868b..ddfa1dd7f7976 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs @@ -481,6 +481,7 @@ public static void RemoveCounterSignature_Negative() SignerInfo signer = cms.SignerInfos[0]; ArgumentOutOfRangeException ex = AssertExtensions.Throws( + "index", "childIndex", () => signer.RemoveCounterSignature(-1)); diff --git a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoConfigForwarder.cs b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoConfigForwarder.cs index c42440669f4b4..9e1055857753a 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoConfigForwarder.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptoConfigForwarder.cs @@ -25,7 +25,7 @@ internal static class CryptoConfigForwarder throw new MissingMethodException(t.FullName, CreateFromNameMethodName); } - return (Func)createFromName.CreateDelegate(typeof(Func)); + return createFromName.CreateDelegate>(); } internal static object? CreateFromName(string name) => s_createFromName(name); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs index 5ba5eb0a55c26..2baabf516b325 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs @@ -215,8 +215,9 @@ public ICertificatePal CopyWithPrivateKey(RSA rsa) IntPtr privateKeyPtr; - // If the certificate has a key handle instead of a key prov info, return the + // If the certificate has a key handle without a key prov info, return the // ephemeral key + if (!certificateContext.HasPersistedPrivateKey) { int cbData = IntPtr.Size; diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx index 37fc7642786bc..d5e8ac308897f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -66,6 +67,9 @@ String cannot be empty or null. + + The '{0}' string cannot be empty or null. + Illegal enum value: {0}. @@ -74,7 +78,7 @@ Invalid type. - + Non-negative number required. @@ -223,7 +227,7 @@ The provided hash value is not the expected size for the specified hash algorithm. - The Disallowed store is not supported on this platform, but already has data. All files under '{0}' must be removed. + The Disallowed store is not supported on this platform, but already has data. All files under '{0}' must be removed. Unix LocalMachine X509Stores are read-only for all users. @@ -235,7 +239,7 @@ The Disallowed store is not supported on this platform. - The {0} value cannot be set on Unix. + The {0} value cannot be set on Unix. '{0}' is not a known hash algorithm. @@ -286,7 +290,7 @@ The X509 certificate store is read-only. - The platform does not have a definition for an X509 certificate store named '{0}' with a StoreLocation of '{1}', and does not support creating it. + The platform does not have a definition for an X509 certificate store named '{0}' with a StoreLocation of '{1}', and does not support creating it. Enumeration has not started. Call MoveNext. @@ -417,4 +421,4 @@ Key is not a valid private key. - + \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Extension.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Extension.cs index af33813026922..84d5cb3eae3e9 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Extension.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Extension.cs @@ -31,7 +31,7 @@ public X509Extension(Oid oid, byte[] rawData, bool critical) if (base.Oid == null || base.Oid.Value == null) throw new ArgumentNullException(nameof(oid)); if (base.Oid.Value.Length == 0) - throw new ArgumentException(SR.Arg_EmptyOrNullString, "oid.Value"); + throw new ArgumentException(SR.Format(SR.Arg_EmptyOrNullString_Named, "oid.Value"), nameof(oid)); Critical = critical; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs index c473d80895fa8..30a1b19bb6893 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs @@ -157,5 +157,131 @@ public static void ExportAsPfxWithPrivateKey() } } } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + [OuterLoop("Modifies user-persisted state")] + public static void ExportDoesNotCorruptPrivateKeyMethods() + { + string keyName = $"clrtest.{Guid.NewGuid():D}"; + X509Store cuMy = new X509Store(StoreName.My, StoreLocation.CurrentUser); + cuMy.Open(OpenFlags.ReadWrite); + X509Certificate2 createdCert = null; + X509Certificate2 foundCert = null; + X509Certificate2 foundCert2 = null; + + try + { + string commonName = nameof(ExportDoesNotCorruptPrivateKeyMethods); + string subject = $"CN={commonName},OU=.NET"; + + using (ImportedCollection toClean = new ImportedCollection(cuMy.Certificates)) + { + X509Certificate2Collection coll = toClean.Collection; + + using (ImportedCollection matches = + new ImportedCollection(coll.Find(X509FindType.FindBySubjectName, commonName, false))) + { + foreach (X509Certificate2 cert in matches.Collection) + { + cuMy.Remove(cert); + } + } + } + + foreach (X509Certificate2 cert in cuMy.Certificates) + { + if (subject.Equals(cert.Subject)) + { + cuMy.Remove(cert); + } + + cert.Dispose(); + } + + CngKeyCreationParameters options = new CngKeyCreationParameters + { + ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport, + }; + + using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, keyName, options)) + using (RSACng rsaCng = new RSACng(key)) + { + CertificateRequest certReq = new CertificateRequest( + subject, + rsaCng, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); + + DateTimeOffset now = DateTimeOffset.UtcNow.AddMinutes(-5); + createdCert = certReq.CreateSelfSigned(now, now.AddDays(1)); + } + + cuMy.Add(createdCert); + + using (ImportedCollection toClean = new ImportedCollection(cuMy.Certificates)) + { + X509Certificate2Collection matches = toClean.Collection.Find( + X509FindType.FindBySubjectName, + commonName, + validOnly: false); + + Assert.Equal(1, matches.Count); + foundCert = matches[0]; + } + + Assert.False(HasEphemeralKey(foundCert)); + foundCert.Export(X509ContentType.Pfx, ""); + Assert.False(HasEphemeralKey(foundCert)); + + using (ImportedCollection toClean = new ImportedCollection(cuMy.Certificates)) + { + X509Certificate2Collection matches = toClean.Collection.Find( + X509FindType.FindBySubjectName, + commonName, + validOnly: false); + + Assert.Equal(1, matches.Count); + foundCert2 = matches[0]; + } + + Assert.False(HasEphemeralKey(foundCert2)); + } + finally + { + if (createdCert != null) + { + cuMy.Remove(createdCert); + createdCert.Dispose(); + } + + cuMy.Dispose(); + + foundCert?.Dispose(); + foundCert2?.Dispose(); + + try + { + CngKey key = CngKey.Open(keyName); + key.Delete(); + key.Dispose(); + } + catch (Exception) + { + } + } + + bool HasEphemeralKey(X509Certificate2 c) + { + using (RSA key = c.GetRSAPrivateKey()) + { + // This code is not defensive against the type changing, because it + // is in the source tree with the code that produces the value. + // Don't blind-cast like this in library or application code. + RSACng rsaCng = (RSACng)key; + return rsaCng.Key.IsEphemeral; + } + } + } } } diff --git a/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj b/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj index e3b9aa3ab4ec2..174f60d9b0688 100644 --- a/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj +++ b/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj @@ -181,7 +181,7 @@ - + - System.Security.Principal.Windows true $(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix;netstandard2.0;netcoreapp2.0-Windows_NT;netcoreapp2.0-Unix;netcoreapp2.1-Windows_NT;netcoreapp2.1-Unix;net461-Windows_NT;$(NetFrameworkCurrent)-Windows_NT true diff --git a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs index 81da0b439bb03..19782152c0169 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs +++ b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs @@ -640,7 +640,9 @@ public SecurityIdentifier(WellKnownSidType sidType, SecurityIdentifier? domainSi if (error == Interop.Errors.ERROR_INVALID_PARAMETER) { +#pragma warning disable CA2208 // Instantiate argument exceptions correctly, combination of arguments used throw new ArgumentException(new Win32Exception(error).Message, "sidType/domainSid"); +#pragma warning restore CS2208 } else if (error != Interop.Errors.ERROR_SUCCESS) { diff --git a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs index be5c623b29967..0c4e03d627194 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs +++ b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs @@ -134,11 +134,8 @@ public WindowsIdentity(string sUserPrincipalName) sourceContext.SourceName = new byte[TOKEN_SOURCE.TOKEN_SOURCE_LENGTH]; Buffer.BlockCopy(sourceName, 0, sourceContext.SourceName, 0, sourceName.Length); - // .NET Framework compat: Desktop never null-checks sUserPrincipalName. Actual behavior is that the null makes it down to Encoding.Unicode.GetBytes() which then throws - // the ArgumentNullException (provided that the prior LSA calls didn't fail first.) To make this compat decision explicit, we'll null check ourselves - // and simulate the exception from Encoding.Unicode.GetBytes(). if (sUserPrincipalName == null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(sUserPrincipalName)); byte[] upnBytes = Encoding.Unicode.GetBytes(sUserPrincipalName); if (upnBytes.Length > ushort.MaxValue) diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 7b5d7a1dfe77f..4aa8377c12746 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -209,9 +209,11 @@ public sealed partial class JsonSerializerOptions { public JsonSerializerOptions() { } public JsonSerializerOptions(System.Text.Json.JsonSerializerOptions options) { } + public JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults defaults) { } public bool AllowTrailingCommas { get { throw null; } set { } } public System.Collections.Generic.IList Converters { get { throw null; } } public int DefaultBufferSize { get { throw null; } set { } } + public System.Text.Json.Serialization.JsonIgnoreCondition DefaultIgnoreCondition { get { throw null; } set { } } public System.Text.Json.JsonNamingPolicy? DictionaryKeyPolicy { get { throw null; } set { } } public System.Text.Encodings.Web.JavaScriptEncoder? Encoder { get { throw null; } set { } } public bool IgnoreNullValues { get { throw null; } set { } } @@ -224,6 +226,11 @@ public sealed partial class JsonSerializerOptions public bool WriteIndented { get { throw null; } set { } } public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } } + public enum JsonSerializerDefaults + { + General = 0, + Web = 1, + } public enum JsonTokenType : byte { None = (byte)0, @@ -459,9 +466,9 @@ namespace System.Text.Json.Serialization { public enum JsonIgnoreCondition { - Always = 0, - WhenNull = 1, - Never = 2, + Never = 0, + Always = 1, + WhenWritingDefault = 2, } public abstract partial class JsonAttribute : System.Attribute { @@ -489,6 +496,8 @@ public abstract partial class JsonConverter : System.Text.Json.Serialization. { protected internal JsonConverter() { } public override bool CanConvert(System.Type typeToConvert) { throw null; } + public virtual bool HandleNull { get { throw null; } } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] public abstract T Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options); public abstract void Write(System.Text.Json.Utf8JsonWriter writer, T value, System.Text.Json.JsonSerializerOptions options); } diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 3f54adaab7447..44de8a1f85fb7 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -396,8 +396,8 @@ The converter '{0}' wrote too much or not enough. - - The dictionary key policy '{0}' cannot return a null key. + + The naming policy '{0}' cannot return null. The attribute '{0}' cannot exist more than once on '{1}'. @@ -521,4 +521,10 @@ The collection type '{0}' is abstract, an interface, or is read only, and could not be instantiated and populated. + + 'IgnoreNullValues' and 'DefaultIgnoreCondition' cannot both be set to non-default values. + + + The value cannot be 'JsonIgnoreCondition.Always'. + \ No newline at end of file diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 1311316b1caa5..7fcf718583ae6 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -15,7 +15,7 @@ $(DefineConstants);BUILDING_INBOX_LIBRARY - $(NoWarn);nullable + $(NoWarn);nullable + @@ -211,7 +212,7 @@ - + - + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs index 0ffe89e51e823..49770ef3f5f67 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs @@ -675,9 +675,13 @@ private static async Debug.Assert(rented.Length >= JsonConstants.Utf8Bom.Length); lastRead = await stream.ReadAsync( +#if BUILDING_INBOX_LIBRARY + rented.AsMemory(written, utf8BomLength - written), +#else rented, written, utf8BomLength - written, +#endif cancellationToken).ConfigureAwait(false); written += lastRead; @@ -702,9 +706,13 @@ private static async } lastRead = await stream.ReadAsync( +#if BUILDING_INBOX_LIBRARY + rented.AsMemory(written), +#else rented, written, rented.Length - written, +#endif cancellationToken).ConfigureAwait(false); written += lastRead; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs index 2993fac38ab54..023fa4b1342af 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs @@ -32,6 +32,15 @@ private JsonEncodedText(byte[] utf8Value) _utf8Value = utf8Value; } + private JsonEncodedText(string stringValue, byte[] utf8Value) + { + Debug.Assert(stringValue != null); + Debug.Assert(utf8Value != null); + + _value = stringValue; + _utf8Value = utf8Value; + } + /// /// Encodes the string text value as a JSON string. /// @@ -125,6 +134,37 @@ private static JsonEncodedText EncodeHelper(ReadOnlySpan utf8Value, JavaSc } } + /// + /// Internal version that keeps the existing string and byte[] references if there is no escaping required. + /// + internal static JsonEncodedText Encode(string stringValue, byte[] utf8Value, JavaScriptEncoder? encoder = null) + { + Debug.Assert(stringValue.Equals(JsonHelpers.Utf8GetString(utf8Value))); + + if (utf8Value.Length == 0) + { + return new JsonEncodedText(stringValue, utf8Value); + } + + JsonWriterHelper.ValidateValue(utf8Value); + return EncodeHelper(stringValue, utf8Value, encoder); + } + + private static JsonEncodedText EncodeHelper(string stringValue, byte[] utf8Value, JavaScriptEncoder? encoder) + { + int idx = JsonWriterHelper.NeedsEscaping(utf8Value, encoder); + + if (idx != -1) + { + return new JsonEncodedText(GetEscapedString(utf8Value, idx, encoder)); + } + else + { + // Encoding is not necessary; use the same stringValue and utf8Value references. + return new JsonEncodedText(stringValue, utf8Value); + } + } + private static byte[] GetEscapedString(ReadOnlySpan utf8Value, int firstEscapeIndexVal, JavaScriptEncoder? encoder) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryDefaultConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryDefaultConverter.cs index 3548737459413..4603b59c82f96 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryDefaultConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryDefaultConverter.cs @@ -47,7 +47,7 @@ protected string GetKeyName(string key, ref WriteStack state, JsonSerializerOpti if (key == null) { - ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(options.DictionaryKeyPolicy.GetType()); + ThrowHelper.ThrowInvalidOperationException_NamingPolicyReturnNull(options.DictionaryKeyPolicy); } } @@ -104,7 +104,7 @@ protected static JsonConverter GetValueConverter(ref WriteStack state) // Read the value and add. reader.ReadWithVerify(); TValue element = elementConverter.Read(ref reader, typeof(TValue), options); - Add(element, options, ref state); + Add(element!, options, ref state); } } else @@ -129,7 +129,7 @@ protected static JsonConverter GetValueConverter(ref WriteStack state) // Get the value from the converter and add it. elementConverter.TryRead(ref reader, typeof(TValue), options, ref state, out TValue element); - Add(element, options, ref state); + Add(element!, options, ref state); } } } @@ -247,7 +247,7 @@ protected static JsonConverter GetValueConverter(ref WriteStack state) return false; } - Add(element, options, ref state); + Add(element!, options, ref state); state.Current.EndElement(); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryOfStringTValueConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryOfStringTValueConverter.cs index 79aa533d14664..14ecb4526999c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryOfStringTValueConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/DictionaryOfStringTValueConverter.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Diagnostics; namespace System.Text.Json.Serialization.Converters { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs index 27214b3c10a2b..1a58ed83cda94 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs @@ -28,7 +28,6 @@ public override bool CanConvert(Type typeToConvert) [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.ArrayConverter`2")] [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.ConcurrentQueueOfTConverter`2")] [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.ConcurrentStackOfTConverter`2")] - [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.DefaultArrayConverter`2")] [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.DictionaryOfStringTValueConverter`2")] [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.ICollectionOfTConverter`2")] [PreserveDependency(".ctor", "System.Text.Json.Serialization.Converters.IDictionaryOfStringTValueConverter`2")] diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableDefaultConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableDefaultConverter.cs index dad477364d6d7..6803e9d58454f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableDefaultConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableDefaultConverter.cs @@ -67,7 +67,7 @@ protected static JsonConverter GetElementConverter(ref WriteStack stat // Obtain the CLR value from the JSON and apply to the object. TElement element = elementConverter.Read(ref reader, elementConverter.TypeToConvert, options); - Add(element, ref state); + Add(element!, ref state); } } else @@ -83,7 +83,7 @@ protected static JsonConverter GetElementConverter(ref WriteStack stat // Get the value from the converter and add it. elementConverter.TryRead(ref reader, typeof(TElement), options, ref state, out TElement element); - Add(element, ref state); + Add(element!, ref state); } } } @@ -184,7 +184,7 @@ protected static JsonConverter GetElementConverter(ref WriteStack stat return false; } - Add(element, ref state); + Add(element!, ref state); // No need to set PropertyState to TryRead since we're done with this element now. state.Current.EndElement(); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs index af02cc267b5d1..a89d1910c365b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs @@ -14,11 +14,11 @@ internal sealed class LargeObjectWithParameterizedConstructorConverter : Obje { protected override bool ReadAndCacheConstructorArgument(ref ReadStack state, ref Utf8JsonReader reader, JsonParameterInfo jsonParameterInfo) { - bool success = jsonParameterInfo.ReadJson(ref state, ref reader, out object? arg0); + bool success = jsonParameterInfo.ReadJson(ref state, ref reader, out object? arg); if (success) { - ((object[])state.Current.CtorArgumentState!.Arguments)[jsonParameterInfo.Position] = arg0!; + ((object[])state.Current.CtorArgumentState!.Arguments)[jsonParameterInfo.Position] = arg!; } return success; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs index 391a5710204b8..1e98384d117c6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Small.cs @@ -33,28 +33,28 @@ protected override bool ReadAndCacheConstructorArgument(ref ReadStack state, ref success = ((JsonParameterInfo)jsonParameterInfo).ReadJsonTyped(ref state, ref reader, out TArg0 arg0); if (success) { - arguments.Arg0 = arg0; + arguments.Arg0 = arg0!; } break; case 1: success = ((JsonParameterInfo)jsonParameterInfo).ReadJsonTyped(ref state, ref reader, out TArg1 arg1); if (success) { - arguments.Arg1 = arg1; + arguments.Arg1 = arg1!; } break; case 2: success = ((JsonParameterInfo)jsonParameterInfo).ReadJsonTyped(ref state, ref reader, out TArg2 arg2); if (success) { - arguments.Arg2 = arg2; + arguments.Arg2 = arg2!; } break; case 3: success = ((JsonParameterInfo)jsonParameterInfo).ReadJsonTyped(ref state, ref reader, out TArg3 arg3); if (success) { - arguments.Arg3 = arg3; + arguments.Arg3 = arg3!; } break; default: diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs index 7842a0b8b7b3b..54e49b3d5dba2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs @@ -99,7 +99,7 @@ internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToCo if (dataExtKey == null) { - jsonPropertyInfo.SetValueAsObject(obj, propValue); + jsonPropertyInfo.SetExtensionDictionaryAsObject(obj, propValue); } else { @@ -454,41 +454,19 @@ private void BeginRead(ref ReadStack state, ref Utf8JsonReader reader, JsonSeria ReadOnlySpan unescapedPropertyName = JsonSerializer.GetPropertyName(ref state, ref reader, options); - if (!state.Current.JsonClassInfo.TryGetParameter(unescapedPropertyName, ref state.Current, out jsonParameterInfo)) - { - return false; - } - - Debug.Assert(jsonParameterInfo != null); + jsonParameterInfo = state.Current.JsonClassInfo.GetParameter( + unescapedPropertyName, + ref state.Current, + out byte[] utf8PropertyName); - // Increment ConstructorParameterIndex so GetProperty() starts with the next parameter the next time this function is called. + // Increment ConstructorParameterIndex so GetParameter() checks the next parameter first when called again. state.Current.CtorArgumentState!.ParameterIndex++; - // Support JsonException.Path. - Debug.Assert( - jsonParameterInfo.JsonPropertyName == null || - options.PropertyNameCaseInsensitive || - unescapedPropertyName.SequenceEqual(jsonParameterInfo.JsonPropertyName)); - - if (jsonParameterInfo.JsonPropertyName == null) - { - byte[] propertyNameArray = unescapedPropertyName.ToArray(); - if (options.PropertyNameCaseInsensitive) - { - // Each payload can have a different name here; remember the value on the temporary stack. - state.Current.JsonPropertyName = propertyNameArray; - } - else - { - //Prevent future allocs by caching globally on the JsonPropertyInfo which is specific to a Type+PropertyName - // so it will match the incoming payload except when case insensitivity is enabled(which is handled above). - jsonParameterInfo.JsonPropertyName = propertyNameArray; - } - } + // For case insensitive and missing property support of JsonPath, remember the value on the temporary stack. + state.Current.JsonPropertyName = utf8PropertyName; state.Current.CtorArgumentState.JsonParameterInfo = jsonParameterInfo; - - return true; + return jsonParameterInfo != null; } internal override bool ConstructorIsParameterized => true; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/KeyValuePairConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/KeyValuePairConverter.cs index fc5035deeb78e..08e790738f62f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/KeyValuePairConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/KeyValuePairConverter.cs @@ -3,23 +3,52 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Text.Encodings.Web; namespace System.Text.Json.Serialization.Converters { internal sealed class KeyValuePairConverter : JsonValueConverter> { - private const string KeyName = "Key"; - private const string ValueName = "Value"; + private const string KeyNameCLR = "Key"; + private const string ValueNameCLR = "Value"; - // todo: https://github.com/dotnet/runtime/issues/1197 - // move these to JsonSerializerOptions and use the proper encoding. - private static readonly JsonEncodedText _keyName = JsonEncodedText.Encode(KeyName, encoder: null); - private static readonly JsonEncodedText _valueName = JsonEncodedText.Encode(ValueName, encoder: null); + // Property name for "Key" and "Value" with Options.PropertyNamingPolicy applied. + private string _keyName = null!; + private string _valueName = null!; + + // _keyName and _valueName as JsonEncodedText. + private JsonEncodedText _keyNameEncoded; + private JsonEncodedText _valueNameEncoded; // todo: https://github.com/dotnet/runtime/issues/32352 // it is possible to cache the underlying converters since this is an internal converter and // an instance is created only once for each JsonSerializerOptions instance. + internal override void Initialize(JsonSerializerOptions options) + { + JsonNamingPolicy? namingPolicy = options.PropertyNamingPolicy; + + if (namingPolicy == null) + { + _keyName = KeyNameCLR; + _valueName = ValueNameCLR; + } + else + { + _keyName = namingPolicy.ConvertName(KeyNameCLR); + _valueName = namingPolicy.ConvertName(ValueNameCLR); + + if (_keyName == null || _valueName == null) + { + ThrowHelper.ThrowInvalidOperationException_NamingPolicyReturnNull(namingPolicy); + } + } + + JavaScriptEncoder? encoder = options.Encoder; + _keyNameEncoded = JsonEncodedText.Encode(_keyName, encoder); + _valueNameEncoded = JsonEncodedText.Encode(_valueName, encoder); + } + internal override bool OnTryRead( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, @@ -44,17 +73,19 @@ internal sealed class KeyValuePairConverter : JsonValueConverter(ref reader, options, ref state, KeyName); + k = JsonSerializer.Deserialize(ref reader, options, ref state, _keyName); keySet = true; } - else if (propertyName == ValueName) + else if (FoundValueProperty(propertyName, caseInsensitiveMatch)) { reader.ReadWithVerify(); - v = JsonSerializer.Deserialize(ref reader, options, ref state, ValueName); + v = JsonSerializer.Deserialize(ref reader, options, ref state, _valueName); valueSet = true; } else @@ -70,28 +101,21 @@ internal sealed class KeyValuePairConverter : JsonValueConverter(ref reader, options, ref state, KeyName); - keySet = true; + k = JsonSerializer.Deserialize(ref reader, options, ref state, _keyName); } - else if (propertyName == ValueName) + else if (!valueSet && FoundValueProperty(propertyName, caseInsensitiveMatch)) { reader.ReadWithVerify(); - v = JsonSerializer.Deserialize(ref reader, options, ref state, ValueName); - valueSet = true; + v = JsonSerializer.Deserialize(ref reader, options, ref state, _valueName); } else { ThrowHelper.ThrowJsonException(); } - if (!keySet || !valueSet) - { - ThrowHelper.ThrowJsonException(); - } - reader.ReadWithVerify(); if (reader.TokenType != JsonTokenType.EndObject) @@ -99,7 +123,7 @@ internal sealed class KeyValuePairConverter : JsonValueConverter(k, v); + value = new KeyValuePair(k!, v!); return true; } @@ -107,14 +131,28 @@ internal override bool OnTryWrite(Utf8JsonWriter writer, KeyValuePair converter) public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + // We do not check _converter.HandleNull, as the underlying struct cannot be null. + // A custom converter for some type T? can handle null. if (reader.TokenType == JsonTokenType.Null) { return null; @@ -30,6 +32,8 @@ public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOption { if (!value.HasValue) { + // We do not check _converter.HandleNull, as the underlying struct cannot be null. + // A custom converter for some type T? can handle null. writer.WriteNullValue(); } else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs index 889471432accd..0e88b3fb048c3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.Cache.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -49,22 +48,6 @@ internal sealed partial class JsonClassInfo // Use an array (instead of List) for highest performance. private volatile PropertyRef[]? _propertyRefsSorted; - private Dictionary CreatePropertyCache(int capacity) - { - StringComparer comparer; - - if (Options.PropertyNameCaseInsensitive) - { - comparer = StringComparer.OrdinalIgnoreCase; - } - else - { - comparer = StringComparer.Ordinal; - } - - return new Dictionary(capacity, comparer); - } - public Dictionary CreateParameterCache(int capacity, JsonSerializerOptions options) { if (options.PropertyNameCaseInsensitive) @@ -145,21 +128,24 @@ public static JsonPropertyInfo AddProperty(PropertyInfo propertyInfo, Type paren runtimePropertyType: runtimePropertyType, propertyInfo: null, // Not a real property so this is null. parentClassType: typeof(object), // a dummy value (not used) - converter : converter, + converter: converter, options); } // AggressiveInlining used although a large method it is only called from one location and is on a hot path. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadStackFrame frame) + public JsonPropertyInfo GetProperty( + ReadOnlySpan propertyName, + ref ReadStackFrame frame, + out byte[] utf8PropertyName) { - JsonPropertyInfo? info = null; + PropertyRef propertyRef; + + ulong key = GetKey(propertyName); // Keep a local copy of the cache in case it changes by another thread. PropertyRef[]? localPropertyRefsSorted = _propertyRefsSorted; - ulong key = GetKey(propertyName); - // If there is an existing cache, then use it. if (localPropertyRefsSorted != null) { @@ -174,10 +160,11 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta { if (iForward < count) { - PropertyRef propertyRef = localPropertyRefsSorted[iForward]; - if (TryIsPropertyRefEqual(propertyRef, propertyName, key, ref info)) + propertyRef = localPropertyRefsSorted[iForward]; + if (IsPropertyRefEqual(propertyRef, propertyName, key)) { - return info; + utf8PropertyName = propertyRef.NameFromJson; + return propertyRef.Info; } ++iForward; @@ -185,9 +172,10 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta if (iBackward >= 0) { propertyRef = localPropertyRefsSorted[iBackward]; - if (TryIsPropertyRefEqual(propertyRef, propertyName, key, ref info)) + if (IsPropertyRefEqual(propertyRef, propertyName, key)) { - return info; + utf8PropertyName = propertyRef.NameFromJson; + return propertyRef.Info; } --iBackward; @@ -195,10 +183,11 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta } else if (iBackward >= 0) { - PropertyRef propertyRef = localPropertyRefsSorted[iBackward]; - if (TryIsPropertyRefEqual(propertyRef, propertyName, key, ref info)) + propertyRef = localPropertyRefsSorted[iBackward]; + if (IsPropertyRefEqual(propertyRef, propertyName, key)) { - return info; + utf8PropertyName = propertyRef.NameFromJson; + return propertyRef.Info; } --iBackward; @@ -211,24 +200,39 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta } } - // No cached item was found. Try the main list which has all of the properties. - - string stringPropertyName = JsonHelpers.Utf8GetString(propertyName); - + // No cached item was found. Try the main dictionary which has all of the properties. Debug.Assert(PropertyCache != null); - if (!PropertyCache.TryGetValue(stringPropertyName, out info)) + if (PropertyCache.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonPropertyInfo? info)) { - info = JsonPropertyInfo.s_missingProperty; - } + if (Options.PropertyNameCaseInsensitive) + { + if (propertyName.SequenceEqual(info.NameAsUtf8Bytes)) + { + Debug.Assert(key == GetKey(info.NameAsUtf8Bytes.AsSpan())); - Debug.Assert(info != null); + // Use the existing byte[] reference instead of creating another one. + utf8PropertyName = info.NameAsUtf8Bytes!; + } + else + { + // Make a copy of the original Span. + utf8PropertyName = propertyName.ToArray(); + } + } + else + { + Debug.Assert(key == GetKey(info.NameAsUtf8Bytes!.AsSpan())); + utf8PropertyName = info.NameAsUtf8Bytes!; + } + } + else + { + info = JsonPropertyInfo.s_missingProperty; - // Three code paths to get here: - // 1) info == s_missingProperty. Property not found. - // 2) key == info.PropertyNameKey. Exact match found. - // 3) key != info.PropertyNameKey. Match found due to case insensitivity. - Debug.Assert(info == JsonPropertyInfo.s_missingProperty || key == info.PropertyNameKey || Options.PropertyNameCaseInsensitive); + // Make a copy of the original Span. + utf8PropertyName = propertyName.ToArray(); + } // Check if we should add this to the cache. // Only cache up to a threshold length and then just use the dictionary when an item is not found in the cache. @@ -255,7 +259,9 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta frame.PropertyRefCache = new List(); } - PropertyRef propertyRef = new PropertyRef(key, info); + Debug.Assert(info != null); + + propertyRef = new PropertyRef(key, info, utf8PropertyName); frame.PropertyRefCache.Add(propertyRef); } } @@ -265,18 +271,18 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta // AggressiveInlining used although a large method it is only called from one location and is on a hot path. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGetParameter( + public JsonParameterInfo? GetParameter( ReadOnlySpan propertyName, ref ReadStackFrame frame, - out JsonParameterInfo? jsonParameterInfo) + out byte[] utf8PropertyName) { - JsonParameterInfo? info = null; + ParameterRef parameterRef; + + ulong key = GetKey(propertyName); // Keep a local copy of the cache in case it changes by another thread. ParameterRef[]? localParameterRefsSorted = _parameterRefsSorted; - ulong key = GetKey(propertyName); - // If there is an existing cache, then use it. if (localParameterRefsSorted != null) { @@ -291,11 +297,11 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta { if (iForward < count) { - ParameterRef parameterRef = localParameterRefsSorted[iForward]; - if (TryIsParameterRefEqual(parameterRef, propertyName, key, ref info)) + parameterRef = localParameterRefsSorted[iForward]; + if (IsParameterRefEqual(parameterRef, propertyName, key)) { - jsonParameterInfo = info; - return true; + utf8PropertyName = parameterRef.NameFromJson; + return parameterRef.Info; } ++iForward; @@ -303,10 +309,10 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta if (iBackward >= 0) { parameterRef = localParameterRefsSorted[iBackward]; - if (TryIsParameterRefEqual(parameterRef, propertyName, key, ref info)) + if (IsParameterRefEqual(parameterRef, propertyName, key)) { - jsonParameterInfo = info; - return true; + utf8PropertyName = parameterRef.NameFromJson; + return parameterRef.Info; } --iBackward; @@ -314,11 +320,11 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta } else if (iBackward >= 0) { - ParameterRef parameterRef = localParameterRefsSorted[iBackward]; - if (TryIsParameterRefEqual(parameterRef, propertyName, key, ref info)) + parameterRef = localParameterRefsSorted[iBackward]; + if (IsParameterRefEqual(parameterRef, propertyName, key)) { - jsonParameterInfo = info; - return true; + utf8PropertyName = parameterRef.NameFromJson; + return parameterRef.Info; } --iBackward; @@ -331,26 +337,39 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta } } - string propertyNameAsString = JsonHelpers.Utf8GetString(propertyName); - + // No cached item was found. Try the main dictionary which has all of the parameters. Debug.Assert(ParameterCache != null); - if (!ParameterCache.TryGetValue(propertyNameAsString, out info)) + if (ParameterCache.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonParameterInfo? info)) { - // Constructor parameter not found. We'll check if it's a property next. - jsonParameterInfo = null; - return false; - } + if (Options.PropertyNameCaseInsensitive) + { + if (propertyName.SequenceEqual(info.NameAsUtf8Bytes)) + { + Debug.Assert(key == GetKey(info.NameAsUtf8Bytes.AsSpan())); - jsonParameterInfo = info; - Debug.Assert(info != null); + // Use the existing byte[] reference instead of creating another one. + utf8PropertyName = info.NameAsUtf8Bytes!; + } + else + { + // Make a copy of the original Span. + utf8PropertyName = propertyName.ToArray(); + } + } + else + { + Debug.Assert(key == GetKey(info.NameAsUtf8Bytes!.AsSpan())); + utf8PropertyName = info.NameAsUtf8Bytes!; + } + } + else + { + Debug.Assert(info == null); - // Two code paths to get here: - // 1) key == info.PropertyNameKey. Exact match found. - // 2) key != info.PropertyNameKey. Match found due to case insensitivity. - // TODO: recheck these conditions - Debug.Assert(key == info.ParameterNameKey || - propertyNameAsString.Equals(info.NameAsString, StringComparison.OrdinalIgnoreCase)); + // Make a copy of the original Span. + utf8PropertyName = propertyName.ToArray(); + } // Check if we should add this to the cache. // Only cache up to a threshold length and then just use the dictionary when an item is not found in the cache. @@ -377,24 +396,23 @@ public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadSta frame.CtorArgumentState.ParameterRefCache = new List(); } - ParameterRef parameterRef = new ParameterRef(key, jsonParameterInfo); + parameterRef = new ParameterRef(key, info!, utf8PropertyName); frame.CtorArgumentState.ParameterRefCache.Add(parameterRef); } } - return true; + return info; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryIsPropertyRefEqual(in PropertyRef propertyRef, ReadOnlySpan propertyName, ulong key, [NotNullWhen(true)] ref JsonPropertyInfo? info) + private static bool IsPropertyRefEqual(in PropertyRef propertyRef, ReadOnlySpan propertyName, ulong key) { if (key == propertyRef.Key) { // We compare the whole name, although we could skip the first 7 bytes (but it's not any faster) if (propertyName.Length <= PropertyNameKeyLength || - propertyName.SequenceEqual(propertyRef.Info.Name)) + propertyName.SequenceEqual(propertyRef.NameFromJson)) { - info = propertyRef.Info; return true; } } @@ -403,15 +421,14 @@ private static bool TryIsPropertyRefEqual(in PropertyRef propertyRef, ReadOnlySp } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryIsParameterRefEqual(in ParameterRef parameterRef, ReadOnlySpan parameterName, ulong key, [NotNullWhen(true)] ref JsonParameterInfo? info) + private static bool IsParameterRefEqual(in ParameterRef parameterRef, ReadOnlySpan parameterName, ulong key) { if (key == parameterRef.Key) { // We compare the whole name, although we could skip the first 7 bytes (but it's not any faster) if (parameterName.Length <= PropertyNameKeyLength || - parameterName.SequenceEqual(parameterRef.Info.ParameterName)) + parameterName.SequenceEqual(parameterRef.NameFromJson)) { - info = parameterRef.Info; return true; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs index cc2861b3aacc8..b97b6117923d4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs @@ -96,52 +96,56 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) case ClassType.Object: { CreateObject = options.MemberAccessorStrategy.CreateConstructor(type); + Dictionary cache = new Dictionary( + Options.PropertyNameCaseInsensitive + ? StringComparer.OrdinalIgnoreCase + : StringComparer.Ordinal); - PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - Dictionary cache = CreatePropertyCache(properties.Length); - - foreach (PropertyInfo propertyInfo in properties) + for (Type? currentType = type; currentType != null; currentType = currentType.BaseType) { - // Ignore indexers - if (propertyInfo.GetIndexParameters().Length > 0) - { - continue; - } - - if (IsNonPublicProperty(propertyInfo)) + foreach (PropertyInfo propertyInfo in currentType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { - if (JsonPropertyInfo.GetAttribute(propertyInfo) != null) + // Ignore indexers + if (propertyInfo.GetIndexParameters().Length > 0) { - ThrowHelper.ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(propertyInfo, Type); + continue; } - // Non-public properties should not be included for (de)serialization. - continue; - } - - // For now we only support public getters\setters - if (propertyInfo.GetMethod?.IsPublic == true || - propertyInfo.SetMethod?.IsPublic == true) - { - JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo, type, options); - Debug.Assert(jsonPropertyInfo != null && jsonPropertyInfo.NameAsString != null); - - // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception. - if (!JsonHelpers.TryAdd(cache, jsonPropertyInfo.NameAsString, jsonPropertyInfo)) + // For now we only support public getters\setters + if (propertyInfo.GetMethod?.IsPublic == true || + propertyInfo.SetMethod?.IsPublic == true) { - JsonPropertyInfo other = cache[jsonPropertyInfo.NameAsString]; + JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo, currentType, options); + Debug.Assert(jsonPropertyInfo != null && jsonPropertyInfo.NameAsString != null); - if (other.ShouldDeserialize == false && other.ShouldSerialize == false) + // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception. + if (!JsonHelpers.TryAdd(cache, jsonPropertyInfo.NameAsString, jsonPropertyInfo)) { - // Overwrite the one just added since it has [JsonIgnore]. - cache[jsonPropertyInfo.NameAsString] = jsonPropertyInfo; + JsonPropertyInfo other = cache[jsonPropertyInfo.NameAsString]; + + if (other.ShouldDeserialize == false && other.ShouldSerialize == false) + { + // Overwrite the one just added since it has [JsonIgnore]. + cache[jsonPropertyInfo.NameAsString] = jsonPropertyInfo; + } + else if (other.PropertyInfo?.Name != jsonPropertyInfo.PropertyInfo?.Name && + (jsonPropertyInfo.ShouldDeserialize == true || jsonPropertyInfo.ShouldSerialize == true)) + { + // Check for name equality is required to determine when a new slot is used for the member. + // Therefore, if names are not the same, there is conflict due to the name policy or attributes. + ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(Type, jsonPropertyInfo); + } + // else ignore jsonPropertyInfo since it has [JsonIgnore] or it's hidden by a new slot. } - else if (jsonPropertyInfo.ShouldDeserialize == true || jsonPropertyInfo.ShouldSerialize == true) + } + else + { + if (JsonPropertyInfo.GetAttribute(propertyInfo) != null) { - ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(Type, jsonPropertyInfo); + ThrowHelper.ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(propertyInfo, currentType); } - // else ignore jsonPropertyInfo since it has [JsonIgnore]. + + // Non-public properties should not be included for (de)serialization. } } } @@ -162,15 +166,23 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) cacheArray = new JsonPropertyInfo[cache.Count]; } - // Set fields when finished to avoid concurrency issues. - PropertyCache = cache; + // Copy the dictionary cache to the array cache. cache.Values.CopyTo(cacheArray, 0); + + // Set the array cache field at this point since it is completely initialized. + // It can now be safely accessed by other threads. PropertyCacheArray = cacheArray; + // Allow constructor parameter logic to remove items from the dictionary since the JSON + // property values will be passed to the constructor and do not call a property setter. if (converter.ConstructorIsParameterized) { - InitializeConstructorParameters(converter.ConstructorInfo!); + InitializeConstructorParameters(cache, converter.ConstructorInfo!); } + + // Set the dictionary cache field at this point since it is completely initialized. + // It can now be safely accessed by other threads. + PropertyCache = cache; } break; case ClassType.Enumerable: @@ -197,20 +209,11 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) } } - private static bool IsNonPublicProperty(PropertyInfo propertyInfo) - { - MethodInfo? getMethod = propertyInfo.GetMethod; - MethodInfo? setMethod = propertyInfo.SetMethod; - return !((getMethod != null && getMethod.IsPublic) || (setMethod != null && setMethod.IsPublic)); - } - - private void InitializeConstructorParameters(ConstructorInfo constructorInfo) + private void InitializeConstructorParameters(Dictionary propertyCache, ConstructorInfo constructorInfo) { ParameterInfo[] parameters = constructorInfo!.GetParameters(); Dictionary parameterCache = CreateParameterCache(parameters.Length, Options); - Dictionary propertyCache = PropertyCache!; - foreach (ParameterInfo parameterInfo in parameters) { PropertyInfo? firstMatch = null; @@ -245,7 +248,7 @@ private void InitializeConstructorParameters(ConstructorInfo constructorInfo) // One object property cannot map to multiple constructor // parameters (ConvertName above can't return multiple strings). - parameterCache.Add(jsonParameterInfo.NameAsString, jsonParameterInfo); + parameterCache.Add(jsonPropertyInfo.NameAsString!, jsonParameterInfo); // Remove property from deserialization cache to reduce the number of JsonPropertyInfos considered during JSON matching. propertyCache.Remove(jsonPropertyInfo.NameAsString!); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs index 9b7a706678c36..361236c42d60b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs @@ -40,12 +40,6 @@ public abstract partial class JsonConverter internal abstract Type? ElementType { get; } - /// - /// Cached value of ShouldHandleNullValue. It is cached since the converter should never - /// change the value depending on state and because it may contain non-trival logic. - /// - internal bool HandleNullValue { get; set; } - /// /// Cached value of TypeToConvert.IsValueType, which is an expensive call. /// @@ -79,5 +73,7 @@ internal bool ShouldFlush(Utf8JsonWriter writer, ref WriteStack state) internal virtual bool ConstructorIsParameterized => false; internal ConstructorInfo? ConstructorInfo { get; set; } + + internal virtual void Initialize(JsonSerializerOptions options) { } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs index 1785b669b2552..c49fd0d7947db 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs @@ -2,6 +2,8 @@ // 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.Diagnostics.CodeAnalysis; + namespace System.Text.Json.Serialization { public partial class JsonConverter @@ -14,6 +16,7 @@ public partial class JsonConverter return ReadCore(ref reader, options, ref state); } + [return: MaybeNull] internal T ReadCore( ref Utf8JsonReader reader, JsonSerializerOptions options, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs index 158094fd661eb..bce4c1224ced7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs @@ -2,6 +2,7 @@ // 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.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -22,7 +23,8 @@ protected internal JsonConverter() // In the future, this will be check for !IsSealed (and excluding value types). CanBePolymorphic = TypeToConvert == typeof(object); IsValueType = TypeToConvert.IsValueType; - HandleNullValue = ShouldHandleNullValue; + HandleNull = IsValueType; + CanBeNull = !IsValueType || Nullable.GetUnderlyingType(TypeToConvert) != null; IsInternalConverter = GetType().Assembly == typeof(JsonConverter).Assembly; CanUseDirectReadOrWrite = !CanBePolymorphic && IsInternalConverter && ClassType == ClassType.Value; } @@ -54,16 +56,27 @@ internal override sealed JsonParameterInfo CreateJsonParameterInfo() internal override Type? ElementType => null; - // Allow a converter that can't be null to return a null value representation, such as JsonElement or Nullable<>. - // In other cases, this will likely cause an JsonException in the converter. - // Do not call this directly; it is cached in HandleNullValue. - internal virtual bool ShouldHandleNullValue => IsValueType; + /// + /// Indicates whether should be passed to the converter on serialization, + /// and whether should be passed on deserialization. + /// + /// + /// The default value is for converters for value types, and for converters for reference types. + /// + public virtual bool HandleNull { get; } + + /// + /// Can be assigned to ? + /// + internal bool CanBeNull { get; } /// /// Is the converter built-in. /// internal bool IsInternalConverter { get; set; } + internal readonly EqualityComparer _defaultComparer = EqualityComparer.Default; + // This non-generic API is sealed as it just forwards to the generic version. internal sealed override bool TryWriteAsObject(Utf8JsonWriter writer, object? value, JsonSerializerOptions options, ref WriteStack state) { @@ -79,7 +92,7 @@ internal virtual bool OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerO } // Provide a default implementation for value converters. - internal virtual bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) + internal virtual bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNull] out T value) { value = Read(ref reader, typeToConvert, options); return true; @@ -95,9 +108,10 @@ internal virtual bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, J /// The being converted. /// The being used. /// The value that was converted. + [return: MaybeNull] public abstract T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options); - internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T value) + internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNull] out T value) { if (ClassType == ClassType.Value) { @@ -105,9 +119,14 @@ internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSeriali Debug.Assert(!state.IsContinuation); // For perf and converter simplicity, handle null here instead of forwarding to the converter. - if (reader.TokenType == JsonTokenType.Null && !HandleNullValue) + if (reader.TokenType == JsonTokenType.Null && !HandleNull) { - value = default!; + if (!CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); + } + + value = default; return true; } @@ -147,10 +166,15 @@ internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSeriali // For performance, only perform validation on internal converters on debug builds. if (IsInternalConverter) { - if (reader.TokenType == JsonTokenType.Null && !HandleNullValue && !wasContinuation) + if (reader.TokenType == JsonTokenType.Null && !HandleNull && !wasContinuation) { + if (!CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); + } + // For perf and converter simplicity, handle null here instead of forwarding to the converter. - value = default!; + value = default; success = true; } else @@ -164,9 +188,14 @@ internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSeriali if (!wasContinuation) { // For perf and converter simplicity, handle null here instead of forwarding to the converter. - if (reader.TokenType == JsonTokenType.Null && !HandleNullValue) + if (reader.TokenType == JsonTokenType.Null && !HandleNull) { - value = default!; + if (!CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); + } + + value = default; state.Pop(true); return true; } @@ -213,7 +242,20 @@ internal bool TryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions opt { if (value == null) { - writer.WriteNullValue(); + if (!HandleNull) + { + writer.WriteNullValue(); + } + else + { + Debug.Assert(ClassType == ClassType.Value); + Debug.Assert(!state.IsContinuation); + + int originalPropertyDepth = writer.CurrentDepth; + Write(writer, value, options); + VerifyWrite(originalPropertyDepth, writer); + } + return true; } @@ -236,15 +278,12 @@ internal bool TryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions opt } } } - else + else if (value == null && !HandleNull) { - // We do not pass null values to converters unless HandleNullValue is true. Null values for properties were + // We do not pass null values to converters unless HandleNull is true. Null values for properties were // already handled in GetMemberAndWriteJson() so we don't need to check for IgnoreNullValues here. - if (value == null && !HandleNullValue) - { - writer.WriteNullValue(); - return true; - } + writer.WriteNullValue(); + return true; } if (ClassType == ClassType.Value) @@ -255,7 +294,6 @@ internal bool TryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions opt Write(writer, value, options); VerifyWrite(originalPropertyDepth, writer); - return true; } @@ -299,48 +337,30 @@ internal bool TryWriteDataExtensionProperty(Utf8JsonWriter writer, T value, Json ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth); } - bool success; JsonDictionaryConverter dictionaryConverter = (JsonDictionaryConverter)this; - if (ClassType == ClassType.Value) - { - Debug.Assert(!state.IsContinuation); - - int originalPropertyDepth = writer.CurrentDepth; + bool isContinuation = state.IsContinuation; + bool success; - // Ignore the naming policy for extension data. - state.Current.IgnoreDictionaryKeyPolicy = true; + state.Push(); - success = dictionaryConverter.OnWriteResume(writer, value, options, ref state); - if (success) - { - VerifyWrite(originalPropertyDepth, writer); - } - } - else + if (!isContinuation) { - bool isContinuation = state.IsContinuation; - - state.Push(); - - if (!isContinuation) - { - Debug.Assert(state.Current.OriginalDepth == 0); - state.Current.OriginalDepth = writer.CurrentDepth; - } - - // Ignore the naming policy for extension data. - state.Current.IgnoreDictionaryKeyPolicy = true; + Debug.Assert(state.Current.OriginalDepth == 0); + state.Current.OriginalDepth = writer.CurrentDepth; + } - success = dictionaryConverter.OnWriteResume(writer, value, options, ref state); - if (success) - { - VerifyWrite(state.Current.OriginalDepth, writer); - } + // Ignore the naming policy for extension data. + state.Current.IgnoreDictionaryKeyPolicy = true; - state.Pop(success); + success = dictionaryConverter.OnWriteResume(writer, value, options, ref state); + if (success) + { + VerifyWrite(state.Current.OriginalDepth, writer); } + state.Pop(success); + return success; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonIgnoreCondition.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonIgnoreCondition.cs index 70a8bca3ad378..93239931addbb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonIgnoreCondition.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonIgnoreCondition.cs @@ -5,21 +5,24 @@ namespace System.Text.Json.Serialization { /// - /// Controls how the ignores properties on serialization and deserialization. + /// When specified on , + /// specifies that properties with default values are ignored during serialization. + /// When specified on , controls whether + /// a property is ignored during serialization and deserialization. /// public enum JsonIgnoreCondition { /// - /// Property will always be ignored. + /// Property is never ignored during serialization or deserialization. /// - Always = 0, + Never = 0, /// - /// Property will only be ignored if it is null. + /// Property is always ignored during serialization and deserialization. /// - WhenNull = 1, + Always = 1, /// - /// Property will always be serialized and deserialized, regardless of configuration. + /// If the value is the default, the property is ignored during serialization. /// - Never = 2 + WhenWritingDefault = 2, } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfo.cs index d531d9f9c2d27..f2d8408205d31 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfo.cs @@ -22,22 +22,13 @@ internal abstract class JsonParameterInfo // The default value of the parameter. This is `DefaultValue` of the `ParameterInfo`, if specified, or the CLR `default` for the `ParameterType`. public object? DefaultValue { get; protected set; } - // The name from a Json value. This is cached for performance on first deserialize. - public byte[]? JsonPropertyName { get; set; } - // Options can be referenced here since all JsonPropertyInfos originate from a JsonClassInfo that is cached on JsonSerializerOptions. protected JsonSerializerOptions Options { get; set; } = null!; // initialized in Init method public ParameterInfo ParameterInfo { get; private set; } = null!; // The name of the parameter as UTF-8 bytes. - public byte[] ParameterName { get; private set; } = null!; - - // The name of the parameter. - public string NameAsString { get; private set; } = null!; - - // Key for fast property name lookup. - public ulong ParameterNameKey { get; private set; } + public byte[] NameAsUtf8Bytes { get; private set; } = null!; // The zero-based position of the parameter in the formal parameter list. public int Position { get; private set; } @@ -77,12 +68,7 @@ public JsonClassInfo RuntimeClassInfo private void DetermineParameterName(JsonPropertyInfo matchingProperty) { - NameAsString = matchingProperty.NameAsString!; - - // `NameAsString` is valid UTF16, so just call the simple UTF16->UTF8 encoder. - ParameterName = Encoding.UTF8.GetBytes(NameAsString); - - ParameterNameKey = JsonClassInfo.GetKey(ParameterName); + NameAsUtf8Bytes = matchingProperty.NameAsUtf8Bytes!; } // Create a parameter that is ignored at run-time. It uses the same type (typeof(sbyte)) to help diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfoOfT.cs index 52a68effdc3aa..a03982f4e40d8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonParameterInfoOfT.cs @@ -2,6 +2,7 @@ // 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.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Json.Serialization; @@ -53,9 +54,14 @@ public override bool ReadJson(ref ReadStack state, ref Utf8JsonReader reader, ou bool success; bool isNullToken = reader.TokenType == JsonTokenType.Null; - if (isNullToken && !_converter.HandleNullValue && !state.IsContinuation) + if (isNullToken && !_converter.HandleNull && !state.IsContinuation) { - // Don't have to check for IgnoreNullValue option here because we set the default value (likely null) regardless + if (!_converter.CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(_converter.TypeToConvert); + } + + // Don't have to check for IgnoreNullValue option here because we set the default value regardless. value = DefaultValue; return true; } @@ -77,13 +83,19 @@ public override bool ReadJson(ref ReadStack state, ref Utf8JsonReader reader, ou return success; } - public bool ReadJsonTyped(ref ReadStack state, ref Utf8JsonReader reader, out T value) + public bool ReadJsonTyped(ref ReadStack state, ref Utf8JsonReader reader, [MaybeNull] out T value) { bool success; bool isNullToken = reader.TokenType == JsonTokenType.Null; - if (isNullToken && !_converter.HandleNullValue && !state.IsContinuation) + if (isNullToken && !_converter.HandleNull && !state.IsContinuation) { + if (!_converter.CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(_converter.TypeToConvert); + } + + // Don't have to check for IgnoreNullValue option here because we set the default value regardless. value = TypedDefaultValue; return true; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs index 5c43c5d8bfb0f..4e345309e244c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs @@ -83,13 +83,10 @@ private void DeterminePropertyName() Debug.Assert(NameAsString != null); // At this point propertyName is valid UTF16, so just call the simple UTF16->UTF8 encoder. - Name = Encoding.UTF8.GetBytes(NameAsString); + NameAsUtf8Bytes = Encoding.UTF8.GetBytes(NameAsString); // Cache the escaped property name. - EscapedName = JsonEncodedText.Encode(Name, Options.Encoder); - - ulong key = JsonClassInfo.GetKey(Name); - PropertyNameKey = key; + EscapedName = JsonEncodedText.Encode(NameAsString, NameAsUtf8Bytes, Options.Encoder); } private void DetermineSerializationCapabilities(JsonIgnoreCondition? ignoreCondition) @@ -135,20 +132,25 @@ private void DetermineIgnoreCondition(JsonIgnoreCondition? ignoreCondition) if (ignoreCondition != JsonIgnoreCondition.Never) { - Debug.Assert(ignoreCondition == JsonIgnoreCondition.WhenNull); - IgnoreNullValues = true; + Debug.Assert(ignoreCondition == JsonIgnoreCondition.WhenWritingDefault); + IgnoreDefaultValuesOnWrite = true; } } - else +#pragma warning disable CS0618 // IgnoreNullValues is obsolete + else if (Options.IgnoreNullValues) + { + Debug.Assert(Options.DefaultIgnoreCondition == JsonIgnoreCondition.Never); + IgnoreDefaultValuesOnRead = true; + IgnoreDefaultValuesOnWrite = true; + } + else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault) { - IgnoreNullValues = Options.IgnoreNullValues; + Debug.Assert(!Options.IgnoreNullValues); + IgnoreDefaultValuesOnWrite = true; } +#pragma warning restore CS0618 // IgnoreNullValues is obsolete } - // The escaped name passed to the writer. - // Use a field here (not a property) to avoid value semantics. - public JsonEncodedText? EscapedName; - public static TAttribute? GetAttribute(PropertyInfo propertyInfo) where TAttribute : Attribute { return (TAttribute?)propertyInfo.GetCustomAttribute(typeof(TAttribute), inherit: false); @@ -190,19 +192,37 @@ public virtual void GetPolicies(JsonIgnoreCondition? ignoreCondition) Options = options; } - public bool IgnoreNullValues { get; private set; } + public bool IgnoreDefaultValuesOnRead { get; private set; } + public bool IgnoreDefaultValuesOnWrite { get; private set; } public bool IsPropertyPolicy { get; protected set; } - // The name from a Json value. This is cached for performance on first deserialize. - public byte[]? JsonPropertyName { get; set; } - - // The name of the property with any casing policy or the name specified from JsonPropertyNameAttribute. - public byte[]? Name { get; private set; } + // There are 3 copies of the property name: + // 1) NameAsString. The unescaped property name. + // 2) NameAsUtf8Bytes. The Utf8 version of NameAsString. Used during during deserialization for property lookup. + // 3) EscapedName. The escaped verson of NameAsString and NameAsUtf8Bytes written during serialization. Internally shares + // the same instances of NameAsString and NameAsUtf8Bytes if there is no escaping. + + /// + /// The unescaped name of the property. + /// Is either the actual CLR property name, + /// the value specified in JsonPropertyNameAttribute, + /// or the value returned from PropertyNamingPolicy(clrPropertyName). + /// public string? NameAsString { get; private set; } - // Key for fast property name lookup. - public ulong PropertyNameKey { get; set; } + /// + /// Utf8 version of NameAsString. + /// + public byte[]? NameAsUtf8Bytes { get; private set; } + + /// + /// The escaped name passed to the writer. + /// + /// + /// JsonEncodedText is a value type so a field is used (not a property) to avoid unnecessary copies. + /// + public JsonEncodedText? EscapedName; // Options can be referenced here since all JsonPropertyInfos originate from a JsonClassInfo that is cached on JsonSerializerOptions. protected JsonSerializerOptions Options { get; set; } = null!; // initialized in Init method @@ -297,7 +317,7 @@ public JsonClassInfo RuntimeClassInfo public Type? RuntimePropertyType { get; private set; } = null; - public abstract void SetValueAsObject(object obj, object? value); + public abstract void SetExtensionDictionaryAsObject(object obj, object? extensionDict); public bool ShouldSerialize { get; private set; } public bool ShouldDeserialize { get; private set; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs index 863590f3b5f2b..648158cd6d703 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Text.Json.Serialization; namespace System.Text.Json @@ -15,6 +16,8 @@ namespace System.Text.Json /// or a type's converter, if the current instance is a . internal sealed class JsonPropertyInfo : JsonPropertyInfo { + private static readonly T s_defaultValue = default!; + public Func? Get { get; private set; } public Action? Set { get; private set; } @@ -98,13 +101,41 @@ public override bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf bool success; T value = Get!(obj); + if (value == null) { - if (!IgnoreNullValues) + Debug.Assert(s_defaultValue == null && Converter.CanBeNull); + + success = true; + if (!IgnoreDefaultValuesOnWrite) { - writer.WriteNull(EscapedName.Value); - } + if (!Converter.HandleNull) + { + writer.WriteNull(EscapedName.Value); + } + else + { + // No object, collection, or re-entrancy converter handles null. + Debug.Assert(Converter.ClassType == ClassType.Value); + + if (state.Current.PropertyState < StackFramePropertyState.Name) + { + state.Current.PropertyState = StackFramePropertyState.Name; + writer.WritePropertyName(EscapedName.Value); + } + int originalDepth = writer.CurrentDepth; + Converter.Write(writer, value, Options); + if (originalDepth != writer.CurrentDepth) + { + ThrowHelper.ThrowJsonException_SerializationConverterWrite(Converter); + } + } + } + } + else if (IgnoreDefaultValuesOnWrite && Converter._defaultComparer.Equals(s_defaultValue, value)) + { + Debug.Assert(s_defaultValue != null && !Converter.CanBeNull); success = true; } else @@ -141,10 +172,18 @@ public override bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteSta public override bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref Utf8JsonReader reader) { bool success; + bool isNullToken = reader.TokenType == JsonTokenType.Null; - if (isNullToken && !Converter.HandleNullValue && !state.IsContinuation) + if (isNullToken && !Converter.HandleNull && !state.IsContinuation) { - if (!IgnoreNullValues) + if (!Converter.CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Converter.TypeToConvert); + } + + Debug.Assert(s_defaultValue == null); + + if (!IgnoreDefaultValuesOnRead) { T value = default; Set!(obj, value!); @@ -152,29 +191,27 @@ public override bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref U success = true; } - else + else if (Converter.CanUseDirectReadOrWrite) { - // Get the value from the converter and set the property. - if (Converter.CanUseDirectReadOrWrite) + if (!(isNullToken && IgnoreDefaultValuesOnRead && Converter.CanBeNull)) { // Optimize for internal converters by avoiding the extra call to TryRead. T fastvalue = Converter.Read(ref reader, RuntimePropertyType!, Options); - if (!IgnoreNullValues || (!isNullToken && fastvalue != null)) - { - Set!(obj, fastvalue); - } - - return true; + Set!(obj, fastvalue!); } - else + + success = true; + } + else + { + success = true; + + if (!(isNullToken && IgnoreDefaultValuesOnRead && Converter.CanBeNull)) { success = Converter.TryRead(ref reader, RuntimePropertyType!, Options, ref state, out T value); if (success) { - if (!IgnoreNullValues || (!isNullToken && value != null)) - { - Set!(obj, value); - } + Set!(obj, value!); } } } @@ -186,8 +223,13 @@ public override bool ReadJsonAsObject(ref ReadStack state, ref Utf8JsonReader re { bool success; bool isNullToken = reader.TokenType == JsonTokenType.Null; - if (isNullToken && !Converter.HandleNullValue && !state.IsContinuation) + if (isNullToken && !Converter.HandleNull && !state.IsContinuation) { + if (!Converter.CanBeNull) + { + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Converter.TypeToConvert); + } + value = default(T)!; success = true; } @@ -197,7 +239,7 @@ public override bool ReadJsonAsObject(ref ReadStack state, ref Utf8JsonReader re if (Converter.CanUseDirectReadOrWrite) { value = Converter.Read(ref reader, RuntimePropertyType!, Options); - return true; + success = true; } else { @@ -209,15 +251,11 @@ public override bool ReadJsonAsObject(ref ReadStack state, ref Utf8JsonReader re return success; } - public override void SetValueAsObject(object obj, object? value) + public override void SetExtensionDictionaryAsObject(object obj, object? extensionDict) { Debug.Assert(HasSetter); - T typedValue = (T)value!; - - if (typedValue != null || !IgnoreNullValues) - { - Set!(obj, typedValue); - } + T typedValue = (T)extensionDict!; + Set!(obj, typedValue); } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs index e2aabd2ceacb9..9d25d2f38fceb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonResumableConverterOfT.cs @@ -2,6 +2,8 @@ // 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.Diagnostics.CodeAnalysis; + namespace System.Text.Json.Serialization { /// @@ -11,7 +13,8 @@ namespace System.Text.Json.Serialization /// internal abstract class JsonResumableConverter : JsonConverter { - public override sealed T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + [return: MaybeNull] + public sealed override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // Bridge from resumable to value converters. if (options == null) @@ -25,7 +28,7 @@ public override sealed T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso return value; } - public override sealed void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + public sealed override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // Bridge from resumable to value converters. if (options == null) @@ -37,5 +40,7 @@ public override sealed void Write(Utf8JsonWriter writer, T value, JsonSerializer state.Initialize(typeof(T), options, supportContinuation: false); TryWrite(writer, value, options, ref state); } + + public sealed override bool HandleNull => false; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs index a59a14fd63489..b7b4db728865a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs @@ -27,13 +27,21 @@ public static partial class JsonSerializer { Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Object); + useExtensionProperty = false; + ReadOnlySpan unescapedPropertyName = GetPropertyName(ref state, ref reader, options); - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.GetProperty(unescapedPropertyName, ref state.Current); + JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.GetProperty( + unescapedPropertyName, + ref state.Current, + out byte[] utf8PropertyName); - // Increment PropertyIndex so GetProperty() starts with the next property the next time this function is called. + // Increment PropertyIndex so GetProperty() checks the next property first when called again. state.Current.PropertyIndex++; + // For case insensitive and missing property support of JsonPath, remember the value on the temporary stack. + state.Current.JsonPropertyName = utf8PropertyName; + // Determine if we should use the extension property. if (jsonPropertyInfo == JsonPropertyInfo.s_missingProperty) { @@ -50,41 +58,9 @@ public static partial class JsonSerializer jsonPropertyInfo = dataExtProperty; useExtensionProperty = true; } - else - { - useExtensionProperty = false; - } - - state.Current.JsonPropertyInfo = jsonPropertyInfo; - return jsonPropertyInfo; } - // Support JsonException.Path. - Debug.Assert( - jsonPropertyInfo.JsonPropertyName == null || - options.PropertyNameCaseInsensitive || - unescapedPropertyName.SequenceEqual(jsonPropertyInfo.JsonPropertyName)); - state.Current.JsonPropertyInfo = jsonPropertyInfo; - - if (jsonPropertyInfo.JsonPropertyName == null) - { - byte[] propertyNameArray = unescapedPropertyName.ToArray(); - if (options.PropertyNameCaseInsensitive) - { - // Each payload can have a different name here; remember the value on the temporary stack. - state.Current.JsonPropertyName = propertyNameArray; - } - else - { - // Prevent future allocs by caching globally on the JsonPropertyInfo which is specific to a Type+PropertyName - // so it will match the incoming payload except when case insensitivity is enabled (which is handled above). - state.Current.JsonPropertyInfo.JsonPropertyName = propertyNameArray; - } - } - - state.Current.JsonPropertyInfo = jsonPropertyInfo; - useExtensionProperty = false; return jsonPropertyInfo; } @@ -146,7 +122,7 @@ public static partial class JsonSerializer } extensionData = jsonPropertyInfo.RuntimeClassInfo.CreateObject(); - jsonPropertyInfo.SetValueAsObject(obj, extensionData); + jsonPropertyInfo.SetExtensionDictionaryAsObject(obj, extensionData); } // We don't add the value to the dictionary here because we need to support the read-ahead functionality for Streams. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs index f8bf98def8199..bfdbd5993c65b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs @@ -3,12 +3,14 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; namespace System.Text.Json { public static partial class JsonSerializer { + [return: MaybeNull] private static TValue ReadCore(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options) { ReadStack state = default; @@ -17,6 +19,7 @@ private static TValue ReadCore(ref Utf8JsonReader reader, Type returnTyp return ReadCore(jsonConverter, ref reader, options, ref state); } + [return: MaybeNull] private static TValue ReadCore(JsonConverter jsonConverter, ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state) { if (jsonConverter is JsonConverter converter) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs index 5215d184204db..082c49645379e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs @@ -43,7 +43,7 @@ public static TValue Deserialize(string json, JsonSerializerOptions? opt throw new ArgumentNullException(nameof(json)); } - return Deserialize(json, typeof(TValue), options)!; + return Deserialize(json, typeof(TValue), options); } /// @@ -85,6 +85,7 @@ public static TValue Deserialize(string json, JsonSerializerOptions? opt return value; } + [return: MaybeNull] private static TValue Deserialize(string json, Type returnType, JsonSerializerOptions? options) { const long ArrayPoolMaxSizeBeforeUsingNormalAlloc = 1024 * 1024; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs index b7182ede223aa..666a6847094a3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs @@ -14,6 +14,7 @@ public static partial class JsonSerializer /// /// Internal version that allows re-entry with preserving ReadStack so that JsonPath works correctly. /// + [return: MaybeNull] internal static TValue Deserialize(ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state, string? propertyName = null) { if (options == null) @@ -162,6 +163,7 @@ private static void CheckSupportedOptions(JsonReaderOptions readerOptions, strin } } + [return: MaybeNull] private static TValue ReadValueCore(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state) { JsonReaderState readerState = reader.CurrentState; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerDefaults.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerDefaults.cs new file mode 100644 index 0000000000000..7df69c390daa7 --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerDefaults.cs @@ -0,0 +1,27 @@ +// 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. + +namespace System.Text.Json +{ + /// + /// Signifies what default options are used by . + /// + public enum JsonSerializerDefaults + { + /// + /// Specifies that general-purpose values should be used. These are the same settings applied if a isn't specified. + /// + /// + /// This option implies that property names are treated as case-sensitive and that "PascalCase" name formatting should be employed. + /// + General = 0, + /// + /// Specifies that values should be used more appropriate to web-based scenarios. + /// + /// + /// This option implies that property names are treated as case-insensitive and that "camelCase" name formatting should be employed. + /// + Web = 1 + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 53d1a676d107c..05b2aec0a2faa 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -3,10 +3,10 @@ // See the LICENSE file in the project root for more information. using System.Collections.Concurrent; +using System.ComponentModel; using System.Diagnostics; using System.Text.Json.Serialization; using System.Text.Encodings.Web; -using System.Reflection; namespace System.Text.Json { @@ -29,6 +29,7 @@ public sealed partial class JsonSerializerOptions private JsonCommentHandling _readCommentHandling; private ReferenceHandling _referenceHandling = ReferenceHandling.Default; private JavaScriptEncoder? _encoder = null; + private JsonIgnoreCondition _defaultIgnoreCondition; private int _defaultBufferSize = BufferSizeDefault; private int _maxDepth; @@ -61,12 +62,13 @@ public JsonSerializerOptions(JsonSerializerOptions options) throw new ArgumentNullException(nameof(options)); } - _memberAccessorStrategy = options.MemberAccessorStrategy; + _memberAccessorStrategy = options._memberAccessorStrategy; _dictionaryKeyPolicy = options._dictionaryKeyPolicy; _jsonPropertyNamingPolicy = options._jsonPropertyNamingPolicy; _readCommentHandling = options._readCommentHandling; _referenceHandling = options._referenceHandling; _encoder = options._encoder; + _defaultIgnoreCondition = options._defaultIgnoreCondition; _defaultBufferSize = options._defaultBufferSize; _maxDepth = options._maxDepth; @@ -82,7 +84,24 @@ public JsonSerializerOptions(JsonSerializerOptions options) // _classes is not copied as sharing the JsonClassInfo and JsonPropertyInfo caches can result in // unnecessary references to type metadata, potentially hindering garbage collection on the source options. - // _haveTypesBeenCreated is not copied; it's okay to make changes to this options instance as (de)serialization has not occured. + // _haveTypesBeenCreated is not copied; it's okay to make changes to this options instance as (de)serialization has not occurred. + } + + /// + /// Constructs a new instance with a predefined set of options determined by the specified . + /// + /// The to reason about. + public JsonSerializerOptions(JsonSerializerDefaults defaults) : this() + { + if (defaults == JsonSerializerDefaults.Web) + { + _propertyNameCaseInsensitive = true; + _jsonPropertyNamingPolicy = JsonNamingPolicy.CamelCase; + } + else if (defaults != JsonSerializerDefaults.General) + { + throw new ArgumentOutOfRangeException(nameof(defaults)); + } } /// @@ -178,7 +197,10 @@ public int DefaultBufferSize /// /// /// Thrown if this property is set after serialization or deserialization has occurred. + /// or has been set to a non-default value. These properties cannot be used together. /// + [Obsolete("To ignore null values when serializing, set DefaultIgnoreCondition to JsonIgnoreCondition.WhenWritingDefault.", error: false)] + [EditorBrowsable(EditorBrowsableState.Never)] public bool IgnoreNullValues { get @@ -188,10 +210,52 @@ public bool IgnoreNullValues set { VerifyMutable(); + + if (value && _defaultIgnoreCondition != JsonIgnoreCondition.Never) + { + Debug.Assert(_defaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault); + throw new InvalidOperationException(SR.DefaultIgnoreConditionAlreadySpecified); + } + _ignoreNullValues = value; } } + /// + /// Specifies a condition to determine when properties with default values are ignored during serialization or deserialization. + /// The default value is . + /// + /// + /// Thrown if this property is set to . + /// + /// + /// Thrown if this property is set after serialization or deserialization has occurred, + /// or has been set to . These properties cannot be used together. + /// + public JsonIgnoreCondition DefaultIgnoreCondition + { + get + { + return _defaultIgnoreCondition; + } + set + { + VerifyMutable(); + + if (value == JsonIgnoreCondition.Always) + { + throw new ArgumentException(SR.DefaultIgnoreConditionInvalid); + } + + if (value != JsonIgnoreCondition.Never && _ignoreNullValues) + { + throw new InvalidOperationException(SR.DefaultIgnoreConditionAlreadySpecified); + } + + _defaultIgnoreCondition = value; + } + } + /// /// Determines whether read-only properties are ignored during serialization. /// A property is read-only if it contains a public getter but not a public setter. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonValueConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonValueConverterOfT.cs index 5332509163f1d..67fa8c46bfeee 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonValueConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonValueConverterOfT.cs @@ -2,6 +2,8 @@ // 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.Diagnostics.CodeAnalysis; + namespace System.Text.Json.Serialization { // Used for value converters that need to re-enter the serializer since it will support JsonPath @@ -10,7 +12,10 @@ internal abstract class JsonValueConverter : JsonConverter { internal sealed override ClassType ClassType => ClassType.NewValue; - public override sealed T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public sealed override bool HandleNull => false; + + [return: MaybeNull] + public sealed override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // Bridge from resumable to value converters. if (options == null) @@ -24,7 +29,7 @@ public override sealed T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso return value; } - public override sealed void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + public sealed override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // Bridge from resumable to value converters. if (options == null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ParameterRef.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ParameterRef.cs index 9f2c654b5a913..f0ee05b6436ae 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ParameterRef.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ParameterRef.cs @@ -6,15 +6,18 @@ namespace System.Text.Json { internal readonly struct ParameterRef { - public ParameterRef(ulong key, JsonParameterInfo info) + public ParameterRef(ulong key, JsonParameterInfo info, byte[] nameFromJson) { Key = key; Info = info; + NameFromJson = nameFromJson; } - // The first 6 bytes are the first part of the name and last 2 bytes are the name's length. public readonly ulong Key; public readonly JsonParameterInfo Info; + + // NameFromJson may be different than Info.NameAsUtf8Bytes when case insensitive is enabled. + public readonly byte[] NameFromJson; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PropertyRef.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PropertyRef.cs index 41dbbe5e411e2..e092a7cfe5cdd 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PropertyRef.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PropertyRef.cs @@ -6,15 +6,17 @@ namespace System.Text.Json { internal readonly struct PropertyRef { - public PropertyRef(ulong key, JsonPropertyInfo info) + public PropertyRef(ulong key, JsonPropertyInfo info, byte[] nameFromJson) { Key = key; Info = info; + NameFromJson = nameFromJson; } - // The first 6 bytes are the first part of the name and last 2 bytes are the name's length. public readonly ulong Key; - public readonly JsonPropertyInfo Info; + + // NameFromJson may be different than Info.NameAsUtf8Bytes when case insensitive is enabled. + public readonly byte[] NameFromJson; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs index 3a9e0dddf145d..7e7f497a536cb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs @@ -298,8 +298,9 @@ static void AppendPropertyName(StringBuilder sb, string? propertyName) if (utf8PropertyName == null) { // Attempt to get the JSON property name from the JsonPropertyInfo or JsonParameterInfo. - utf8PropertyName = frame.JsonPropertyInfo?.JsonPropertyName ?? - frame.CtorArgumentState?.JsonParameterInfo?.JsonPropertyName; + utf8PropertyName = frame.JsonPropertyInfo?.NameAsUtf8Bytes ?? + frame.CtorArgumentState?.JsonParameterInfo?.NameAsUtf8Bytes; + if (utf8PropertyName == null) { // Attempt to get the JSON property name set manually for dictionary diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReferenceHandling.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReferenceHandling.cs index 2928b0f275814..269e0cb84b1bb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReferenceHandling.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReferenceHandling.cs @@ -53,8 +53,8 @@ public sealed class ReferenceHandling /// public static ReferenceHandling Preserve { get; } = new ReferenceHandling(PreserveReferencesHandling.All); - private readonly PreserveReferencesHandling _preserveHandlingOnSerialize; - private readonly PreserveReferencesHandling _preserveHandlingOnDeserialize; + private readonly bool _shouldReadPreservedReferences; + private readonly bool _shouldWritePreservedReferences; /// /// Creates a new instance of using the specified @@ -65,18 +65,18 @@ public sealed class ReferenceHandling // For future, someone may want to define their own custom Handler with different behaviors of PreserveReferenceHandling on Serialize vs Deserialize. private ReferenceHandling(PreserveReferencesHandling preserveHandlingOnSerialize, PreserveReferencesHandling preserveHandlingOnDeserialize) { - _preserveHandlingOnSerialize = preserveHandlingOnSerialize; - _preserveHandlingOnDeserialize = preserveHandlingOnDeserialize; + _shouldReadPreservedReferences = preserveHandlingOnDeserialize == PreserveReferencesHandling.All; + _shouldWritePreservedReferences = preserveHandlingOnSerialize == PreserveReferencesHandling.All; } internal bool ShouldReadPreservedReferences() { - return _preserveHandlingOnDeserialize == PreserveReferencesHandling.All; + return _shouldReadPreservedReferences; } internal bool ShouldWritePreservedReferences() { - return _preserveHandlingOnSerialize == PreserveReferencesHandling.All; + return _shouldWritePreservedReferences; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs index 137a74f593c65..a5d53eee033c1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs @@ -5,6 +5,7 @@ #if NETFRAMEWORK || NETCOREAPP using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Reflection.Emit; @@ -56,10 +57,14 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor return (JsonClassInfo.ConstructorDelegate)dynamicMethod.CreateDelegate(typeof(JsonClassInfo.ConstructorDelegate)); } - public override JsonClassInfo.ParameterizedConstructorDelegate? CreateParameterizedConstructor(ConstructorInfo constructor) + public override JsonClassInfo.ParameterizedConstructorDelegate? CreateParameterizedConstructor(ConstructorInfo constructor) => + CreateDelegate>(CreateParameterizedConstructor(constructor)); + + private static DynamicMethod? CreateParameterizedConstructor(ConstructorInfo constructor) { - Type type = typeof(T); + Type? type = constructor.DeclaringType; + Debug.Assert(type != null); Debug.Assert(!type.IsAbstract); Debug.Assert(type.GetConstructors(BindingFlags.Public | BindingFlags.Instance).Contains(constructor)); @@ -87,40 +92,35 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4_S, i); generator.Emit(OpCodes.Ldelem_Ref); - - if (paramType.IsValueType) - { - generator.Emit(OpCodes.Unbox_Any, paramType); - } - else - { - generator.Emit(OpCodes.Castclass, paramType); - }; + generator.Emit(OpCodes.Unbox_Any, paramType); } generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Ret); - return (JsonClassInfo.ParameterizedConstructorDelegate)dynamicMethod.CreateDelegate(typeof(JsonClassInfo.ParameterizedConstructorDelegate)); + return dynamicMethod; } public override JsonClassInfo.ParameterizedConstructorDelegate? - CreateParameterizedConstructor(ConstructorInfo constructor) + CreateParameterizedConstructor(ConstructorInfo constructor) => + CreateDelegate>( + CreateParameterizedConstructor(constructor, typeof(TArg0), typeof(TArg1), typeof(TArg2), typeof(TArg3))); + + private static DynamicMethod? CreateParameterizedConstructor(ConstructorInfo constructor, Type parameterType1, Type parameterType2, Type parameterType3, Type parameterType4) { - Type type = typeof(T); + Type? type = constructor.DeclaringType; + Debug.Assert(type != null); Debug.Assert(!type.IsAbstract); Debug.Assert(type.GetConstructors(BindingFlags.Public | BindingFlags.Instance).Contains(constructor)); ParameterInfo[] parameters = constructor.GetParameters(); int parameterCount = parameters.Length; - Debug.Assert(parameterCount <= JsonConstants.UnboxedParameterCountThreshold); - var dynamicMethod = new DynamicMethod( ConstructorInfo.ConstructorName, type, - new[] { typeof(TArg0), typeof(TArg1), typeof(TArg2), typeof(TArg3) }, + new[] { parameterType1, parameterType2, parameterType3, parameterType4 }, typeof(ReflectionEmitMemberAccessor).Module, skipVisibility: true); @@ -128,46 +128,37 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor for (int index = 0; index < parameterCount; index++) { - switch (index) - { - case 0: - generator.Emit(OpCodes.Ldarg_0); - break; - case 1: - generator.Emit(OpCodes.Ldarg_1); - break; - case 2: - generator.Emit(OpCodes.Ldarg_2); - break; - case 3: - generator.Emit(OpCodes.Ldarg_3); - break; - default: - Debug.Fail("We shouldn't be here if there are more than 4 parameters."); - throw new InvalidOperationException(); - } + Debug.Assert(index <= JsonConstants.UnboxedParameterCountThreshold); + + generator.Emit( + index switch + { + 0 => OpCodes.Ldarg_0, + 1 => OpCodes.Ldarg_1, + 2 => OpCodes.Ldarg_2, + 3 => OpCodes.Ldarg_3, + _ => throw new InvalidOperationException() + }); } generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Ret); - return (JsonClassInfo.ParameterizedConstructorDelegate) - dynamicMethod.CreateDelegate( - typeof(JsonClassInfo.ParameterizedConstructorDelegate)); + return dynamicMethod; } - public override Action CreateAddMethodDelegate() - { - Type collectionType = typeof(TCollection); - Type elementType = typeof(object); + public override Action CreateAddMethodDelegate() => + CreateDelegate>(CreateAddMethodDelegate(typeof(TCollection))); + private static DynamicMethod CreateAddMethodDelegate(Type collectionType) + { // We verified this won't be null when we created the converter that calls this method. MethodInfo realMethod = (collectionType.GetMethod("Push") ?? collectionType.GetMethod("Enqueue"))!; var dynamicMethod = new DynamicMethod( realMethod.Name, typeof(void), - new[] { collectionType, elementType }, + new[] { collectionType, typeof(object) }, typeof(ReflectionEmitMemberAccessor).Module, skipVisibility: true); @@ -178,18 +169,21 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor generator.Emit(OpCodes.Callvirt, realMethod); generator.Emit(OpCodes.Ret); - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); + return dynamicMethod; } - public override Func, TCollection> CreateImmutableEnumerableCreateRangeDelegate() + public override Func, TCollection> CreateImmutableEnumerableCreateRangeDelegate() => + CreateDelegate, TCollection>>( + CreateImmutableEnumerableCreateRangeDelegate(typeof(TCollection), typeof(TElement), typeof(IEnumerable))); + + private static DynamicMethod CreateImmutableEnumerableCreateRangeDelegate(Type collectionType, Type elementType, Type enumerableType) { - Type collectionType = typeof(TCollection); - MethodInfo realMethod = collectionType.GetImmutableEnumerableCreateRangeMethod(typeof(TElement)); + MethodInfo realMethod = collectionType.GetImmutableEnumerableCreateRangeMethod(elementType); var dynamicMethod = new DynamicMethod( realMethod.Name, collectionType, - new[] { typeof(IEnumerable) }, + new[] { enumerableType }, typeof(ReflectionEmitMemberAccessor).Module, skipVisibility: true); @@ -199,18 +193,21 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor generator.Emit(OpCodes.Call, realMethod); generator.Emit(OpCodes.Ret); - return (Func, TCollection>)dynamicMethod.CreateDelegate(typeof(Func, TCollection>)); + return dynamicMethod; } - public override Func>, TCollection> CreateImmutableDictionaryCreateRangeDelegate() + public override Func>, TCollection> CreateImmutableDictionaryCreateRangeDelegate() => + CreateDelegate>, TCollection>>( + CreateImmutableDictionaryCreateRangeDelegate(typeof(TCollection), typeof(TElement), typeof(IEnumerable>))); + + private static DynamicMethod CreateImmutableDictionaryCreateRangeDelegate(Type collectionType, Type elementType, Type enumerableType) { - Type collectionType = typeof(TCollection); - MethodInfo realMethod = collectionType.GetImmutableDictionaryCreateRangeMethod(typeof(TElement)); + MethodInfo realMethod = collectionType.GetImmutableDictionaryCreateRangeMethod(elementType); var dynamicMethod = new DynamicMethod( realMethod.Name, collectionType, - new[] { typeof(IEnumerable>) }, + new[] { enumerableType }, typeof(ReflectionEmitMemberAccessor).Module, skipVisibility: true); @@ -220,13 +217,13 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor generator.Emit(OpCodes.Call, realMethod); generator.Emit(OpCodes.Ret); - return (Func>, TCollection>)dynamicMethod.CreateDelegate(typeof(Func>, TCollection>)); + return dynamicMethod; } public override Func CreatePropertyGetter(PropertyInfo propertyInfo) => - (Func)CreatePropertyGetter(propertyInfo, propertyInfo.DeclaringType!, typeof(TProperty)); + CreateDelegate>(CreatePropertyGetter(propertyInfo, propertyInfo.DeclaringType!, typeof(TProperty))); - private static Delegate CreatePropertyGetter(PropertyInfo propertyInfo, Type classType, Type propertyType) + private static DynamicMethod CreatePropertyGetter(PropertyInfo propertyInfo, Type classType, Type propertyType) { MethodInfo? realMethod = propertyInfo.GetMethod; Type objectType = typeof(object); @@ -256,13 +253,13 @@ private static Delegate CreatePropertyGetter(PropertyInfo propertyInfo, Type cla generator.Emit(OpCodes.Ret); - return dynamicMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(objectType, propertyType)); + return dynamicMethod; } public override Action CreatePropertySetter(PropertyInfo propertyInfo) => - (Action)CreatePropertySetter(propertyInfo, propertyInfo.DeclaringType!, typeof(TProperty)); + CreateDelegate>(CreatePropertySetter(propertyInfo, propertyInfo.DeclaringType!, typeof(TProperty))); - private static Delegate CreatePropertySetter(PropertyInfo propertyInfo, Type classType, Type propertyType) + private static DynamicMethod CreatePropertySetter(PropertyInfo propertyInfo, Type classType, Type propertyType) { MethodInfo? realMethod = propertyInfo.SetMethod; Type objectType = typeof(object); @@ -294,8 +291,12 @@ private static Delegate CreatePropertySetter(PropertyInfo propertyInfo, Type cla generator.Emit(OpCodes.Ret); - return dynamicMethod.CreateDelegate(typeof(Action<,>).MakeGenericType(objectType, propertyType)); + return dynamicMethod; } + + [return: NotNullIfNotNull("method")] + private static T? CreateDelegate(DynamicMethod? method) where T : Delegate => + (T?)method?.CreateDelegate(typeof(T)); } } #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index 8d0bb4d01b403..0d7bd68400ee4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -163,9 +163,9 @@ public static void ThrowInvalidOperationException_SerializerPropertyNameNull(Typ [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowInvalidOperationException_SerializerDictionaryKeyNull(Type policyType) + public static void ThrowInvalidOperationException_NamingPolicyReturnNull(JsonNamingPolicy namingPolicy) { - throw new InvalidOperationException(SR.Format(SR.SerializerDictionaryKeyNull, policyType)); + throw new InvalidOperationException(SR.Format(SR.NamingPolicyReturnNull, namingPolicy)); } [DoesNotReturn] diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index 9ba41e024b4b3..16c00a80f8f21 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -78,13 +78,7 @@ public sealed partial class Utf8JsonWriter : IDisposable, IAsyncDisposable /// the which indicates whether to format the output /// while writing and whether to skip structural JSON validation or not. /// - public JsonWriterOptions Options - { - get - { - return _options; - } - } + public JsonWriterOptions Options => _options; private int Indentation => CurrentDepth * JsonConstants.SpacesPerIndent; @@ -107,21 +101,7 @@ public JsonWriterOptions Options public Utf8JsonWriter(IBufferWriter bufferWriter, JsonWriterOptions options = default) { _output = bufferWriter ?? throw new ArgumentNullException(nameof(bufferWriter)); - _stream = default; - _arrayBufferWriter = default; - - BytesPending = default; - BytesCommitted = default; - _memory = default; - - _inObject = default; - _tokenType = default; - _currentDepth = default; _options = options; - - // Only allocate if the user writes a JSON payload beyond the depth that the _allocationFreeContainer can handle. - // This way we avoid allocations in the common, default cases, and allocate lazily. - _bitStack = default; } /// @@ -142,21 +122,8 @@ public Utf8JsonWriter(Stream utf8Json, JsonWriterOptions options = default) throw new ArgumentException(SR.StreamNotWritable); _stream = utf8Json; - _arrayBufferWriter = new ArrayBufferWriter(); - _output = default; - - BytesPending = default; - BytesCommitted = default; - _memory = default; - - _inObject = default; - _tokenType = default; - _currentDepth = default; _options = options; - - // Only allocate if the user writes a JSON payload beyond the depth that the _allocationFreeContainer can handle. - // This way we avoid allocations in the common, default cases, and allocate lazily. - _bitStack = default; + _arrayBufferWriter = new ArrayBufferWriter(); } /// @@ -249,8 +216,6 @@ private void ResetHelper() _tokenType = default; _currentDepth = default; - // Only allocate if the user writes a JSON payload beyond the depth that the _allocationFreeContainer can handle. - // This way we avoid allocations in the common, default cases, and allocate lazily. _bitStack = default; } diff --git a/src/libraries/System.Text.Json/tests/JsonDateTimeTestData.cs b/src/libraries/System.Text.Json/tests/JsonDateTimeTestData.cs index 7ff20c7e1c125..d172726159a2d 100644 --- a/src/libraries/System.Text.Json/tests/JsonDateTimeTestData.cs +++ b/src/libraries/System.Text.Json/tests/JsonDateTimeTestData.cs @@ -42,7 +42,6 @@ public static IEnumerable ValidISO8601Tests() yield return new object[] { "\"1997-07-16T19:20:30.6666660\"", "1997-07-16T19:20:30.666666" }; // Test fraction truncation. - yield return new object[] { "\"1997-07-16T19:20:30.0000000\"", "1997-07-16T19:20:30" }; yield return new object[] { "\"1997-07-16T19:20:30.00000001\"", "1997-07-16T19:20:30" }; yield return new object[] { "\"1997-07-16T19:20:30.000000001\"", "1997-07-16T19:20:30" }; yield return new object[] { "\"1997-07-16T19:20:30.77777770\"", "1997-07-16T19:20:30.7777777" }; @@ -153,7 +152,6 @@ public static IEnumerable InvalidISO8601Tests() // Invalid fractions. yield return new object[] { "\"1997-07-16T19.45\"" }; yield return new object[] { "\"1997-07-16T19:20.45\"" }; - yield return new object[] { "\"1997-07-16T19:20:30a\"" }; yield return new object[] { "\"1997-07-16T19:20:30,45\"" }; yield return new object[] { "\"1997-07-16T19:20:30.\"" }; yield return new object[] { "\"1997-07-16T19:20:30.a\"" }; @@ -168,7 +166,6 @@ public static IEnumerable InvalidISO8601Tests() yield return new object[] { "\"1997-07-16T19:20:30.4555555+01Z\"" }; yield return new object[] { "\"1997-07-16T19:20:30.4555555+01:\"" }; yield return new object[] { "\"1997-07-16T19:20:30.4555555 +01:00\"" }; - yield return new object[] { "\"1997-07-16T19:20:30.4555555+01:\"" }; yield return new object[] { "\"1997-07-16T19:20:30.4555555- 01:00\"" }; yield return new object[] { "\"1997-07-16T19:20:30.4555555+04 :30\"" }; yield return new object[] { "\"1997-07-16T19:20:30.4555555-04: 30\"" }; diff --git a/src/libraries/System.Text.Json/tests/JsonGuidTestData.cs b/src/libraries/System.Text.Json/tests/JsonGuidTestData.cs index 26fd675487085..bb74e59511b34 100644 --- a/src/libraries/System.Text.Json/tests/JsonGuidTestData.cs +++ b/src/libraries/System.Text.Json/tests/JsonGuidTestData.cs @@ -35,16 +35,40 @@ public static IEnumerable ValidHexGuidTests() public static IEnumerable InvalidGuidTests() { + // Invalid formats + Guid testGuid = new Guid(s_guidStr); + yield return new object[] { testGuid.ToString("B", CultureInfo.InvariantCulture) }; + yield return new object[] { testGuid.ToString("P", CultureInfo.InvariantCulture) }; + yield return new object[] { testGuid.ToString("N", CultureInfo.InvariantCulture) }; + + yield return new object[] { new string('$', 1) }; + yield return new object[] { new string(' ', 1) }; + yield return new object[] { new string('$', s_guidStr.Length) }; + yield return new object[] { new string(' ', s_guidStr.Length) }; + + for (int truncationPoint = 1; truncationPoint < s_guidStr.Length - 1; truncationPoint++) + { + string truncatedText = s_guidStr.Substring(0, truncationPoint); + + // Stop short + yield return new object[] { truncatedText }; + + // Append junk + yield return new object[] { truncatedText.PadRight(s_guidStr.Length, '$') }; + yield return new object[] { truncatedText.PadRight(s_guidStr.Length, ' ') }; + yield return new object[] { truncatedText.PadRight(truncatedText.Length + 1, '$') }; + yield return new object[] { truncatedText.PadRight(truncatedText.Length + 1, ' ') }; + // Prepend junk + yield return new object[] { truncatedText.PadLeft(s_guidStr.Length, '$') }; + yield return new object[] { truncatedText.PadLeft(s_guidStr.Length, ' ') }; + yield return new object[] { truncatedText.PadLeft(truncatedText.Length + 1, '$') }; + yield return new object[] { truncatedText.PadLeft(truncatedText.Length + 1, ' ') }; + } + foreach (object[] guid in ValidGuidTests()) { string guidStr = (string)guid[0]; - // Invalid formats - Guid testGuid = new Guid(guidStr); - yield return new object[] { testGuid.ToString("B", CultureInfo.InvariantCulture) }; - yield return new object[] { testGuid.ToString("P", CultureInfo.InvariantCulture) }; - yield return new object[] { testGuid.ToString("N", CultureInfo.InvariantCulture) }; - for (int i = 0; i < guidStr.Length; i++) { // Corrupt one character @@ -72,25 +96,6 @@ public static IEnumerable InvalidGuidTests() } } - for (int truncationPoint = 0; truncationPoint < guidStr.Length; truncationPoint++) - { - string truncatedText = guidStr.Substring(0, truncationPoint); - - // Stop short - yield return new object[] { truncatedText }; - - // Append junk - yield return new object[] { truncatedText.PadRight(guidStr.Length, '$') }; - yield return new object[] { truncatedText.PadRight(guidStr.Length, ' ') }; - yield return new object[] { truncatedText.PadRight(truncatedText.Length + 1, '$') }; - yield return new object[] { truncatedText.PadRight(truncatedText.Length + 1, ' ') }; - // Prepend junk - yield return new object[] { truncatedText.PadLeft(guidStr.Length, '$') }; - yield return new object[] { truncatedText.PadLeft(guidStr.Length, ' ') }; - yield return new object[] { truncatedText.PadLeft(truncatedText.Length + 1, '$') }; - yield return new object[] { truncatedText.PadLeft(truncatedText.Length + 1, ' ') }; - } - // Too long yield return new object[] { $"{guidStr} " }; yield return new object[] { $"{guidStr}$" }; diff --git a/src/libraries/System.Text.Json/tests/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/JsonTestHelper.cs index b83fcbe3f1a92..1f31adc4915ea 100644 --- a/src/libraries/System.Text.Json/tests/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/JsonTestHelper.cs @@ -867,8 +867,15 @@ private static void AssertJsonEqual(JsonElement expected, JsonElement actual) case JsonValueKind.String: Assert.Equal(expected.GetString(), actual.GetString()); break; + case JsonValueKind.Number: + case JsonValueKind.True: + case JsonValueKind.False: + case JsonValueKind.Null: + Assert.Equal(expected.GetRawText(), actual.GetRawText()); + break; default: - throw new NotImplementedException(); + Debug.Fail($"Unexpected JsonValueKind: JsonValueKind.{valueKind}."); + break; } } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Read.cs b/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Read.cs index 2d72329f49480..3e9eae828e837 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Read.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Read.cs @@ -962,159 +962,6 @@ public static void ReadSimpleSortedSetT() Assert.Equal(0, result.Count()); } - [Fact] - public static void ReadSimpleKeyValuePairFail() - { - // Invalid form: no Value - Assert.Throws(() => JsonSerializer.Deserialize>(@"{""Key"": 123}")); - - // Invalid form: extra property - Assert.Throws(() => JsonSerializer.Deserialize>(@"{""Key"": ""Key"", ""Value"": 123, ""Value2"": 456}")); - - // Invalid form: does not contain both Key and Value properties - Assert.Throws(() => JsonSerializer.Deserialize>(@"{""Key"": ""Key"", ""Val"": 123")); - } - - [Fact] - public static void ReadListOfKeyValuePair() - { - List> input = JsonSerializer.Deserialize>>(@"[{""Key"": ""123"", ""Value"": 123},{""Key"": ""456"", ""Value"": 456}]"); - - Assert.Equal(2, input.Count); - Assert.Equal("123", input[0].Key); - Assert.Equal(123, input[0].Value); - Assert.Equal("456", input[1].Key); - Assert.Equal(456, input[1].Value); - } - - [Fact] - public static void ReadKeyValuePairOfList() - { - KeyValuePair> input = JsonSerializer.Deserialize>>(@"{""Key"":""Key"", ""Value"":[1, 2, 3]}"); - - Assert.Equal("Key", input.Key); - Assert.Equal(3, input.Value.Count); - Assert.Equal(1, input.Value[0]); - Assert.Equal(2, input.Value[1]); - Assert.Equal(3, input.Value[2]); - } - - [Theory] - [InlineData(@"{""Key"":""Key"", ""Value"":{""Key"":1, ""Value"":2}}")] - [InlineData(@"{""Key"":""Key"", ""Value"":{""Value"":2, ""Key"":1}}")] - [InlineData(@"{""Value"":{""Key"":1, ""Value"":2}, ""Key"":""Key""}")] - [InlineData(@"{""Value"":{""Value"":2, ""Key"":1}, ""Key"":""Key""}")] - public static void ReadKeyValuePairOfKeyValuePair(string json) - { - KeyValuePair> input = JsonSerializer.Deserialize>>(json); - - Assert.Equal("Key", input.Key); - Assert.Equal(1, input.Value.Key); - Assert.Equal(2, input.Value.Value); - } - - [Fact] - public static void ReadKeyValuePairWithNullValues() - { - { - KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":""key"",""Value"":null}"); - Assert.Equal("key", kvp.Key); - Assert.Null(kvp.Value); - } - - { - KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":""key"",""Value"":null}"); - Assert.Equal("key", kvp.Key); - Assert.Null(kvp.Value); - } - - { - KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":""key"",""Value"":null}"); - Assert.Equal("key", kvp.Key); - Assert.Null(kvp.Value); - } - - { - KeyValuePair> kvp = JsonSerializer.Deserialize>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}"); - Assert.Equal("key", kvp.Key); - Assert.Equal("key", kvp.Value.Key); - Assert.Null(kvp.Value.Value); - } - - { - KeyValuePair> kvp = JsonSerializer.Deserialize>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}"); - Assert.Equal("key", kvp.Key); - Assert.Equal("key", kvp.Value.Key); - Assert.Null(kvp.Value.Value); - } - - { - KeyValuePair> kvp = JsonSerializer.Deserialize>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}"); - Assert.Equal("key", kvp.Key); - Assert.Equal("key", kvp.Value.Key); - Assert.Null(kvp.Value.Value); - } - } - - [Fact] - public static void ReadClassWithNullKeyValuePairValues() - { - string json = - @"{" + - @"""KvpWStrVal"":{" + - @"""Key"":""key""," + - @"""Value"":null" + - @"}," + - @"""KvpWObjVal"":{" + - @"""Key"":""key""," + - @"""Value"":null" + - @"}," + - @"""KvpWClassVal"":{" + - @"""Key"":""key""," + - @"""Value"":null" + - @"}," + - @"""KvpWStrKvpVal"":{" + - @"""Key"":""key""," + - @"""Value"":{" + - @"""Key"":""key""," + - @"""Value"":null" + - @"}" + - @"}," + - @"""KvpWObjKvpVal"":{" + - @"""Key"":""key""," + - @"""Value"":{" + - @"""Key"":""key""," + - @"""Value"":null" + - @"}" + - @"}," + - @"""KvpWClassKvpVal"":{" + - @"""Key"":""key""," + - @"""Value"":{" + - @"""Key"":""key""," + - @"""Value"":null" + - @"}" + - @"}" + - @"}"; - SimpleClassWithKeyValuePairs obj = JsonSerializer.Deserialize(json); - - Assert.Equal("key", obj.KvpWStrVal.Key); - Assert.Equal("key", obj.KvpWObjVal.Key); - Assert.Equal("key", obj.KvpWClassVal.Key); - Assert.Equal("key", obj.KvpWStrKvpVal.Key); - Assert.Equal("key", obj.KvpWObjKvpVal.Key); - Assert.Equal("key", obj.KvpWClassKvpVal.Key); - Assert.Equal("key", obj.KvpWStrKvpVal.Value.Key); - Assert.Equal("key", obj.KvpWObjKvpVal.Value.Key); - Assert.Equal("key", obj.KvpWClassKvpVal.Value.Key); - - Assert.Null(obj.KvpWStrVal.Value); - Assert.Null(obj.KvpWObjVal.Value); - Assert.Null(obj.KvpWClassVal.Value); - Assert.Null(obj.KvpWStrKvpVal.Value.Value); - Assert.Null(obj.KvpWObjKvpVal.Value.Value); - Assert.Null(obj.KvpWClassKvpVal.Value.Value); - } - [Fact] public static void ReadSimpleTestClass_GenericCollectionWrappers() { diff --git a/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Write.cs b/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Write.cs index e408f09b0e7fd..2c2c61819d1ac 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Write.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.Generic.Write.cs @@ -750,117 +750,6 @@ public static void WritePrimitiveSortedSetT() Assert.Equal("[1,2]", json); } - [Fact] - public static void WritePrimitiveKeyValuePair() - { - KeyValuePair input = new KeyValuePair("Key", 123) ; - - string json = JsonSerializer.Serialize(input); - Assert.Equal(@"{""Key"":""Key"",""Value"":123}", json); - } - - [Fact] - public static void WriteListOfKeyValuePair() - { - List> input = new List> - { - new KeyValuePair("123", 123), - new KeyValuePair("456", 456) - }; - - string json = JsonSerializer.Serialize(input); - Assert.Equal(@"[{""Key"":""123"",""Value"":123},{""Key"":""456"",""Value"":456}]", json); - } - - [Fact] - public static void WriteKeyValuePairOfList() - { - KeyValuePair> input = new KeyValuePair>("Key", new List { 1, 2, 3 }); - - string json = JsonSerializer.Serialize(input); - Assert.Equal(@"{""Key"":""Key"",""Value"":[1,2,3]}", json); - } - - [Fact] - public static void WriteKeyValuePairOfKeyValuePair() - { - KeyValuePair> input = new KeyValuePair>( - "Key", new KeyValuePair("Key", 1)); - - string json = JsonSerializer.Serialize(input); - Assert.Equal(@"{""Key"":""Key"",""Value"":{""Key"":""Key"",""Value"":1}}", json); - } - - [Fact] - public static void WriteKeyValuePairWithNullValues() - { - { - KeyValuePair kvp = new KeyValuePair("key", null); - Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp)); - } - - { - KeyValuePair kvp = new KeyValuePair("key", null); - Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp)); - } - - { - KeyValuePair kvp = new KeyValuePair("key", null); - Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp)); - } - - { - KeyValuePair> kvp = new KeyValuePair>("key", new KeyValuePair("key", null)); - Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp)); - } - - { - KeyValuePair> kvp = new KeyValuePair>("key", new KeyValuePair("key", null)); - Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp)); - } - - { - KeyValuePair> kvp = new KeyValuePair>("key", new KeyValuePair("key", null)); - Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp)); - } - } - - // https://github.com/dotnet/runtime/issues/30388 - [Fact] - public static void WriteClassWithNullKeyValuePairValues_NullWrittenAsEmptyObject() - { - var value = new SimpleClassWithKeyValuePairs() - { - KvpWStrVal = new KeyValuePair("key", null), - KvpWObjVal = new KeyValuePair("key", null), - KvpWClassVal = new KeyValuePair("key", null), - KvpWStrKvpVal = new KeyValuePair>("key", new KeyValuePair("key", null)), - KvpWObjKvpVal = new KeyValuePair>("key", new KeyValuePair("key", null)), - KvpWClassKvpVal = new KeyValuePair>("key", new KeyValuePair("key", null)), - }; - - string result = JsonSerializer.Serialize(value); - - // Roundtrip to ensure serialize was correct. - value = JsonSerializer.Deserialize(result); - Assert.Equal("key", value.KvpWStrVal.Key); - Assert.Equal("key", value.KvpWObjVal.Key); - Assert.Equal("key", value.KvpWClassVal.Key); - Assert.Equal("key", value.KvpWStrKvpVal.Key); - Assert.Equal("key", value.KvpWObjKvpVal.Key); - Assert.Equal("key", value.KvpWClassKvpVal.Key); - Assert.Equal("key", value.KvpWStrKvpVal.Value.Key); - Assert.Equal("key", value.KvpWObjKvpVal.Value.Key); - Assert.Equal("key", value.KvpWClassKvpVal.Value.Key); - - Assert.Null(value.KvpWStrVal.Value); - Assert.Null(value.KvpWObjVal.Value); - Assert.Null(value.KvpWClassVal.Value); - Assert.Null(value.KvpWStrKvpVal.Value.Value); - Assert.Null(value.KvpWObjKvpVal.Value.Value); - Assert.Null(value.KvpWClassKvpVal.Value.Value); - } - [Fact] public static void WriteGenericCollectionWrappers() { diff --git a/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.KeyValuePair.cs b/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.KeyValuePair.cs new file mode 100644 index 0000000000000..868167086cfa9 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/Serialization/CollectionTests/CollectionTests.KeyValuePair.cs @@ -0,0 +1,438 @@ +// 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.Collections.Generic; +using System.Text.Encodings.Web; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public static partial class CollectionTests + { + [Fact] + public static void ReadSimpleKeyValuePairFail() + { + // Invalid form: no Value + Assert.Throws(() => JsonSerializer.Deserialize>(@"{""Key"": 123}")); + + // Invalid form: extra property + Assert.Throws(() => JsonSerializer.Deserialize>(@"{""Key"": ""Key"", ""Value"": 123, ""Value2"": 456}")); + + // Invalid form: does not contain both Key and Value properties + Assert.Throws(() => JsonSerializer.Deserialize>(@"{""Key"": ""Key"", ""Val"": 123")); + } + + [Fact] + public static void ReadListOfKeyValuePair() + { + List> input = JsonSerializer.Deserialize>>(@"[{""Key"": ""123"", ""Value"": 123},{""Key"": ""456"", ""Value"": 456}]"); + + Assert.Equal(2, input.Count); + Assert.Equal("123", input[0].Key); + Assert.Equal(123, input[0].Value); + Assert.Equal("456", input[1].Key); + Assert.Equal(456, input[1].Value); + } + + [Fact] + public static void ReadKeyValuePairOfList() + { + KeyValuePair> input = JsonSerializer.Deserialize>>(@"{""Key"":""Key"", ""Value"":[1, 2, 3]}"); + + Assert.Equal("Key", input.Key); + Assert.Equal(3, input.Value.Count); + Assert.Equal(1, input.Value[0]); + Assert.Equal(2, input.Value[1]); + Assert.Equal(3, input.Value[2]); + } + + [Theory] + [InlineData(@"{""Key"":""Key"", ""Value"":{""Key"":1, ""Value"":2}}")] + [InlineData(@"{""Key"":""Key"", ""Value"":{""Value"":2, ""Key"":1}}")] + [InlineData(@"{""Value"":{""Key"":1, ""Value"":2}, ""Key"":""Key""}")] + [InlineData(@"{""Value"":{""Value"":2, ""Key"":1}, ""Key"":""Key""}")] + public static void ReadKeyValuePairOfKeyValuePair(string json) + { + KeyValuePair> input = JsonSerializer.Deserialize>>(json); + + Assert.Equal("Key", input.Key); + Assert.Equal(1, input.Value.Key); + Assert.Equal(2, input.Value.Value); + } + + [Fact] + public static void ReadKeyValuePairWithNullValues() + { + { + KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":""key"",""Value"":null}"); + Assert.Equal("key", kvp.Key); + Assert.Null(kvp.Value); + } + + { + KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":""key"",""Value"":null}"); + Assert.Equal("key", kvp.Key); + Assert.Null(kvp.Value); + } + + { + KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":""key"",""Value"":null}"); + Assert.Equal("key", kvp.Key); + Assert.Null(kvp.Value); + } + + { + KeyValuePair> kvp = JsonSerializer.Deserialize>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}"); + Assert.Equal("key", kvp.Key); + Assert.Equal("key", kvp.Value.Key); + Assert.Null(kvp.Value.Value); + } + + { + KeyValuePair> kvp = JsonSerializer.Deserialize>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}"); + Assert.Equal("key", kvp.Key); + Assert.Equal("key", kvp.Value.Key); + Assert.Null(kvp.Value.Value); + } + + { + KeyValuePair> kvp = JsonSerializer.Deserialize>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}"); + Assert.Equal("key", kvp.Key); + Assert.Equal("key", kvp.Value.Key); + Assert.Null(kvp.Value.Value); + } + } + + [Fact] + public static void ReadClassWithNullKeyValuePairValues() + { + string json = + @"{" + + @"""KvpWStrVal"":{" + + @"""Key"":""key""," + + @"""Value"":null" + + @"}," + + @"""KvpWObjVal"":{" + + @"""Key"":""key""," + + @"""Value"":null" + + @"}," + + @"""KvpWClassVal"":{" + + @"""Key"":""key""," + + @"""Value"":null" + + @"}," + + @"""KvpWStrKvpVal"":{" + + @"""Key"":""key""," + + @"""Value"":{" + + @"""Key"":""key""," + + @"""Value"":null" + + @"}" + + @"}," + + @"""KvpWObjKvpVal"":{" + + @"""Key"":""key""," + + @"""Value"":{" + + @"""Key"":""key""," + + @"""Value"":null" + + @"}" + + @"}," + + @"""KvpWClassKvpVal"":{" + + @"""Key"":""key""," + + @"""Value"":{" + + @"""Key"":""key""," + + @"""Value"":null" + + @"}" + + @"}" + + @"}"; + SimpleClassWithKeyValuePairs obj = JsonSerializer.Deserialize(json); + + Assert.Equal("key", obj.KvpWStrVal.Key); + Assert.Equal("key", obj.KvpWObjVal.Key); + Assert.Equal("key", obj.KvpWClassVal.Key); + Assert.Equal("key", obj.KvpWStrKvpVal.Key); + Assert.Equal("key", obj.KvpWObjKvpVal.Key); + Assert.Equal("key", obj.KvpWClassKvpVal.Key); + Assert.Equal("key", obj.KvpWStrKvpVal.Value.Key); + Assert.Equal("key", obj.KvpWObjKvpVal.Value.Key); + Assert.Equal("key", obj.KvpWClassKvpVal.Value.Key); + + Assert.Null(obj.KvpWStrVal.Value); + Assert.Null(obj.KvpWObjVal.Value); + Assert.Null(obj.KvpWClassVal.Value); + Assert.Null(obj.KvpWStrKvpVal.Value.Value); + Assert.Null(obj.KvpWObjKvpVal.Value.Value); + Assert.Null(obj.KvpWClassKvpVal.Value.Value); + } + + [Fact] + public static void Kvp_NullKeyIsFine() + { + KeyValuePair kvp = JsonSerializer.Deserialize>(@"{""Key"":null,""Value"":null}"); + Assert.Null(kvp.Key); + Assert.Null(kvp.Value); + } + + [Fact] + public static void WritePrimitiveKeyValuePair() + { + KeyValuePair input = new KeyValuePair("Key", 123); + + string json = JsonSerializer.Serialize(input); + Assert.Equal(@"{""Key"":""Key"",""Value"":123}", json); + } + + [Fact] + public static void WriteListOfKeyValuePair() + { + List> input = new List> + { + new KeyValuePair("123", 123), + new KeyValuePair("456", 456) + }; + + string json = JsonSerializer.Serialize(input); + Assert.Equal(@"[{""Key"":""123"",""Value"":123},{""Key"":""456"",""Value"":456}]", json); + } + + [Fact] + public static void WriteKeyValuePairOfList() + { + KeyValuePair> input = new KeyValuePair>("Key", new List { 1, 2, 3 }); + + string json = JsonSerializer.Serialize(input); + Assert.Equal(@"{""Key"":""Key"",""Value"":[1,2,3]}", json); + } + + [Fact] + public static void WriteKeyValuePairOfKeyValuePair() + { + KeyValuePair> input = new KeyValuePair>( + "Key", new KeyValuePair("Key", 1)); + + string json = JsonSerializer.Serialize(input); + Assert.Equal(@"{""Key"":""Key"",""Value"":{""Key"":""Key"",""Value"":1}}", json); + } + + [Fact] + public static void WriteKeyValuePairWithNullValues() + { + { + KeyValuePair kvp = new KeyValuePair("key", null); + Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp)); + } + + { + KeyValuePair kvp = new KeyValuePair("key", null); + Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp)); + } + + { + KeyValuePair kvp = new KeyValuePair("key", null); + Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp)); + } + + { + KeyValuePair> kvp = new KeyValuePair>("key", new KeyValuePair("key", null)); + Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp)); + } + + { + KeyValuePair> kvp = new KeyValuePair>("key", new KeyValuePair("key", null)); + Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp)); + } + + { + KeyValuePair> kvp = new KeyValuePair>("key", new KeyValuePair("key", null)); + Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp)); + } + } + + [Fact] + public static void WriteClassWithNullKeyValuePairValues_NullWrittenAsEmptyObject() + { + var value = new SimpleClassWithKeyValuePairs() + { + KvpWStrVal = new KeyValuePair("key", null), + KvpWObjVal = new KeyValuePair("key", null), + KvpWClassVal = new KeyValuePair("key", null), + KvpWStrKvpVal = new KeyValuePair>("key", new KeyValuePair("key", null)), + KvpWObjKvpVal = new KeyValuePair>("key", new KeyValuePair("key", null)), + KvpWClassKvpVal = new KeyValuePair>("key", new KeyValuePair("key", null)), + }; + + string result = JsonSerializer.Serialize(value); + + // Roundtrip to ensure serialize was correct. + value = JsonSerializer.Deserialize(result); + Assert.Equal("key", value.KvpWStrVal.Key); + Assert.Equal("key", value.KvpWObjVal.Key); + Assert.Equal("key", value.KvpWClassVal.Key); + Assert.Equal("key", value.KvpWStrKvpVal.Key); + Assert.Equal("key", value.KvpWObjKvpVal.Key); + Assert.Equal("key", value.KvpWClassKvpVal.Key); + Assert.Equal("key", value.KvpWStrKvpVal.Value.Key); + Assert.Equal("key", value.KvpWObjKvpVal.Value.Key); + Assert.Equal("key", value.KvpWClassKvpVal.Value.Key); + + Assert.Null(value.KvpWStrVal.Value); + Assert.Null(value.KvpWObjVal.Value); + Assert.Null(value.KvpWClassVal.Value); + Assert.Null(value.KvpWStrKvpVal.Value.Value); + Assert.Null(value.KvpWObjKvpVal.Value.Value); + Assert.Null(value.KvpWClassKvpVal.Value.Value); + } + + [Fact] + public static void HonorNamingPolicy() + { + var kvp = new KeyValuePair("Hello, World!", 1); + + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = new LeadingUnderscorePolicy() + }; + + string serialized = JsonSerializer.Serialize(kvp, options); + // We know serializer writes the key first. + Assert.Equal(@"{""_Key"":""Hello, World!"",""_Value"":1}", serialized); + + kvp = JsonSerializer.Deserialize>(serialized, options); + Assert.Equal("Hello, World!", kvp.Key); + Assert.Equal(1, kvp.Value); + } + + [Fact] + public static void HonorNamingPolicy_CaseInsensitive() + { + const string json = @"{""key"":""Hello, World!"",""value"":1}"; + + // Baseline - with case-sensitive matching, the payload doesn't have mapping properties. + Assert.Throws(() => JsonSerializer.Deserialize>(json)); + + // Test - with case-insensitivity on, we have property matches. + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + KeyValuePair kvp = JsonSerializer.Deserialize>(json, options); + Assert.Equal("Hello, World!", kvp.Key); + Assert.Equal(1, kvp.Value); + } + + [Fact] + public static void HonorCLRProperties() + { + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = new LeadingUnderscorePolicy() // Key -> _Key, Value -> _Value + }; + + // Although policy won't produce this JSON string, the serializer parses the properties + // as "Key" and "Value" are special cased to accomodate content serialized with previous + // versions of the serializer (.NET Core 3.x/System.Text.Json 4.7.x). + string json = @"{""Key"":""Hello, World!"",""Value"":1}"; + KeyValuePair kvp = JsonSerializer.Deserialize>(json, options); + Assert.Equal("Hello, World!", kvp.Key); + Assert.Equal(1, kvp.Value); + + // "Key" and "Value" matching is case sensitive. + json = @"{""key"":""Hello, World!"",""value"":1}"; + Assert.Throws(() => JsonSerializer.Deserialize>(json, options)); + + // "Key" and "Value" matching is case sensitive, even when case sensitivity is on. + // Case sensitivity only applies to the result of converting the CLR property names + // (Key -> _Key, Value -> _Value) with the naming policy. + options = new JsonSerializerOptions + { + PropertyNamingPolicy = new LeadingUnderscorePolicy(), + PropertyNameCaseInsensitive = true + }; + + Assert.Throws(() => JsonSerializer.Deserialize>(json, options)); + } + + private class LeadingUnderscorePolicy : JsonNamingPolicy + { + public override string ConvertName(string name) => "_" + name; + } + + [Fact] + public static void HonorCustomEncoder() + { + var kvp = new KeyValuePair(1, 2); + + JsonNamingPolicy namingPolicy = new TrailingAngleBracketPolicy(); + + // Baseline - properties serialized with default encoder if none specified. + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = namingPolicy, + }; + + Assert.Equal(@"{""Key\u003C"":1,""Value\u003C"":2}", JsonSerializer.Serialize(kvp, options)); + + // Test - serializer honors custom encoder. + options = new JsonSerializerOptions + { + PropertyNamingPolicy = namingPolicy, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + + Assert.Equal(@"{""Key<"":1,""Value<"":2}", JsonSerializer.Serialize(kvp, options)); + } + + private class TrailingAngleBracketPolicy : JsonNamingPolicy + { + public override string ConvertName(string name) => name + "<"; + } + + [Theory] + [InlineData(typeof(KeyNameNullPolicy))] + [InlineData(typeof(ValueNameNullPolicy))] + public static void InvalidPropertyNameFail(Type policyType) + { + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = (JsonNamingPolicy)Activator.CreateInstance(policyType) + }; + + InvalidOperationException ex = Assert.Throws(() => JsonSerializer.Deserialize>("", options)); + string exAsStr = ex.ToString(); + Assert.Contains(policyType.ToString(), exAsStr); + + Assert.Throws(() => JsonSerializer.Serialize(new KeyValuePair("", ""), options)); + } + + private class KeyNameNullPolicy : JsonNamingPolicy + { + public override string ConvertName(string name) => name == "Key" ? null : name; + } + + private class ValueNameNullPolicy : JsonNamingPolicy + { + public override string ConvertName(string name) => name == "Value" ? null : name; + } + + [Theory] + [InlineData("")] + [InlineData("1")] + [InlineData("[")] + [InlineData("}")] + [InlineData("{")] + [InlineData("{}")] + [InlineData("{Key")] + [InlineData("{0")] + [InlineData(@"{""Random"":")] + [InlineData(@"{""Value"":1}")] + [InlineData(@"{""Value"":1,2")] + [InlineData(@"{""Value"":1,""Random"":")] + [InlineData(@"{""Key"":1,""Key"":1}")] + [InlineData(@"{""Key"":1,""Key"":2}")] + [InlineData(@"{""Value"":1,""Value"":1}")] + [InlineData(@"{""Value"":1,""Value"":2}")] + public static void InvalidJsonFail(string json) + { + Assert.Throws(() => JsonSerializer.Deserialize>(json)); + } + } +} diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs index f6979cf22c967..a69c9ad6b9a58 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -339,19 +339,35 @@ public void PropertiesNotSet_WhenJSON_MapsToConstructorParameters() [Fact] public void IgnoreNullValues_DontSetNull_ToConstructorArguments_ThatCantBeNull() { - // Throw JsonException when null applied to types that can't be null. + // Throw JsonException when null applied to types that can't be null. Behavior should align with properties deserialized with setters. + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""Int"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""Int"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""ImmutableArray"":null}")); + Assert.Throws(() => Serializer.Deserialize(@"{""ImmutableArray"":null}")); // Throw even when IgnoreNullValues is true for symmetry with property deserialization, // until https://github.com/dotnet/runtime/issues/30795 is addressed. + var options = new JsonSerializerOptions { IgnoreNullValues = true }; Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""Int"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""ImmutableArray"":null}", options)); + Assert.Throws(() => Serializer.Deserialize(@"{""Point3DStruct"":null,""Int"":null,""ImmutableArray"":null}", options)); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests/CustomConverterTests.HandleNull.cs b/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests/CustomConverterTests.HandleNull.cs new file mode 100644 index 0000000000000..fd30dab747521 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests/CustomConverterTests.HandleNull.cs @@ -0,0 +1,546 @@ +// 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.Buffers; +using System.Collections.Generic; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public static partial class CustomConverterTests + { + [Fact] + public static void ValueTypeConverter_NoOverride() + { + // Baseline + Assert.Throws(() => JsonSerializer.Deserialize("null")); + + // Per null handling default value for value types (true), converter handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new Int32NullConverter_SpecialCaseNull()); + + Assert.Equal(-1, JsonSerializer.Deserialize("null", options)); + } + + private class Int32NullConverter_SpecialCaseNull : JsonConverter + { + public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return -1; + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } + + [Fact] + public static void ValueTypeConverter_OptOut() + { + // Per null handling opt-out, serializer handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new Int32NullConverter_OptOut()); + + // Serializer throws JsonException if null is assigned to value that can't be null. + Assert.Throws(() => JsonSerializer.Deserialize("null", options)); + Assert.Throws(() => JsonSerializer.Deserialize(@"{""MyInt"":null}", options)); + Assert.Throws(() => JsonSerializer.Deserialize>("[null]", options)); + Assert.Throws(() => JsonSerializer.Deserialize>(@"{""MyInt"":null}", options)); + } + + private class Int32NullConverter_OptOut : Int32NullConverter_SpecialCaseNull + { + public override bool HandleNull => false; + } + + private class ClassWithInt + { + public int MyInt { get; set; } + } + + [Fact] + public static void ValueTypeConverter_NullOptIn() + { + // Per null handling opt-in, converter handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new Int32NullConverter_NullOptIn()); + + Assert.Equal(-1, JsonSerializer.Deserialize("null", options)); + } + + private class Int32NullConverter_NullOptIn : Int32NullConverter_SpecialCaseNull + { + public override bool HandleNull => true; + } + + [Fact] + public static void ComplexValueTypeConverter_NoOverride() + { + // Baseline + Assert.Throws(() => JsonSerializer.Deserialize("null")); + + var options = new JsonSerializerOptions(); + options.Converters.Add(new PointStructConverter_SpecialCaseNull()); + + // Per null handling default value for value types (true), converter handles null. + var obj = JsonSerializer.Deserialize("null", options); + Assert.Equal(-1, obj.X); + Assert.Equal(-1, obj.Y); + } + + private class PointStructConverter_SpecialCaseNull : JsonConverter + { + public override Point_2D_Struct Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return new Point_2D_Struct(-1, -1); + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, Point_2D_Struct value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } + + [Fact] + public static void ComplexValueTypeConverter_OptOut() + { + // Per null handling opt-out, serializer handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new PointStructConverter_OptOut()); + + // Serializer throws JsonException if null is assigned to value that can't be null. + Assert.Throws(() => JsonSerializer.Deserialize("null", options)); + Assert.Throws(() => JsonSerializer.Deserialize(@"{""MyPoint"":null}", options)); + Assert.Throws(() => JsonSerializer.Deserialize(@"{""MyPoint"":null}", options)); + Assert.Throws(() => JsonSerializer.Deserialize>("[null]", options)); + Assert.Throws(() => JsonSerializer.Deserialize>(@"{""MyPoint"":null}", options)); + } + + private class PointStructConverter_OptOut : PointStructConverter_SpecialCaseNull + { + public override bool HandleNull => false; + } + + private class ClassWithPoint + { + public Point_2D_Struct MyPoint { get; set; } + } + + private class ImmutableClassWithPoint + { + public Point_2D_Struct MyPoint { get; } + + public ImmutableClassWithPoint(Point_2D_Struct myPoint) => MyPoint = myPoint; + } + + [Fact] + public static void ComplexValueTypeConverter_NullOptIn() + { + // Baseline + Assert.Throws(() => JsonSerializer.Deserialize("null")); + + // Per null handling opt-in, converter handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new PointStructConverter_NullOptIn()); + + var obj = JsonSerializer.Deserialize("null", options); + Assert.Equal(-1, obj.X); + Assert.Equal(-1, obj.Y); + } + + private class PointStructConverter_NullOptIn : PointStructConverter_SpecialCaseNull + { + public override bool HandleNull => true; + } + + [Fact] + public static void NullableValueTypeConverter_NoOverride() + { + // Baseline + int? val = JsonSerializer.Deserialize("null"); + Assert.Null(val); + Assert.Equal("null", JsonSerializer.Serialize(val)); + + // Per null handling default value for value types (true), converter handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new NullableInt32NullConverter_SpecialCaseNull()); + + val = JsonSerializer.Deserialize("null", options); + Assert.Equal(-1, val); + + val = null; + Assert.Equal("-1", JsonSerializer.Serialize(val, options)); + } + + private class NullableInt32NullConverter_SpecialCaseNull : JsonConverter + { + public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return -1; + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options) + { + if (!value.HasValue) + { + writer.WriteNumberValue(-1); + return; + } + + throw new NotSupportedException(); + } + } + + [Fact] + public static void NullableValueTypeConverter_OptOut() + { + // Baseline + int? val = JsonSerializer.Deserialize("null"); + Assert.Null(val); + Assert.Equal("null", JsonSerializer.Serialize(val)); + + // Per null handling opt-out, serializer handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new NullableInt32NullConverter_NullOptOut()); + + val = JsonSerializer.Deserialize("null", options); + Assert.Null(val); + Assert.Equal("null", JsonSerializer.Serialize(val, options)); + } + + private class NullableInt32NullConverter_NullOptOut : NullableInt32NullConverter_SpecialCaseNull + { + public override bool HandleNull => false; + } + + [Fact] + public static void ReferenceTypeConverter_NoOverride() + { + // Baseline + Uri val = JsonSerializer.Deserialize("null"); + Assert.Null(val); + Assert.Equal("null", JsonSerializer.Serialize(val)); + + // Per null handling default value for reference types (false), serializer handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new UriNullConverter_SpecialCaseNull()); + + // Serializer sets default value. + val = JsonSerializer.Deserialize("null", options); + Assert.Null(val); + + // Serializer serializes null. + Assert.Equal("null", JsonSerializer.Serialize(val, options)); + } + + private class UriNullConverter_SpecialCaseNull : JsonConverter + { + public override Uri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return new Uri("https://default"); + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, Uri value, JsonSerializerOptions options) + { + if (value == null) + { + writer.WriteStringValue("https://default"); + return; + } + + throw new NotSupportedException(); + } + } + + [Fact] + public static void ReferenceTypeConverter_OptOut() + { + // Per null handling opt-out, serializer handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new UriNullConverter_OptOut()); + + Uri val = JsonSerializer.Deserialize("null", options); + Assert.Null(val); + Assert.Equal("null", JsonSerializer.Serialize(val, options)); + } + + private class UriNullConverter_OptOut : UriNullConverter_SpecialCaseNull + { + public override bool HandleNull => false; + } + + [Fact] + public static void ReferenceTypeConverter_NullOptIn() + { + // Per null handling opt-in, converter handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new UriNullConverter_NullOptIn()); + + Uri val = JsonSerializer.Deserialize("null", options); + Assert.Equal(new Uri("https://default"), val); + + val = null; + Assert.Equal(@"""https://default""", JsonSerializer.Serialize(val, options)); + } + + private class UriNullConverter_NullOptIn : UriNullConverter_SpecialCaseNull + { + public override bool HandleNull => true; + } + + [Fact] + public static void ComplexReferenceTypeConverter_NoOverride() + { + // Baseline + Point_2D obj = JsonSerializer.Deserialize("null"); + Assert.Null(obj); + Assert.Equal("null", JsonSerializer.Serialize(obj)); + + // Per null handling default value for reference types (false), serializer handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new PointClassConverter_SpecialCaseNull()); + + obj = JsonSerializer.Deserialize("null", options); + Assert.Null(obj); + Assert.Equal("null", JsonSerializer.Serialize(obj)); + } + + private class PointClassConverter_SpecialCaseNull : JsonConverter + { + public override Point_2D Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return new Point_2D(-1, -1); + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, Point_2D value, JsonSerializerOptions options) + { + if (value == null) + { + writer.WriteStartObject(); + writer.WriteNumber("X", -1); + writer.WriteNumber("Y", -1); + writer.WriteEndObject(); + return; + } + + throw new JsonException(); + } + } + + [Fact] + public static void ComplexReferenceTypeConverter_NullOptIn() + { + // Per null handling opt-in, converter handles null. + var options = new JsonSerializerOptions(); + options.Converters.Add(new PointClassConverter_NullOptIn()); + + Point_2D obj = JsonSerializer.Deserialize("null", options); + Assert.Equal(-1, obj.X); + Assert.Equal(-1, obj.Y); + + obj = null; + JsonTestHelper.AssertJsonEqual(@"{""X"":-1,""Y"":-1}", JsonSerializer.Serialize(obj, options)); + } + + private class PointClassConverter_NullOptIn : PointClassConverter_SpecialCaseNull + { + public override bool HandleNull => true; + } + + [Fact] + public static void ConverterNotCalled_IgnoreNullValues() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new UriNullConverter_NullOptIn()); + + // Converter is called - JsonIgnoreCondition.WhenWritingDefault does not apply to deserialization. + ClassWithIgnoredUri obj = JsonSerializer.Deserialize(@"{""MyUri"":null}", options); + Assert.Equal(new Uri("https://default"), obj.MyUri); + + obj.MyUri = null; + // Converter is not called - value is ignored on serialization. + Assert.Equal("{}", JsonSerializer.Serialize(obj, options)); + } + + private class ClassWithIgnoredUri + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public Uri MyUri { get; set; } = new Uri("https://microsoft.com"); + } + + [Fact] + public static void ConverterWritesBadAmount() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new BadUriConverter()); + options.Converters.Add(new BadObjectConverter()); + + // Using serializer overload in Release mode uses a writer with SkipValidation = true. + var writerOptions = new JsonWriterOptions { SkipValidation = false }; + using (Utf8JsonWriter writer = new Utf8JsonWriter(new ArrayBufferWriter(), writerOptions)) + { + Assert.Throws(() => JsonSerializer.Serialize(writer, new ClassWithUri(), options)); + } + + using (Utf8JsonWriter writer = new Utf8JsonWriter(new ArrayBufferWriter(), writerOptions)) + { + Assert.Throws(() => JsonSerializer.Serialize(new StructWithObject(), options)); + } + } + + private class BadUriConverter : UriNullConverter_NullOptIn + { + public override void Write(Utf8JsonWriter writer, Uri value, JsonSerializerOptions options) { } + } + + private class BadObjectConverter : JsonConverter + { + public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("hello"); + writer.WriteNullValue(); + } + + public override bool HandleNull => true; + } + + private class ClassWithUri + { + public Uri MyUri { get; set; } + } + + + private class StructWithObject + { + public object MyObj { get; set; } + } + + [Fact] + public static void ObjectAsRootValue() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new ObjectConverter()); + + object obj = null; + Assert.Equal(@"""NullObject""", JsonSerializer.Serialize(obj, options)); + Assert.Equal("NullObject", JsonSerializer.Deserialize("null", options)); + + options = new JsonSerializerOptions(); + options.Converters.Add(new BadObjectConverter()); + Assert.Throws(() => JsonSerializer.Serialize(obj, options)); + } + + [Fact] + public static void ObjectAsCollectionElement() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new ObjectConverter()); + + List list = new List { null }; + Assert.Equal(@"[""NullObject""]", JsonSerializer.Serialize(list, options)); + + list = JsonSerializer.Deserialize>("[null]", options); + Assert.Equal("NullObject", list[0]); + + options = new JsonSerializerOptions(); + options.Converters.Add(new BadObjectConverter()); + + list[0] = null; + Assert.Throws(() => JsonSerializer.Serialize(list, options)); + } + + public class ObjectConverter : JsonConverter + { + public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return "NullObject"; + } + + throw new NotSupportedException(); + } + + public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) + { + if (value == null) + { + writer.WriteStringValue("NullObject"); + return; + } + + throw new NotSupportedException(); + } + + public override bool HandleNull => true; + } + + [Fact] + public static void SetterCalledWhenConverterReturnsNull() + { + var options = new JsonSerializerOptions + { + IgnoreNullValues = true, + Converters = { new UriToNullConverter() } + }; + + // Baseline - null values ignored, converter is not called. + string json = @"{""MyUri"":null}"; + + ClassWithInitializedUri obj = JsonSerializer.Deserialize(json, options); + Assert.Equal(new Uri("https://microsoft.com"), obj.MyUri); + + // Test - setter is called if payload is not null and converter returns null. + json = @"{""MyUri"":""https://default""}"; + obj = JsonSerializer.Deserialize(json, options); + Assert.Null(obj.MyUri); + } + + private class ClassWithInitializedUri + { + public Uri MyUri { get; set; } = new Uri("https://microsoft.com"); + } + + public class UriToNullConverter : JsonConverter + { + public override Uri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => null; + + public override void Write(Utf8JsonWriter writer, Uri value, JsonSerializerOptions options) => throw new NotImplementedException(); + + public override bool HandleNull => true; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/Serialization/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/Serialization/ExtensionDataTests.cs index b0e27027971c8..8c95c471e509e 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ExtensionDataTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ExtensionDataTests.cs @@ -56,7 +56,7 @@ void Verify() } [Fact] - public static void ExtensionPropertyIgnoredWhenNull() + public static void ExtensionPropertyIgnoredWhenWritingDefault() { string expected = @"{}"; string actual = JsonSerializer.Serialize(new ClassWithExtensionPropertyAsObject()); @@ -64,7 +64,7 @@ public static void ExtensionPropertyIgnoredWhenNull() } [Fact] - public static void MultipleExtensionPropertyIgnoredWhenNull() + public static void MultipleExtensionPropertyIgnoredWhenWritingDefault() { var obj = new ClassWithMultipleDictionaries(); string actual = JsonSerializer.Serialize(obj); @@ -99,6 +99,18 @@ public static void MultipleExtensionPropertyIgnoredWhenNull() Assert.Equal("{\"ActualDictionary\":{},\"test\":\"value\"}", actual); } + [Fact] + public static void ExtensionPropertyInvalidJsonFail() + { + const string BadJson = @"{""Good"":""OK"",""Bad"":!}"; + + JsonException jsonException = Assert.Throws(() => JsonSerializer.Deserialize(BadJson)); + Assert.Contains("Path: $.Bad | LineNumber: 0 | BytePositionInLine: 19.", jsonException.ToString()); + Assert.NotNull(jsonException.InnerException); + Assert.IsAssignableFrom(jsonException.InnerException); + Assert.Contains("!", jsonException.InnerException.ToString()); + } + [Fact] public static void ExtensionPropertyAlreadyInstantiated() { diff --git a/src/libraries/System.Text.Json/tests/Serialization/OptionsTests.cs b/src/libraries/System.Text.Json/tests/Serialization/OptionsTests.cs index aedd10bf6b876..c4fe9c48bb757 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/OptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/OptionsTests.cs @@ -340,7 +340,7 @@ private static void GenericObjectOrJsonElementConverterTestHelper(string conv JsonConverter converter = (JsonConverter)options.GetConverter(typeof(T)); Assert.Equal(converterName, converter.GetType().Name); - + ReadOnlySpan data = Encoding.UTF8.GetBytes(stringValue); Utf8JsonReader reader = new Utf8JsonReader(data); reader.Read(); @@ -406,7 +406,6 @@ public static void Options_GetConverter_GivesCorrectDefaultConverterAndReadWrite GenericConverterTestHelper("GuidConverter", testGuid, $"\"{testGuid.ToString()}\"", options); GenericConverterTestHelper>("KeyValuePairConverter`2", new KeyValuePair("key", "value"), @"{""Key"":""key"",""Value"":""value""}", options); GenericConverterTestHelper("UriConverter", new Uri("http://test.com"), "\"http://test.com\"", options); - } [Fact] @@ -452,35 +451,9 @@ private static void GenericConverterTestHelper(string converterName, object o } [Fact] - public static void CopyConstructorTest_OriginalMutable() + public static void CopyConstructor_OriginalLocked() { - JsonSerializerOptions options = CreateOptionsInstance(); - var newOptions = new JsonSerializerOptions(options); - VerifyOptionsEqual(options, newOptions); - - // No exception is thrown on mutating the new options instance because it is "unlocked". - newOptions.ReferenceHandling = ReferenceHandling.Preserve; - newOptions.Converters.Add(new JsonStringEnumConverter()); - newOptions.Converters.Add(new JsonStringEnumConverter()); - - // Changes to new options don't affect old options. - Assert.Equal(ReferenceHandling.Default, options.ReferenceHandling); - Assert.Equal(2, options.Converters.Count); - Assert.Equal(4, newOptions.Converters.Count); - - // Changes to old options don't affect new options. - options.DefaultBufferSize = 2; - options.Converters.Add(new ConverterForInt32()); - - Assert.Equal(20, newOptions.DefaultBufferSize); - Assert.Equal(3, options.Converters.Count); - Assert.Equal(4, newOptions.Converters.Count); - } - - [Fact] - public static void CopyConstructorTest_OriginalLocked() - { - JsonSerializerOptions options = CreateOptionsInstance(); + JsonSerializerOptions options = new JsonSerializerOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; // Perform serialization with options, after which it will be locked. JsonSerializer.Serialize("1", options); @@ -494,7 +467,7 @@ public static void CopyConstructorTest_OriginalLocked() } [Fact] - public static void CopyConstructorTest_MaxDepth() + public static void CopyConstructor_MaxDepth() { static void RunTest(int maxDepth, int effectiveMaxDepth) { @@ -525,20 +498,46 @@ static void RunTest(int maxDepth, int effectiveMaxDepth) } [Fact] - public static void CopyConstructorTest_CopiesAllPublicProperties() + public static void CopyConstructor_CopiesAllPublicProperties() { JsonSerializerOptions options = GetFullyPopulatedOptionsInstance(); var newOptions = new JsonSerializerOptions(options); - VerifyOptionsEqual_WithReflection(options, newOptions); + VerifyOptionsEqual(options, newOptions); } [Fact] - public static void CopyConstructorTest_NullInput() + public static void CopyConstructor_NullInput() { ArgumentNullException ex = Assert.Throws(() => new JsonSerializerOptions(null)); Assert.Contains("options", ex.ToString()); } + [Fact] + public static void DefaultSerializerOptions_General() + { + var options = new JsonSerializerOptions(); + var newOptions = new JsonSerializerOptions(JsonSerializerDefaults.General); + VerifyOptionsEqual(options, newOptions); + } + + [Fact] + public static void PredefinedSerializerOptions_Web() + { + var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); + JsonNamingPolicy policy = options.PropertyNamingPolicy; + Assert.True(options.PropertyNameCaseInsensitive); + Assert.Same(JsonNamingPolicy.CamelCase, policy); + } + + [Theory] + [InlineData(-1)] + [InlineData(2)] + public static void PredefinedSerializerOptions_UnhandledDefaults(int enumValue) + { + var outOfRangeSerializerDefaults = (JsonSerializerDefaults)enumValue; + Assert.Throws(() => new JsonSerializerOptions(outOfRangeSerializerDefaults)); + } + private static JsonSerializerOptions CreateOptionsInstance() { var options = new JsonSerializerOptions @@ -563,28 +562,6 @@ private static JsonSerializerOptions CreateOptionsInstance() return options; } - private static void VerifyOptionsEqual(JsonSerializerOptions options, JsonSerializerOptions newOptions) - { - Assert.Equal(options.AllowTrailingCommas, newOptions.AllowTrailingCommas); - Assert.Equal(options.DefaultBufferSize, newOptions.DefaultBufferSize); - Assert.Equal(options.IgnoreNullValues, newOptions.IgnoreNullValues); - Assert.Equal(options.IgnoreReadOnlyProperties, newOptions.IgnoreReadOnlyProperties); - Assert.Equal(options.MaxDepth, newOptions.MaxDepth); - Assert.Equal(options.PropertyNameCaseInsensitive, newOptions.PropertyNameCaseInsensitive); - Assert.Equal(options.ReadCommentHandling, newOptions.ReadCommentHandling); - Assert.Equal(options.WriteIndented, newOptions.WriteIndented); - - Assert.Same(options.DictionaryKeyPolicy, newOptions.DictionaryKeyPolicy); - Assert.Same(options.Encoder, newOptions.Encoder); - Assert.Same(options.PropertyNamingPolicy, newOptions.PropertyNamingPolicy); - - Assert.Equal(options.Converters.Count, newOptions.Converters.Count); - for (int i = 0; i < options.Converters.Count; i++) - { - Assert.Same(options.Converters[i], newOptions.Converters[i]); - } - } - private static JsonSerializerOptions GetFullyPopulatedOptionsInstance() { var options = new JsonSerializerOptions(); @@ -595,7 +572,11 @@ private static JsonSerializerOptions GetFullyPopulatedOptionsInstance() if (propertyType == typeof(bool)) { - property.SetValue(options, true); + // IgnoreNullValues and DefaultIgnoreCondition cannot be active at the same time. + if (property.Name != "IgnoreNullValues") + { + property.SetValue(options, true); + } } if (propertyType == typeof(int)) { @@ -622,6 +603,7 @@ private static JsonSerializerOptions GetFullyPopulatedOptionsInstance() else if (propertyType.IsValueType) { options.ReadCommentHandling = JsonCommentHandling.Disallow; + options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault; } else { @@ -634,7 +616,7 @@ private static JsonSerializerOptions GetFullyPopulatedOptionsInstance() return options; } - private static void VerifyOptionsEqual_WithReflection(JsonSerializerOptions options, JsonSerializerOptions newOptions) + private static void VerifyOptionsEqual(JsonSerializerOptions options, JsonSerializerOptions newOptions) { foreach (PropertyInfo property in typeof(JsonSerializerOptions).GetProperties()) { @@ -642,12 +624,10 @@ private static void VerifyOptionsEqual_WithReflection(JsonSerializerOptions opti if (propertyType == typeof(bool)) { - Assert.True((bool)property.GetValue(options)); Assert.Equal((bool)property.GetValue(options), (bool)property.GetValue(newOptions)); } else if (propertyType == typeof(int)) { - Assert.Equal(32, (int)property.GetValue(options)); Assert.Equal((int)property.GetValue(options), (int)property.GetValue(newOptions)); } else if (typeof(IEnumerable).IsAssignableFrom(propertyType)) @@ -667,6 +647,10 @@ private static void VerifyOptionsEqual_WithReflection(JsonSerializerOptions opti { Assert.Equal(options.ReadCommentHandling, newOptions.ReadCommentHandling); } + else if (property.Name == "DefaultIgnoreCondition") + { + Assert.Equal(options.DefaultIgnoreCondition, newOptions.DefaultIgnoreCondition); + } else { Assert.True(false, $"Public option was added to JsonSerializerOptions but not copied in the copy ctor: {property.Name}"); @@ -678,5 +662,46 @@ private static void VerifyOptionsEqual_WithReflection(JsonSerializerOptions opti } } } + + [Fact] + public static void CopyConstructor_IgnoreNullValuesCopied() + { + var options = new JsonSerializerOptions { IgnoreNullValues = true }; + var newOptions = new JsonSerializerOptions(options); + VerifyOptionsEqual(options, newOptions); + } + + [Fact] + public static void CannotSetBoth_IgnoreNullValues_And_DefaultIgnoreCondition() + { + // Set IgnoreNullValues first. + JsonSerializerOptions options = new JsonSerializerOptions { IgnoreNullValues = true }; + + InvalidOperationException ex = Assert.Throws( + () => options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault); + string exAsStr = ex.ToString(); + Assert.Contains("IgnoreNullValues", exAsStr); + Assert.Contains("DefaultIgnoreCondition", exAsStr); + + options.IgnoreNullValues = false; + // We can set the property now. + options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault; + + // Set DefaultIgnoreCondition first. + + options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; + Assert.Throws( + () => options.IgnoreNullValues = true); + + options.DefaultIgnoreCondition = JsonIgnoreCondition.Never; + // We can set the property now. + options.IgnoreNullValues = true; + } + + [Fact] + public static void CannotSet_DefaultIgnoreCondition_To_Always() + { + Assert.Throws(() => new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.Always }); + } } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs b/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs index a13f36661798b..1b0ff3e70ae12 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs @@ -231,6 +231,89 @@ public static void EmptyPropertyName() } } + [Fact] + public static void EmptyPropertyNameInExtensionData() + { + { + string json = @"{"""":42}"; + EmptyClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(42, obj.MyOverflow[""].GetInt32()); + } + + { + // Verify that last-in wins. + string json = @"{"""":42, """":43}"; + EmptyClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(43, obj.MyOverflow[""].GetInt32()); + } + } + + [Fact] + public static void EmptyPropertyName_WinsOver_ExtensionDataEmptyPropertyName() + { + string json = @"{"""":1}"; + + ClassWithEmptyPropertyNameAndExtensionProperty obj; + + // Create a new options instances to re-set any caches. + JsonSerializerOptions options = new JsonSerializerOptions(); + + // Verify the real property wins over the extension data property. + obj = JsonSerializer.Deserialize(json, options); + Assert.Equal(1, obj.MyInt1); + Assert.Null(obj.MyOverflow); + } + + [Fact] + public static void EmptyPropertyNameAndExtensionData_ExtDataFirst() + { + // Verify any caching treats real property (with empty name) differently than a missing property. + + ClassWithEmptyPropertyNameAndExtensionProperty obj; + + // Create a new options instances to re-set any caches. + JsonSerializerOptions options = new JsonSerializerOptions(); + + // First populate cache with a missing property name. + string json = @"{""DoesNotExist"":42}"; + obj = JsonSerializer.Deserialize(json, options); + Assert.Equal(0, obj.MyInt1); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(42, obj.MyOverflow["DoesNotExist"].GetInt32()); + + // Then use an empty property. + json = @"{"""":43}"; + obj = JsonSerializer.Deserialize(json, options); + Assert.Equal(43, obj.MyInt1); + Assert.Null(obj.MyOverflow); + } + + [Fact] + public static void EmptyPropertyAndExtensionData_PropertyFirst() + { + // Verify any caching treats real property (with empty name) differently than a missing property. + + ClassWithEmptyPropertyNameAndExtensionProperty obj; + + // Create a new options instances to re-set any caches. + JsonSerializerOptions options = new JsonSerializerOptions(); + + // First use an empty property. + string json = @"{"""":43}"; + obj = JsonSerializer.Deserialize(json, options); + Assert.Equal(43, obj.MyInt1); + Assert.Null(obj.MyOverflow); + + // Then populate cache with a missing property name. + json = @"{""DoesNotExist"":42}"; + obj = JsonSerializer.Deserialize(json, options); + Assert.Equal(0, obj.MyInt1); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(42, obj.MyOverflow["DoesNotExist"].GetInt32()); + } + [Fact] public static void UnicodePropertyNames() { @@ -515,4 +598,13 @@ public class EmptyClassWithExtensionProperty [JsonExtensionData] public IDictionary MyOverflow { get; set; } } + + public class ClassWithEmptyPropertyNameAndExtensionProperty + { + [JsonPropertyName("")] + public int MyInt1 { get; set; } + + [JsonExtensionData] + public IDictionary MyOverflow { get; set; } + } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.NonPublicAccessors.cs b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.NonPublicAccessors.cs index de7e206c5a953..4385cd6fae519 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.NonPublicAccessors.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.NonPublicAccessors.cs @@ -88,7 +88,7 @@ private class MyClass_WithNonPublicAccessors_WithPropertyAttributes_And_Property public int MyInt { get; private set; } [JsonInclude] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string MyString { get; internal set; } = "DefaultString"; [JsonInclude] diff --git a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs index 9aa9cd6bb8ba7..8cc9cf6e6bde7 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs @@ -11,6 +11,469 @@ namespace System.Text.Json.Serialization.Tests { public static partial class PropertyVisibilityTests { + [Fact] + public static void Serialize_NewSlotPublicProperty() + { + // Serialize + var obj = new ClassWithNewSlotProperty(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{""MyString"":""NewDefaultValue""}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("NewValue", ((ClassWithNewSlotProperty)obj).MyString); + Assert.Equal("DefaultValue", ((ClassWithInternalProperty)obj).MyString); + } + + [Fact] + public static void Serialize_BasePublicProperty_ConflictWithDerivedPrivate() + { + // Serialize + var obj = new ClassWithNewSlotInternalProperty(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{""MyString"":""DefaultValue""}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("NewValue", ((ClassWithPublicProperty)obj).MyString); + Assert.Equal("NewDefaultValue", ((ClassWithNewSlotInternalProperty)obj).MyString); + } + + [Fact] + public static void Serialize_PublicProperty_ConflictWithPrivateDueAttributes() + { + // Serialize + var obj = new ClassWithPropertyNamingConflict(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{""MyString"":""DefaultValue""}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("NewValue", obj.MyString); + Assert.Equal("ConflictingValue", obj.ConflictingString); + } + + [Fact] + public static void Serialize_PublicProperty_ConflictWithPrivateDuePolicy() + { + var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + + // Serialize + var obj = new ClassWithPropertyPolicyConflict(); + string json = JsonSerializer.Serialize(obj, options); + + Assert.Equal(@"{""myString"":""DefaultValue""}", json); + + // Deserialize + json = @"{""myString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json, options); + + Assert.Equal("NewValue", obj.MyString); + Assert.Equal("ConflictingValue", obj.myString); + } + + [Fact] + public static void Serealize_NewSlotPublicProperty_ConflictWithBasePublicProperty() + { + // Serialize + var obj = new ClassWithNewSlotDecimalProperty(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{""MyNumeric"":1.5}", json); + + // Deserialize + json = @"{""MyNumeric"":2.5}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal(2.5M, obj.MyNumeric); + } + + [Fact] + public static void Serealize_NewSlotPublicProperty_SpecifiedJsonPropertyName() + { + // Serialize + var obj = new ClassWithNewSlotAttributedDecimalProperty(); + string json = JsonSerializer.Serialize(obj); + + Assert.Contains(@"""MyNewNumeric"":1.5", json); + Assert.Contains(@"""MyNumeric"":1", json); + + // Deserialize + json = @"{""MyNewNumeric"":2.5,""MyNumeric"":4}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal(4, ((ClassWithHiddenByNewSlotIntProperty)obj).MyNumeric); + Assert.Equal(2.5M, ((ClassWithNewSlotAttributedDecimalProperty)obj).MyNumeric); + } + + [Fact] + public static void Ignore_NonPublicProperty() + { + // Serialize + var obj = new ClassWithInternalProperty(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("DefaultValue", obj.MyString); + } + + [Fact] + public static void Ignore_NewSlotPublicPropertyIgnored() + { + // Serialize + var obj = new ClassWithIgnoredNewSlotProperty(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("NewDefaultValue", ((ClassWithIgnoredNewSlotProperty)obj).MyString); + Assert.Equal("DefaultValue", ((ClassWithInternalProperty)obj).MyString); + } + + [Fact] + public static void Ignore_BasePublicPropertyIgnored_ConflictWithDerivedPrivate() + { + // Serialize + var obj = new ClassWithIgnoredPublicPropertyAndNewSlotPrivate(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("DefaultValue", ((ClassWithIgnoredPublicProperty)obj).MyString); + Assert.Equal("NewDefaultValue", ((ClassWithIgnoredPublicPropertyAndNewSlotPrivate)obj).MyString); + } + + [Fact] + public static void Ignore_PublicProperty_ConflictWithPrivateDueAttributes() + { + // Serialize + var obj = new ClassWithIgnoredPropertyNamingConflictPrivate(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("DefaultValue", obj.MyString); + Assert.Equal("ConflictingValue", obj.ConflictingString); + } + + [Fact] + public static void Ignore_PublicProperty_ConflictWithPrivateDuePolicy() + { + var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + + // Serialize + var obj = new ClassWithIgnoredPropertyPolicyConflictPrivate(); + string json = JsonSerializer.Serialize(obj, options); + + Assert.Equal(@"{}", json); + + // Deserialize + json = @"{""myString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json, options); + + Assert.Equal("DefaultValue", obj.MyString); + Assert.Equal("ConflictingValue", obj.myString); + } + + [Fact] + public static void Ignore_PublicProperty_ConflictWithPublicDueAttributes() + { + // Serialize + var obj = new ClassWithIgnoredPropertyNamingConflictPublic(); + string json = JsonSerializer.Serialize(obj); + + Assert.Equal(@"{""MyString"":""ConflictingValue""}", json); + + // Deserialize + json = @"{""MyString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json); + + Assert.Equal("DefaultValue", obj.MyString); + Assert.Equal("NewValue", obj.ConflictingString); + } + + [Fact] + public static void Ignore_PublicProperty_ConflictWithPublicDuePolicy() + { + var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + + // Serialize + var obj = new ClassWithIgnoredPropertyPolicyConflictPublic(); + string json = JsonSerializer.Serialize(obj, options); + + Assert.Equal(@"{""myString"":""ConflictingValue""}", json); + + // Deserialize + json = @"{""myString"":""NewValue""}"; + obj = JsonSerializer.Deserialize(json, options); + + Assert.Equal("DefaultValue", obj.MyString); + Assert.Equal("NewValue", obj.myString); + } + + [Fact] + public static void Throw_PublicProperty_ConflictDueAttributes() + { + // Serialize + var obj = new ClassWithPropertyNamingConflictWhichThrows(); + Assert.Throws( + () => JsonSerializer.Serialize(obj)); + + // Deserialize + string json = @"{""MyString"":""NewValue""}"; + Assert.Throws( + () => JsonSerializer.Deserialize(json)); + } + + [Fact] + public static void Throw_PublicProperty_ConflictDueAttributes_SingleInheritance() + { + // Serialize + var obj = new ClassInheritedWithPropertyNamingConflictWhichThrows(); + Assert.Throws( + () => JsonSerializer.Serialize(obj)); + + // Deserialize + string json = @"{""MyString"":""NewValue""}"; + Assert.Throws( + () => JsonSerializer.Deserialize(json)); + } + + [Fact] + public static void Throw_PublicProperty_ConflictDueAttributes_DoubleInheritance() + { + // Serialize + var obj = new ClassTwiceInheritedWithPropertyNamingConflictWhichThrows(); + Assert.Throws( + () => JsonSerializer.Serialize(obj)); + + // Deserialize + string json = @"{""MyString"":""NewValue""}"; + Assert.Throws( + () => JsonSerializer.Deserialize(json)); + } + + [Fact] + public static void Throw_PublicProperty_ConflictDuePolicy() + { + var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + + // Serialize + var obj = new ClassWithPropertyPolicyConflictWhichThrows(); + Assert.Throws( + () => JsonSerializer.Serialize(obj, options)); + + // Deserialize + string json = @"{""MyString"":""NewValue""}"; + Assert.Throws( + () => JsonSerializer.Deserialize(json, options)); + } + + [Fact] + public static void Throw_PublicProperty_ConflictDuePolicy_SingleInheritance() + { + var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + + // Serialize + var obj = new ClassInheritedWithPropertyPolicyConflictWhichThrows(); + Assert.Throws( + () => JsonSerializer.Serialize(obj, options)); + + // Deserialize + string json = @"{""MyString"":""NewValue""}"; + Assert.Throws( + () => JsonSerializer.Deserialize(json, options)); + } + + [Fact] + public static void Throw_PublicProperty_ConflictDuePolicy_DobuleInheritance() + { + var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + + // Serialize + var obj = new ClassTwiceInheritedWithPropertyPolicyConflictWhichThrows(); + Assert.Throws( + () => JsonSerializer.Serialize(obj, options)); + + // Deserialize + string json = @"{""MyString"":""NewValue""}"; + Assert.Throws( + () => JsonSerializer.Deserialize(json, options)); + } + + public class ClassWithInternalProperty + { + internal string MyString { get; set; } = "DefaultValue"; + } + + public class ClassWithNewSlotProperty : ClassWithInternalProperty + { + public new string MyString { get; set; } = "NewDefaultValue"; + } + + public class ClassWithPublicProperty + { + public string MyString { get; set; } = "DefaultValue"; + } + + public class ClassWithNewSlotInternalProperty : ClassWithPublicProperty + { + internal new string MyString { get; set; } = "NewDefaultValue"; + } + + public class ClassWithPropertyNamingConflict + { + public string MyString { get; set; } = "DefaultValue"; + + [JsonPropertyName(nameof(MyString))] + internal string ConflictingString { get; set; } = "ConflictingValue"; + } + + public class ClassWithPropertyNamingConflictWhichThrows + { + public string MyString { get; set; } = "DefaultValue"; + + [JsonPropertyName(nameof(MyString))] + public string ConflictingString { get; set; } = "ConflictingValue"; + } + + public class ClassInheritedWithPropertyNamingConflictWhichThrows : ClassWithPublicProperty + { + [JsonPropertyName(nameof(MyString))] + public string ConflictingString { get; set; } = "ConflictingValue"; + } + + public class ClassTwiceInheritedWithPropertyNamingConflictWhichThrowsDummy : ClassWithPublicProperty + { + } + + public class ClassTwiceInheritedWithPropertyNamingConflictWhichThrows : ClassTwiceInheritedWithPropertyNamingConflictWhichThrowsDummy + { + [JsonPropertyName(nameof(MyString))] + public string ConflictingString { get; set; } = "ConflictingValue"; + } + + public class ClassWithPropertyPolicyConflict + { + public string MyString { get; set; } = "DefaultValue"; + + internal string myString { get; set; } = "ConflictingValue"; + } + + public class ClassWithPropertyPolicyConflictWhichThrows + { + public string MyString { get; set; } = "DefaultValue"; + + public string myString { get; set; } = "ConflictingValue"; + } + + public class ClassInheritedWithPropertyPolicyConflictWhichThrows : ClassWithPublicProperty + { + public string myString { get; set; } = "ConflictingValue"; + } + + public class ClassInheritedWithPropertyPolicyConflictWhichThrowsDummy : ClassWithPublicProperty + { + } + + public class ClassTwiceInheritedWithPropertyPolicyConflictWhichThrows : ClassInheritedWithPropertyPolicyConflictWhichThrowsDummy + { + public string myString { get; set; } = "ConflictingValue"; + } + + public class ClassWithIgnoredNewSlotProperty : ClassWithInternalProperty + { + [JsonIgnore] + public new string MyString { get; set; } = "NewDefaultValue"; + } + + public class ClassWithIgnoredPublicProperty + { + [JsonIgnore] + public string MyString { get; set; } = "DefaultValue"; + } + + public class ClassWithIgnoredPublicPropertyAndNewSlotPrivate : ClassWithIgnoredPublicProperty + { + internal new string MyString { get; set; } = "NewDefaultValue"; + } + + public class ClassWithIgnoredPropertyNamingConflictPrivate + { + [JsonIgnore] + public string MyString { get; set; } = "DefaultValue"; + + [JsonPropertyName(nameof(MyString))] + internal string ConflictingString { get; set; } = "ConflictingValue"; + } + + public class ClassWithIgnoredPropertyPolicyConflictPrivate + { + [JsonIgnore] + public string MyString { get; set; } = "DefaultValue"; + + internal string myString { get; set; } = "ConflictingValue"; + } + + public class ClassWithIgnoredPropertyNamingConflictPublic + { + [JsonIgnore] + public string MyString { get; set; } = "DefaultValue"; + + [JsonPropertyName(nameof(MyString))] + public string ConflictingString { get; set; } = "ConflictingValue"; + } + + public class ClassWithIgnoredPropertyPolicyConflictPublic + { + [JsonIgnore] + public string MyString { get; set; } = "DefaultValue"; + + public string myString { get; set; } = "ConflictingValue"; + } + + public class ClassWithHiddenByNewSlotIntProperty + { + public int MyNumeric { get; set; } = 1; + } + + public class ClassWithNewSlotDecimalProperty : ClassWithHiddenByNewSlotIntProperty + { + public new decimal MyNumeric { get; set; } = 1.5M; + } + + public class ClassWithNewSlotAttributedDecimalProperty : ClassWithHiddenByNewSlotIntProperty + { + [JsonPropertyName("MyNewNumeric")] + public new decimal MyNumeric { get; set; } = 1.5M; + } + [Fact] public static void NoSetter() { @@ -524,8 +987,8 @@ public ClassWithProperty_IgnoreConditionAlways_Ctor(DateTime myDateTime, int myI } [Theory] - [MemberData(nameof(JsonIgnoreConditionWhenNull_ClassProperty_TestData))] - public static void JsonIgnoreConditionWhenNull_ClassProperty(Type type, JsonSerializerOptions options) + [MemberData(nameof(JsonIgnoreConditionWhenWritingDefault_ClassProperty_TestData))] + public static void JsonIgnoreConditionWhenWritingDefault_ClassProperty(Type type, JsonSerializerOptions options) { // Property shouldn't be ignored if it isn't null. string json = @"{""Int1"":1,""MyString"":""Random"",""Int2"":2}"; @@ -545,7 +1008,17 @@ public static void JsonIgnoreConditionWhenNull_ClassProperty(Type type, JsonSeri obj = JsonSerializer.Deserialize(json, type, options); Assert.Equal(1, (int)type.GetProperty("Int1").GetValue(obj)); - Assert.Equal("DefaultString", (string)type.GetProperty("MyString").GetValue(obj)); + + if (options.IgnoreNullValues) + { + // Null values can be ignored on deserialization using IgnoreNullValues. + Assert.Equal("DefaultString", (string)type.GetProperty("MyString").GetValue(obj)); + } + else + { + Assert.Null((string)type.GetProperty("MyString").GetValue(obj)); + } + Assert.Equal(2, (int)type.GetProperty("Int2").GetValue(obj)); // Set property to be ignored to null. @@ -557,22 +1030,22 @@ public static void JsonIgnoreConditionWhenNull_ClassProperty(Type type, JsonSeri Assert.DoesNotContain(@"""MyString"":", serialized); } - private class ClassWithClassProperty_IgnoreConditionWhenNull + private class ClassWithClassProperty_IgnoreConditionWhenWritingDefault { public int Int1 { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string MyString { get; set; } = "DefaultString"; public int Int2 { get; set; } } - private class ClassWithClassProperty_IgnoreConditionWhenNull_Ctor + private class ClassWithClassProperty_IgnoreConditionWhenWritingDefault_Ctor { public int Int1 { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string MyString { get; set; } = "DefaultString"; public int Int2 { get; set; } - public ClassWithClassProperty_IgnoreConditionWhenNull_Ctor(string myString) + public ClassWithClassProperty_IgnoreConditionWhenWritingDefault_Ctor(string myString) { if (myString != null) { @@ -581,15 +1054,15 @@ public ClassWithClassProperty_IgnoreConditionWhenNull_Ctor(string myString) } } - private static IEnumerable JsonIgnoreConditionWhenNull_ClassProperty_TestData() + private static IEnumerable JsonIgnoreConditionWhenWritingDefault_ClassProperty_TestData() { - yield return new object[] { typeof(ClassWithClassProperty_IgnoreConditionWhenNull), new JsonSerializerOptions() }; - yield return new object[] { typeof(ClassWithClassProperty_IgnoreConditionWhenNull_Ctor), new JsonSerializerOptions { IgnoreNullValues = true } }; + yield return new object[] { typeof(ClassWithClassProperty_IgnoreConditionWhenWritingDefault), new JsonSerializerOptions() }; + yield return new object[] { typeof(ClassWithClassProperty_IgnoreConditionWhenWritingDefault_Ctor), new JsonSerializerOptions { IgnoreNullValues = true } }; } [Theory] - [MemberData(nameof(JsonIgnoreConditionWhenNull_StructProperty_TestData))] - public static void JsonIgnoreConditionWhenNull_StructProperty(Type type, JsonSerializerOptions options) + [MemberData(nameof(JsonIgnoreConditionWhenWritingDefault_StructProperty_TestData))] + public static void JsonIgnoreConditionWhenWritingDefault_StructProperty(Type type, JsonSerializerOptions options) { // Property shouldn't be ignored if it isn't null. string json = @"{""Int1"":1,""MyInt"":3,""Int2"":2}"; @@ -609,23 +1082,23 @@ public static void JsonIgnoreConditionWhenNull_StructProperty(Type type, JsonSer Assert.Throws(() => JsonSerializer.Deserialize(json, type, options)); } - private class ClassWithStructProperty_IgnoreConditionWhenNull + private class ClassWithStructProperty_IgnoreConditionWhenWritingDefault { public int Int1 { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public int MyInt { get; set; } public int Int2 { get; set; } } - private struct StructWithStructProperty_IgnoreConditionWhenNull_Ctor + private struct StructWithStructProperty_IgnoreConditionWhenWritingDefault_Ctor { public int Int1 { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public int MyInt { get; } public int Int2 { get; set; } [JsonConstructor] - public StructWithStructProperty_IgnoreConditionWhenNull_Ctor(int myInt) + public StructWithStructProperty_IgnoreConditionWhenWritingDefault_Ctor(int myInt) { Int1 = 0; MyInt = myInt; @@ -633,10 +1106,10 @@ public StructWithStructProperty_IgnoreConditionWhenNull_Ctor(int myInt) } } - private static IEnumerable JsonIgnoreConditionWhenNull_StructProperty_TestData() + private static IEnumerable JsonIgnoreConditionWhenWritingDefault_StructProperty_TestData() { - yield return new object[] { typeof(ClassWithStructProperty_IgnoreConditionWhenNull), new JsonSerializerOptions() }; - yield return new object[] { typeof(StructWithStructProperty_IgnoreConditionWhenNull_Ctor), new JsonSerializerOptions { IgnoreNullValues = true } }; + yield return new object[] { typeof(ClassWithStructProperty_IgnoreConditionWhenWritingDefault), new JsonSerializerOptions() }; + yield return new object[] { typeof(StructWithStructProperty_IgnoreConditionWhenWritingDefault_Ctor), new JsonSerializerOptions { IgnoreNullValues = true } }; } [Theory] @@ -745,33 +1218,30 @@ public static void JsonIgnoreCondition_LastOneWins() } [Fact] - public static void ClassWithComplexObjectsUsingIgnoreWhenNullAttribute() + public static void ClassWithComplexObjectsUsingIgnoreWhenWritingDefaultAttribute() { string json = @"{""Class"":{""MyInt16"":18}, ""Dictionary"":null}"; - ClassUsingIgnoreWhenNullAttribute obj = JsonSerializer.Deserialize(json); + ClassUsingIgnoreWhenWritingDefaultAttribute obj = JsonSerializer.Deserialize(json); - // Class is deserialized because it is not null in json. + // Class is deserialized. Assert.NotNull(obj.Class); Assert.Equal(18, obj.Class.MyInt16); - // Dictionary is left alone because it is null in json. - Assert.NotNull(obj.Dictionary); - Assert.Equal(1, obj.Dictionary.Count); - Assert.Equal("Value", obj.Dictionary["Key"]); - + // Dictionary is deserialized as JsonIgnoreCondition.WhenWritingDefault only applies to deserialization. + Assert.Null(obj.Dictionary); - obj = new ClassUsingIgnoreWhenNullAttribute(); + obj = new ClassUsingIgnoreWhenWritingDefaultAttribute(); json = JsonSerializer.Serialize(obj); Assert.Equal(@"{""Dictionary"":{""Key"":""Value""}}", json); } - public class ClassUsingIgnoreWhenNullAttribute + public class ClassUsingIgnoreWhenWritingDefaultAttribute { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public SimpleTestClass Class { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public Dictionary Dictionary { get; set; } = new Dictionary { ["Key"] = "Value" }; } @@ -827,7 +1297,7 @@ public static void IgnoreConditionNever_WinsOver_IgnoreReadOnlyValues() } [Fact] - public static void IgnoreConditionWhenNull_WinsOver_IgnoreReadOnlyValues() + public static void IgnoreConditionWhenWritingDefault_WinsOver_IgnoreReadOnlyValues() { var options = new JsonSerializerOptions { IgnoreReadOnlyProperties = true }; @@ -836,10 +1306,10 @@ public static void IgnoreConditionWhenNull_WinsOver_IgnoreReadOnlyValues() Assert.Equal("{}", json); // With condition to ignore when null - json = JsonSerializer.Serialize(new ClassWithReadOnlyString_IgnoreWhenNull("Hello"), options); + json = JsonSerializer.Serialize(new ClassWithReadOnlyString_IgnoreWhenWritingDefault("Hello"), options); Assert.Equal(@"{""MyString"":""Hello""}", json); - json = JsonSerializer.Serialize(new ClassWithReadOnlyString_IgnoreWhenNull(null), options); + json = JsonSerializer.Serialize(new ClassWithReadOnlyString_IgnoreWhenWritingDefault(null), options); Assert.Equal(@"{}", json); } @@ -858,12 +1328,12 @@ private class ClassWithReadOnlyString_IgnoreNever public ClassWithReadOnlyString_IgnoreNever(string myString) => MyString = myString; } - private class ClassWithReadOnlyString_IgnoreWhenNull + private class ClassWithReadOnlyString_IgnoreWhenWritingDefault { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenNull)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string MyString { get; } - public ClassWithReadOnlyString_IgnoreWhenNull(string myString) => MyString = myString; + public ClassWithReadOnlyString_IgnoreWhenWritingDefault(string myString) => MyString = myString; } [Fact] @@ -889,5 +1359,81 @@ private class ClassWithNonPublicProperties internal float GetMyFloat => MyFloat; internal double GetMyDouble => MyDouble; } + + [Fact] + public static void IgnoreCondition_WhenWritingDefault_Globally_Works() + { + // Baseline - default values written. + string expected = @"{""MyString"":null,""MyInt"":0,""MyPoint"":{""X"":0,""Y"":0}}"; + var obj = new ClassWithProps(); + JsonTestHelper.AssertJsonEqual(expected, JsonSerializer.Serialize(obj)); + + // Default values ignored when specified. + Assert.Equal("{}", JsonSerializer.Serialize(obj, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault })); + } + + private class ClassWithProps + { + public string MyString { get; set; } + public int MyInt { get; set; } + public Point_2D_Struct MyPoint { get; set; } + } + + [Fact] + public static void IgnoreCondition_WhenWritingDefault_PerProperty_Works() + { + // Default values ignored when specified. + Assert.Equal(@"{""MyInt"":0}", JsonSerializer.Serialize(new ClassWithPropsAndIgnoreAttributes())); + } + + private class ClassWithPropsAndIgnoreAttributes + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public string MyString { get; set; } + public int MyInt { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public Point_2D_Struct MyPoint { get; set; } + } + + [Fact] + public static void IgnoreCondition_WhenWritingDefault_DoesNotApplyToCollections() + { + var list = new List { false, true }; + + var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; + Assert.Equal("[false,true]", JsonSerializer.Serialize(list, options)); + } + + [Fact] + public static void IgnoreCondition_WhenWritingDefault_DoesNotApplyToDeserialization() + { + // Baseline - null values are ignored on deserialization when using IgnoreNullValues (for compat with initial support). + string json = @"{""MyString"":null,""MyInt"":0,""MyPoint"":{""X"":0,""Y"":0}}"; + + var options = new JsonSerializerOptions { IgnoreNullValues = true }; + ClassWithInitializedProps obj = JsonSerializer.Deserialize(json, options); + + Assert.Equal("Default", obj.MyString); + // Value types are not ignored. + Assert.Equal(0, obj.MyInt); + Assert.Equal(0, obj.MyPoint.X); + Assert.Equal(0, obj.MyPoint.X); + + // Test - default values (both null and default for value types) are not ignored when using + // JsonIgnoreCondition.WhenWritingDefault (as the option name implies) + options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; + obj = JsonSerializer.Deserialize(json, options); + Assert.Null(obj.MyString); + Assert.Equal(0, obj.MyInt); + Assert.Equal(0, obj.MyPoint.X); + Assert.Equal(0, obj.MyPoint.X); + } + + private class ClassWithInitializedProps + { + public string MyString { get; set; } = "Default"; + public int MyInt { get; set; } = -1; + public Point_2D_Struct MyPoint { get; set; } = new Point_2D_Struct(-1, -1); + } } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs index 8fce473d62993..1d02e33d7f6a0 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs @@ -917,6 +917,13 @@ public NullArgTester(Point_3D_Struct point3DStruct, ImmutableArray immutabl } } + public class NullArgTester_Mutable + { + public Point_3D_Struct Point3DStruct { get; set; } + public ImmutableArray ImmutableArray { get; set; } + public int Int { get; set; } + } + public class ClassWithConstructor_SimpleAndComplexParameters : ITestClassWithParameterizedCtor { public byte MyByte { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj index 881b2d8450fe1..2693078629bfc 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -5,11 +5,10 @@ - $(DefineConstants);BUILDING_INBOX_LIBRARY + $(DefineConstants);BUILDING_INBOX_LIBRARY - + @@ -45,6 +44,7 @@ + @@ -70,6 +70,7 @@ + @@ -136,12 +137,10 @@ - + - - + + diff --git a/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs b/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs index 392eeb1cc9dd1..3b80897e1ed94 100644 --- a/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs +++ b/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs @@ -4380,7 +4380,6 @@ public static IEnumerable InvalidJsonStrings new object[] {"+0", 0, 0}, new object[] {"+1", 0, 0}, new object[] {"0e", 0, 2}, - new object[] {"0.", 0, 2}, new object[] {"0.1e", 0, 4}, new object[] {"01", 0, 1}, new object[] {"1a", 0, 1}, diff --git a/src/libraries/System.Text.Json/tests/Utf8JsonWriterTests.cs b/src/libraries/System.Text.Json/tests/Utf8JsonWriterTests.cs index 82ab722487415..5ead06b20c4bc 100644 --- a/src/libraries/System.Text.Json/tests/Utf8JsonWriterTests.cs +++ b/src/libraries/System.Text.Json/tests/Utf8JsonWriterTests.cs @@ -2982,6 +2982,16 @@ public void WritingTooLargeBase64Bytes(bool formatted, bool skipValidation) Assert.Throws(() => jsonUtf8.WriteBase64StringValue(value.AsSpan(0, 125_000_001))); } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + Assert.Throws(() => jsonUtf8.WriteBase64String(value.AsSpan(0, 166_666_667), value.AsSpan(0, 1))); + } + + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + Assert.Throws(() => jsonUtf8.WriteBase64String(Encoding.UTF8.GetString(value).ToCharArray().AsSpan(0, 166_666_667), value.AsSpan(0, 1))); + } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) { Assert.Throws(() => jsonUtf8.WriteBase64StringValue(value)); diff --git a/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs b/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs index f97324489a8bf..c063564dd4244 100644 --- a/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs +++ b/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs @@ -37,12 +37,12 @@ public partial class CaptureCollection : System.Collections.Generic.ICollection< int System.Collections.Generic.IList.IndexOf(System.Text.RegularExpressions.Capture item) { throw null; } void System.Collections.Generic.IList.Insert(int index, System.Text.RegularExpressions.Capture item) { } void System.Collections.Generic.IList.RemoveAt(int index) { } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } void System.Collections.IList.Clear() { } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } void System.Collections.IList.RemoveAt(int index) { } } public partial class Group : System.Text.RegularExpressions.Capture @@ -80,12 +80,12 @@ public partial class GroupCollection : System.Collections.Generic.ICollection.IndexOf(System.Text.RegularExpressions.Group item) { throw null; } void System.Collections.Generic.IList.Insert(int index, System.Text.RegularExpressions.Group item) { } void System.Collections.Generic.IList.RemoveAt(int index) { } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } void System.Collections.IList.Clear() { } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } void System.Collections.IList.RemoveAt(int index) { } #pragma warning disable CS8614 // Nullability of reference types in type of parameter doesn't match implicitly implemented member. public bool TryGetValue(string key, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.RegularExpressions.Group? value) { throw null; } @@ -122,12 +122,12 @@ public partial class MatchCollection : System.Collections.Generic.ICollection.IndexOf(System.Text.RegularExpressions.Match item) { throw null; } void System.Collections.Generic.IList.Insert(int index, System.Text.RegularExpressions.Match item) { } void System.Collections.Generic.IList.RemoveAt(int index) { } - int System.Collections.IList.Add(object value) { throw null; } + int System.Collections.IList.Add(object? value) { throw null; } void System.Collections.IList.Clear() { } - bool System.Collections.IList.Contains(object value) { throw null; } - int System.Collections.IList.IndexOf(object value) { throw null; } - void System.Collections.IList.Insert(int index, object value) { } - void System.Collections.IList.Remove(object value) { } + bool System.Collections.IList.Contains(object? value) { throw null; } + int System.Collections.IList.IndexOf(object? value) { throw null; } + void System.Collections.IList.Insert(int index, object? value) { } + void System.Collections.IList.Remove(object? value) { } void System.Collections.IList.RemoveAt(int index) { } } public delegate string MatchEvaluator(System.Text.RegularExpressions.Match match); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/CompiledRegexRunnerFactory.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/CompiledRegexRunnerFactory.cs index 2d2d930e97548..e025fdf69f080 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/CompiledRegexRunnerFactory.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/CompiledRegexRunnerFactory.cs @@ -25,8 +25,8 @@ public CompiledRegexRunnerFactory(DynamicMethod goMethod, DynamicMethod findFirs protected internal override RegexRunner CreateInstance() => new CompiledRegexRunner( - _go ??= (Action)_goMethod.CreateDelegate(typeof(Action)), - _findFirstChar ??= (Func)_findFirstCharMethod.CreateDelegate(typeof(Func)), + _go ??= _goMethod.CreateDelegate>(), + _findFirstChar ??= _findFirstCharMethod.CreateDelegate>(), _trackcount); } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs index 1479c2ea6de06..79f352130f5d7 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs @@ -310,18 +310,18 @@ internal RegexNode FinalOptimize() // to implementations that don't support backtracking. EliminateEndingBacktracking(rootNode.Child(0), DefaultMaxRecursionDepth); - // Optimization: unnecessary re-processing of atomic starting groups. - // If an expression is guaranteed to begin with a single-character infinite atomic group that isn't part of an alternation (in which case it + // Optimization: unnecessary re-processing of starting loops. + // If an expression is guaranteed to begin with a single-character unbounded loop that isn't part of an alternation (in which case it // wouldn't be guaranteed to be at the beginning) or a capture (in which case a back reference could be influenced by its length), then we // can update the tree with a temporary node to indicate that the implementation should use that node's ending position in the input text // as the next starting position at which to start the next match. This avoids redoing matches we've already performed, e.g. matching // "\w+@dot.net" against "is this a valid address@dot.net", the \w+ will initially match the "is" and then will fail to match the "@". - // Rather than bumping the scan loop by 1 and trying again to match at the "s", we can instead start at the " ". We limit ourselves to - // one/set atomic loops with a min iteration count of 1 so that we know we'll get something in exchange for the extra overhead of storing - // the updated position. For functional correctness we can only consider infinite atomic loops, as to be able to start at the end of the - // loop we need the loop to have consumed all possible matches; otherwise, you could end up with a pattern like "a{1,3}b" matching - // against "aaaabc", which should match, but if we pre-emptively stop consuming after the first three a's and re-start from that position, - // we'll end up failing the match even though it should have succeeded. + // Rather than bumping the scan loop by 1 and trying again to match at the "s", we can instead start at the " ". For functional correctness + // we can only consider unbounded loops, as to be able to start at the end of the loop we need the loop to have consumed all possible matches; + // otherwise, you could end up with a pattern like "a{1,3}b" matching against "aaaabc", which should match, but if we pre-emptively stop consuming + // after the first three a's and re-start from that position, we'll end up failing the match even though it should have succeeded. We can also + // apply this optimization to non-atomic loops. Even though backtracking could be necessary, such backtracking would be handled within the processing + // of a single starting position. { RegexNode node = rootNode.Child(0); // skip implicit root capture node while (true) @@ -333,9 +333,12 @@ internal RegexNode FinalOptimize() node = node.Child(0); continue; - case Oneloopatomic when node.M > 0 && node.N == int.MaxValue: - case Notoneloopatomic when node.M > 0 && node.N == int.MaxValue: - case Setloopatomic when node.M > 0 && node.N == int.MaxValue: + case Oneloop when node.N == int.MaxValue: + case Oneloopatomic when node.N == int.MaxValue: + case Notoneloop when node.N == int.MaxValue: + case Notoneloopatomic when node.N == int.MaxValue: + case Setloop when node.N == int.MaxValue: + case Setloopatomic when node.N == int.MaxValue: RegexNode? parent = node.Next; if (parent != null && parent.Type == Concatenate) { diff --git a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs index cf25c63f18afb..efd7b3cc7d8cc 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs @@ -124,6 +124,8 @@ public static IEnumerable Match_Basic_TestData() yield return new object[] { @"\w+(?\w+)(?\w+)(? + + netstandard2.0;netstandard1.0;netstandard1.1 + enable + + $(DefineConstants);FEATURE_TRACING $(DefineConstants);USE_INTERNAL_CONCURRENT_COLLECTIONS $(DefineConstants);USE_INTERNAL_THREADING netstandard1.1;portable-net45+win8+wpa81 - netstandard2.0;netstandard1.0;netstandard1.1 - enable diff --git a/src/libraries/System.Threading.Thread/tests/ThreadTests.cs b/src/libraries/System.Threading.Thread/tests/ThreadTests.cs index 846602b863b3b..97356a400e7f3 100644 --- a/src/libraries/System.Threading.Thread/tests/ThreadTests.cs +++ b/src/libraries/System.Threading.Thread/tests/ThreadTests.cs @@ -651,6 +651,20 @@ public static void NameTest() }); } + [Fact] + public static void ThreadNameDoesNotAffectProcessName() + { + // On Linux, changing the main thread name affects ProcessName. + // To avoid that, .NET ignores requests to change the main thread name. + RemoteExecutor.Invoke(() => + { + const string ThreadName = "my-thread"; + Thread.CurrentThread.Name = ThreadName; + Assert.Equal(ThreadName, Thread.CurrentThread.Name); + Assert.NotEqual(ThreadName, Process.GetCurrentProcess().ProcessName); + }).Dispose(); + } + [Fact] public static void PriorityTest() { diff --git a/src/libraries/System.Threading/tests/MutexTests.cs b/src/libraries/System.Threading/tests/MutexTests.cs index 79de3ee2be4f9..1557a24f8a0da 100644 --- a/src/libraries/System.Threading/tests/MutexTests.cs +++ b/src/libraries/System.Threading/tests/MutexTests.cs @@ -394,46 +394,60 @@ public static IEnumerable AbandonExisting_MemberData() public static IEnumerable CrossProcess_NamedMutex_ProtectedFileAccessAtomic_MemberData() { - var nameGuidStr = Guid.NewGuid().ToString("N"); foreach (var namePrefix in GetNamePrefixes()) { - yield return new object[] { namePrefix + nameGuidStr }; + yield return new object[] { namePrefix }; } } - [ActiveIssue("https://github.com/dotnet/runtime/issues/28449")] [Theory] + [ActiveIssue("https://github.com/dotnet/runtime/issues/36307", TestRuntimes.Mono)] [MemberData(nameof(CrossProcess_NamedMutex_ProtectedFileAccessAtomic_MemberData))] public void CrossProcess_NamedMutex_ProtectedFileAccessAtomic(string prefix) { - ThreadTestHelpers.RunTestInBackgroundThread(() => + string fileName = GetTestFilePath(); + try { - string mutexName = prefix + Guid.NewGuid().ToString("N"); - string fileName = GetTestFilePath(); - - Action otherProcess = (m, f) => + ThreadTestHelpers.RunTestInBackgroundThread(() => { - using (var mutex = Mutex.OpenExisting(m)) - { - mutex.CheckedWait(); - try - { File.WriteAllText(f, "0"); } - finally { mutex.ReleaseMutex(); } + string mutexName = prefix + Guid.NewGuid().ToString("N"); - IncrementValueInFileNTimes(mutex, f, 10); - } - }; + Action otherProcess = (m, f) => + { + using (var mutex = Mutex.OpenExisting(m)) + { + mutex.CheckedWait(); + try + { File.WriteAllText(f, "0"); } + finally { mutex.ReleaseMutex(); } - using (var mutex = new Mutex(false, mutexName)) - using (var remote = RemoteExecutor.Invoke(otherProcess, mutexName, fileName)) - { - SpinWait.SpinUntil(() => File.Exists(fileName), ThreadTestHelpers.UnexpectedTimeoutMilliseconds); + IncrementValueInFileNTimes(mutex, f, 10); + } + }; - IncrementValueInFileNTimes(mutex, fileName, 10); - } + using (var mutex = new Mutex(false, mutexName)) + using (var remote = RemoteExecutor.Invoke(otherProcess, mutexName, fileName)) + { + SpinWait.SpinUntil( + () => + { + mutex.CheckedWait(); + try + { return File.Exists(fileName) && int.TryParse(File.ReadAllText(fileName), out _); } + finally { mutex.ReleaseMutex(); } + }, + ThreadTestHelpers.UnexpectedTimeoutMilliseconds); + + IncrementValueInFileNTimes(mutex, fileName, 10); + } - Assert.Equal(20, int.Parse(File.ReadAllText(fileName))); - }); + Assert.Equal(20, int.Parse(File.ReadAllText(fileName))); + }); + } + catch (Exception ex) when (File.Exists(fileName)) + { + throw new AggregateException($"File contents: {File.ReadAllText(fileName)}", ex); + } } private static void IncrementValueInFileNTimes(Mutex mutex, string fileName, int n) @@ -451,6 +465,103 @@ private static void IncrementValueInFileNTimes(Mutex mutex, string fileName, int } } + [Fact] + public void NamedMutex_ThreadExitDisposeRaceTest() + { + var mutexName = Guid.NewGuid().ToString("N"); + + for (int i = 0; i < 1000; ++i) + { + var m = new Mutex(false, mutexName); + var startParallelTest = new ManualResetEvent(false); + + var t0Ready = new AutoResetEvent(false); + Thread t0 = ThreadTestHelpers.CreateGuardedThread(out Action waitForT0, () => + { + m.CheckedWait(); + t0Ready.Set(); + startParallelTest.CheckedWait(); // after this, exit T0 + }); + t0.IsBackground = true; + + var t1Ready = new AutoResetEvent(false); + Thread t1 = ThreadTestHelpers.CreateGuardedThread(out Action waitForT1, () => + { + using (var m2 = Mutex.OpenExisting(mutexName)) + { + m.Dispose(); + t1Ready.Set(); + startParallelTest.CheckedWait(); // after this, close last handle to named mutex, exit T1 + } + }); + t1.IsBackground = true; + + t0.Start(); + t0Ready.CheckedWait(); // wait for T0 to acquire the mutex + t1.Start(); + t1Ready.CheckedWait(); // wait for T1 to open the existing mutex in a new mutex object and dispose one of the two + + // Release both threads at the same time. T0 will be exiting the thread, perhaps trying to abandon the mutex + // that is still locked by it. In parallel, T1 will be disposing the last mutex instance, which would try to + // destroy the mutex. + startParallelTest.Set(); + waitForT0(); + waitForT1(); + + // Create a new mutex object with the same name and acquire it. There can be a delay between Thread.Join() above + // returning and for T0 to abandon its mutex, keep trying to also verify that the mutex object is actually + // destroyed and created new again. + SpinWait.SpinUntil(() => + { + using (m = new Mutex(true, mutexName, out bool createdNew)) + { + if (createdNew) + { + m.ReleaseMutex(); + } + return createdNew; + } + }); + } + } + + [Fact] + public void NamedMutex_DisposeWhenLockedRaceTest() + { + var mutexName = Guid.NewGuid().ToString("N"); + var mutex2Name = mutexName + "_2"; + + var waitsForThread = new Action[Environment.ProcessorCount]; + for (int i = 0; i < waitsForThread.Length; ++i) + { + var t = ThreadTestHelpers.CreateGuardedThread(out waitsForThread[i], () => + { + for (int i = 0; i < 1000; ++i) + { + // Create or open two mutexes with different names, acquire the lock if created, and dispose without + // releasing the lock. What may occasionally happen is, one thread T0 will acquire the lock, another + // thread T1 will open the same mutex, T0 will dispose its mutex while the lock is held, and T1 will + // then release the last reference to the mutex. On some implementations T1 may not be able to destroy + // the mutex when it is still locked by T0, or there may be potential for races in the sequence. This + // test only looks for errors from race conditions. + using (var mutex = new Mutex(true, mutexName)) + { + } + using (var mutex = new Mutex(true, mutex2Name)) + { + } + } + }); + t.IsBackground = true; + t.Start(); + } + + foreach (var waitForThread in waitsForThread) + { + waitForThread(); + } + } + public static TheoryData GetValidNames() { var names = new TheoryData() { Guid.NewGuid().ToString("N") }; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionScope.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionScope.cs index 71e2285e792a5..acd51f7c186fc 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionScope.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionScope.cs @@ -211,7 +211,7 @@ TransactionScopeAsyncFlowOption asyncFlowOption // If the requested IsolationLevel is stronger than that of the specified transaction, throw. if ((IsolationLevel.Unspecified != transactionOptions.IsolationLevel) && (_expectedCurrent.IsolationLevel != transactionOptions.IsolationLevel)) { - throw new ArgumentException(SR.TransactionScopeIsolationLevelDifferentFromTransaction, "transactionOptions.IsolationLevel"); + throw new ArgumentException(SR.TransactionScopeIsolationLevelDifferentFromTransaction, nameof(transactionOptions)); } } } @@ -293,7 +293,7 @@ TransactionScopeAsyncFlowOption asyncFlowOption // If the requested IsolationLevel is stronger than that of the specified transaction, throw. if ((IsolationLevel.Unspecified != transactionOptions.IsolationLevel) && (_expectedCurrent.IsolationLevel != transactionOptions.IsolationLevel)) { - throw new ArgumentException(SR.TransactionScopeIsolationLevelDifferentFromTransaction, "transactionOptions.IsolationLevel"); + throw new ArgumentException(SR.TransactionScopeIsolationLevelDifferentFromTransaction, nameof(transactionOptions)); } } } diff --git a/src/libraries/System.Utf8String.Experimental/src/System.Utf8String.Experimental.csproj b/src/libraries/System.Utf8String.Experimental/src/System.Utf8String.Experimental.csproj index d40ffab549bb0..8c12e12713963 100644 --- a/src/libraries/System.Utf8String.Experimental/src/System.Utf8String.Experimental.csproj +++ b/src/libraries/System.Utf8String.Experimental/src/System.Utf8String.Experimental.csproj @@ -1,13 +1,16 @@ true + $(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix;netstandard2.0;netstandard2.1;netcoreapp3.0 + enable + $(DefineContants);FEATURE_UTF8STRING + + + $(NoWarn);CS3019;CS0162 true - netstandard2.0;netstandard2.1;netcoreapp3.0;$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix - enable - $(DefineContants);FEATURE_UTF8STRING diff --git a/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs b/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs index 91059ddbeb3a5..38e129a08022c 100644 --- a/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs +++ b/src/libraries/System.Utf8String.Experimental/src/System/Runtime/Intrinsics/Intrinsics.Shims.cs @@ -4,6 +4,16 @@ namespace System.Runtime.Intrinsics { + internal static class Vector64 + { + public static Vector64 Create(ulong value) => throw new PlatformNotSupportedException(); + public static Vector64 AsByte(this Vector64 vector) where T : struct => throw new PlatformNotSupportedException(); + } + internal readonly struct Vector64 + where T : struct + { + } + internal static class Vector128 { public static Vector128 Create(short value) => throw new PlatformNotSupportedException(); @@ -15,6 +25,7 @@ internal static class Vector128 public static Vector128 AsUInt32(this Vector128 vector) where T : struct => throw new PlatformNotSupportedException(); public static Vector128 AsUInt64(this Vector128 vector) where T : struct => throw new PlatformNotSupportedException(); public static T GetElement(this Vector128 vector, int index) where T : struct => throw new PlatformNotSupportedException(); + public static T ToScalar(this Vector64 vector) where T : struct => throw new PlatformNotSupportedException(); } internal readonly struct Vector128 where T : struct @@ -130,4 +141,13 @@ public abstract class Arm64 public static int LeadingZeroCount(uint value) => throw new PlatformNotSupportedException(); public static uint ReverseElementBits(uint value) => throw new PlatformNotSupportedException(); } + + internal abstract class AdvSimd : ArmBase + { + public new abstract class Arm64 : ArmBase.Arm64 + { + public static Vector64 AddAcross(Vector64 value) => throw new PlatformNotSupportedException(); + } + public static Vector64 PopCount(Vector64 value) => throw new PlatformNotSupportedException(); + } } diff --git a/src/libraries/System.Utf8String.Experimental/tests/System.Utf8String.Experimental.Tests.csproj b/src/libraries/System.Utf8String.Experimental/tests/System.Utf8String.Experimental.Tests.csproj index 92e4d04476e3c..73e52762cdf01 100644 --- a/src/libraries/System.Utf8String.Experimental/tests/System.Utf8String.Experimental.Tests.csproj +++ b/src/libraries/System.Utf8String.Experimental/tests/System.Utf8String.Experimental.Tests.csproj @@ -42,7 +42,7 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Windows.Extensions/ref/System.Windows.Extensions.csproj b/src/libraries/System.Windows.Extensions/ref/System.Windows.Extensions.csproj index ac9792c7a5d07..ebbd3e46f7670 100644 --- a/src/libraries/System.Windows.Extensions/ref/System.Windows.Extensions.csproj +++ b/src/libraries/System.Windows.Extensions/ref/System.Windows.Extensions.csproj @@ -1,6 +1,6 @@ - netcoreapp3.0;$(NetCoreAppCurrent) + $(NetCoreAppCurrent);netcoreapp3.0 true diff --git a/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj b/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj index 43c366dda9fac..ea77d6793f77f 100644 --- a/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj +++ b/src/libraries/System.Windows.Extensions/src/System.Windows.Extensions.csproj @@ -2,7 +2,7 @@ SR.PlatformNotSupported_System_Windows_Extensions true - netcoreapp3.0-Windows_NT;netcoreapp3.0;$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent) + $(NetCoreAppCurrent)-Windows_NT;netcoreapp3.0-Windows_NT;netcoreapp3.0;$(NetCoreAppCurrent) true diff --git a/src/libraries/System.Windows.Extensions/src/System/Drawing/FontConverter.cs b/src/libraries/System.Windows.Extensions/src/System/Drawing/FontConverter.cs index aaea6553cf598..af1308e860eac 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Drawing/FontConverter.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Drawing/FontConverter.cs @@ -173,7 +173,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c catch { // Exception from converter is too generic. - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, font, $"name{separator} size[units[{separator} style=style1[{separator} style2{separator} ...]]]"), nameof(sizeStr)); + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, font, $"name{separator} size[units[{separator} style=style1[{separator} style2{separator} ...]]]"), nameof(value)); } } diff --git a/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs b/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs index 69d474b8803a1..ae9cd72ae2e24 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs @@ -489,7 +489,7 @@ private async Task CopyStreamAsync(CancellationToken cancellationToken) _streamData = new byte[BlockSize]; - int readBytes = await _stream.ReadAsync(_streamData, _currentPos, BlockSize, cancellationToken).ConfigureAwait(false); + int readBytes = await _stream.ReadAsync(_streamData.AsMemory(_currentPos, BlockSize), cancellationToken).ConfigureAwait(false); int totalBytes = readBytes; while (readBytes > 0) @@ -501,7 +501,7 @@ private async Task CopyStreamAsync(CancellationToken cancellationToken) Array.Copy(_streamData, newData, _streamData.Length); _streamData = newData; } - readBytes = await _stream.ReadAsync(_streamData, _currentPos, BlockSize, cancellationToken).ConfigureAwait(false); + readBytes = await _stream.ReadAsync(_streamData.AsMemory(_currentPos, BlockSize), cancellationToken).ConfigureAwait(false); totalBytes += readBytes; } diff --git a/src/libraries/System.Windows.Extensions/tests/System/Drawing/FontConverterTests.cs b/src/libraries/System.Windows.Extensions/tests/System/Drawing/FontConverterTests.cs index 02a01346d208f..951ccfaeb9193 100644 --- a/src/libraries/System.Windows.Extensions/tests/System/Drawing/FontConverterTests.cs +++ b/src/libraries/System.Windows.Extensions/tests/System/Drawing/FontConverterTests.cs @@ -131,7 +131,7 @@ private static bool EmptyFontPresent public static TheoryData ArgumentExceptionFontConverterData() => new TheoryData() { { $"Courier New{s_Separator} 11 px{s_Separator} type=Bold{s_Separator} Italic", "units", null }, - { $"Courier New{s_Separator} {s_Separator} Style=Bold", "sizeStr", null }, + { $"Courier New{s_Separator} {s_Separator} Style=Bold", "value", null }, { $"Courier New{s_Separator} 11{s_Separator} Style=", "value", null }, { $"Courier New{s_Separator} 11{s_Separator} Style=RandomEnum", null, null }, { $"Arial{s_Separator} 10{s_Separator} style=bold{s_Separator}", "value", null }, diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/Microsoft.NETCore.Platforms.Future.pkgproj b/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/Microsoft.NETCore.Platforms.Future.pkgproj deleted file mode 100644 index be13ea21ac232..0000000000000 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/Microsoft.NETCore.Platforms.Future.pkgproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - true - - false - - - - - - lib/netstandard1.0 - - - - - - diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/Microsoft.NETCore.Platforms.Future.proj b/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/Microsoft.NETCore.Platforms.Future.proj deleted file mode 100644 index 24c9f63af136b..0000000000000 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/Microsoft.NETCore.Platforms.Future.proj +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/readme.md b/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/readme.md deleted file mode 100644 index 1e8e216fd6409..0000000000000 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/readme.md +++ /dev/null @@ -1 +0,0 @@ -see ..\Microsoft.NETCore.Platforms\readme.md \ No newline at end of file diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtime.compatibility.json b/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtime.compatibility.json deleted file mode 100644 index 278b1bcc7e614..0000000000000 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtime.compatibility.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "unix-wasm": [ - "unix-wasm" - ], - "webassembly": [ - "webassembly", - "unix" - ], - "webassembly-wasm": [ - "webassembly-wasm", - "webassembly", - "unix-wasm", - "unix" - ] -} \ No newline at end of file diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtime.json b/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtime.json deleted file mode 100644 index 07393a3db820f..0000000000000 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtime.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "runtimes": { - "unix-wasm": { - "#import": [] - }, - "webassembly": { - "#import": [ - "unix" - ] - }, - "webassembly-wasm": { - "#import": [ - "webassembly", - "unix-wasm" - ] - } - } -} \ No newline at end of file diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtimeGroups.props b/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtimeGroups.props deleted file mode 100644 index ff4c96a23b829..0000000000000 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms.Future/runtimeGroups.props +++ /dev/null @@ -1,26 +0,0 @@ - - - - wasm - - unix - - - unix - wasm - - - - - - - - - diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json b/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json index ecadced6e121d..ca8d8b4493f6a 100644 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json +++ b/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json @@ -92,6 +92,47 @@ "any", "base" ], + "alpine.3.12": [ + "alpine.3.12", + "alpine.3.11", + "alpine.3.10", + "alpine.3.9", + "alpine.3.8", + "alpine.3.7", + "alpine.3.6", + "alpine", + "linux-musl", + "linux", + "unix", + "any", + "base" + ], + "alpine.3.12-x64": [ + "alpine.3.12-x64", + "alpine.3.12", + "alpine.3.11-x64", + "alpine.3.11", + "alpine.3.10-x64", + "alpine.3.10", + "alpine.3.9-x64", + "alpine.3.9", + "alpine.3.8-x64", + "alpine.3.8", + "alpine.3.7-x64", + "alpine.3.7", + "alpine.3.6-x64", + "alpine.3.6", + "alpine-x64", + "alpine", + "linux-musl-x64", + "linux-musl", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "alpine.3.6": [ "alpine.3.6", "alpine", @@ -1125,6 +1166,18 @@ "any", "base" ], + "centos-arm64": [ + "centos-arm64", + "centos", + "rhel-arm64", + "rhel", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], "centos-x64": [ "centos-x64", "centos", @@ -1173,6 +1226,22 @@ "any", "base" ], + "centos.8-arm64": [ + "centos.8-arm64", + "centos.8", + "centos-arm64", + "rhel.8-arm64", + "centos", + "rhel.8", + "rhel-arm64", + "rhel", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], "centos.8-x64": [ "centos.8-x64", "centos.8", @@ -1189,6 +1258,48 @@ "any", "base" ], + "centos.9": [ + "centos.9", + "centos", + "rhel.9", + "rhel", + "linux", + "unix", + "any", + "base" + ], + "centos.9-arm64": [ + "centos.9-arm64", + "centos.9", + "centos-arm64", + "rhel.9-arm64", + "centos", + "rhel.9", + "rhel-arm64", + "rhel", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "centos.9-x64": [ + "centos.9-x64", + "centos.9", + "centos-x64", + "rhel.9-x64", + "centos", + "rhel.9", + "rhel-x64", + "rhel", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "debian": [ "debian", "linux", @@ -1829,6 +1940,38 @@ "any", "base" ], + "fedora.34": [ + "fedora.34", + "fedora", + "linux", + "unix", + "any", + "base" + ], + "fedora.34-arm64": [ + "fedora.34-arm64", + "fedora.34", + "fedora-arm64", + "fedora", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "fedora.34-x64": [ + "fedora.34-x64", + "fedora.34", + "fedora-x64", + "fedora", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "freebsd": [ "freebsd", "unix", @@ -1950,6 +2093,14 @@ "any", "base" ], + "ios-x86": [ + "ios-x86", + "ios", + "unix-x86", + "unix", + "any", + "base" + ], "ios.10": [ "ios.10", "ios.9", @@ -2001,6 +2152,20 @@ "any", "base" ], + "ios.10-x86": [ + "ios.10-x86", + "ios.10", + "ios.9-x86", + "ios.9", + "ios.8-x86", + "ios.8", + "ios-x86", + "ios", + "unix-x86", + "unix", + "any", + "base" + ], "ios.11": [ "ios.11", "ios.10", @@ -2179,6 +2344,16 @@ "any", "base" ], + "ios.8-x86": [ + "ios.8-x86", + "ios.8", + "ios-x86", + "ios", + "unix-x86", + "unix", + "any", + "base" + ], "ios.9": [ "ios.9", "ios.8", @@ -2223,6 +2398,18 @@ "any", "base" ], + "ios.9-x86": [ + "ios.9-x86", + "ios.9", + "ios.8-x86", + "ios.8", + "ios-x86", + "ios", + "unix-x86", + "unix", + "any", + "base" + ], "linux": [ "linux", "unix", @@ -3811,6 +3998,38 @@ "any", "base" ], + "rhel.9": [ + "rhel.9", + "rhel", + "linux", + "unix", + "any", + "base" + ], + "rhel.9-arm64": [ + "rhel.9-arm64", + "rhel.9", + "rhel-arm64", + "rhel", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "rhel.9-x64": [ + "rhel.9-x64", + "rhel.9", + "rhel-x64", + "rhel", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "sles": [ "sles", "linux", @@ -5156,6 +5375,266 @@ "any", "base" ], + "ubuntu.20.04": [ + "ubuntu.20.04", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.20.04-arm": [ + "ubuntu.20.04-arm", + "ubuntu.20.04", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.20.04-arm64": [ + "ubuntu.20.04-arm64", + "ubuntu.20.04", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.20.04-x64": [ + "ubuntu.20.04-x64", + "ubuntu.20.04", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.20.04-x86": [ + "ubuntu.20.04-x86", + "ubuntu.20.04", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "ubuntu.20.10": [ + "ubuntu.20.10", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.20.10-arm": [ + "ubuntu.20.10-arm", + "ubuntu.20.10", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.20.10-arm64": [ + "ubuntu.20.10-arm64", + "ubuntu.20.10", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.20.10-x64": [ + "ubuntu.20.10-x64", + "ubuntu.20.10", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.20.10-x86": [ + "ubuntu.20.10-x86", + "ubuntu.20.10", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "ubuntu.21.04": [ + "ubuntu.21.04", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.21.04-arm": [ + "ubuntu.21.04-arm", + "ubuntu.21.04", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.21.04-arm64": [ + "ubuntu.21.04-arm64", + "ubuntu.21.04", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.21.04-x64": [ + "ubuntu.21.04-x64", + "ubuntu.21.04", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.21.04-x86": [ + "ubuntu.21.04-x86", + "ubuntu.21.04", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], + "ubuntu.21.10": [ + "ubuntu.21.10", + "ubuntu", + "debian", + "linux", + "unix", + "any", + "base" + ], + "ubuntu.21.10-arm": [ + "ubuntu.21.10-arm", + "ubuntu.21.10", + "ubuntu-arm", + "ubuntu", + "debian-arm", + "debian", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "ubuntu.21.10-arm64": [ + "ubuntu.21.10-arm64", + "ubuntu.21.10", + "ubuntu-arm64", + "ubuntu", + "debian-arm64", + "debian", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "ubuntu.21.10-x64": [ + "ubuntu.21.10-x64", + "ubuntu.21.10", + "ubuntu-x64", + "ubuntu", + "debian-x64", + "debian", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], + "ubuntu.21.10-x86": [ + "ubuntu.21.10-x86", + "ubuntu.21.10", + "ubuntu-x86", + "ubuntu", + "debian-x86", + "debian", + "linux-x86", + "linux", + "unix-x86", + "unix", + "any", + "base" + ], "unix": [ "unix", "any", diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.json b/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.json index 02151ad0b20c6..aa9f28ca15d33 100644 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.json +++ b/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.json @@ -33,6 +33,17 @@ "alpine.3.10-x64" ] }, + "alpine.3.12": { + "#import": [ + "alpine.3.11" + ] + }, + "alpine.3.12-x64": { + "#import": [ + "alpine.3.12", + "alpine.3.11-x64" + ] + }, "alpine.3.6": { "#import": [ "alpine" @@ -406,6 +417,12 @@ "rhel" ] }, + "centos-arm64": { + "#import": [ + "centos", + "rhel-arm64" + ] + }, "centos-x64": { "#import": [ "centos", @@ -431,6 +448,13 @@ "rhel.8" ] }, + "centos.8-arm64": { + "#import": [ + "centos.8", + "centos-arm64", + "rhel.8-arm64" + ] + }, "centos.8-x64": { "#import": [ "centos.8", @@ -438,6 +462,26 @@ "rhel.8-x64" ] }, + "centos.9": { + "#import": [ + "centos", + "rhel.9" + ] + }, + "centos.9-arm64": { + "#import": [ + "centos.9", + "centos-arm64", + "rhel.9-arm64" + ] + }, + "centos.9-x64": { + "#import": [ + "centos.9", + "centos-x64", + "rhel.9-x64" + ] + }, "debian": { "#import": [ "linux" @@ -782,6 +826,23 @@ "fedora-x64" ] }, + "fedora.34": { + "#import": [ + "fedora" + ] + }, + "fedora.34-arm64": { + "#import": [ + "fedora.34", + "fedora-arm64" + ] + }, + "fedora.34-x64": { + "#import": [ + "fedora.34", + "fedora-x64" + ] + }, "freebsd": { "#import": [ "unix" @@ -860,6 +921,12 @@ "unix-x64" ] }, + "ios-x86": { + "#import": [ + "ios", + "unix-x86" + ] + }, "ios.10": { "#import": [ "ios.9" @@ -883,6 +950,12 @@ "ios.9-x64" ] }, + "ios.10-x86": { + "#import": [ + "ios.10", + "ios.9-x86" + ] + }, "ios.11": { "#import": [ "ios.10" @@ -957,6 +1030,12 @@ "ios-x64" ] }, + "ios.8-x86": { + "#import": [ + "ios.8", + "ios-x86" + ] + }, "ios.9": { "#import": [ "ios.8" @@ -980,6 +1059,12 @@ "ios.8-x64" ] }, + "ios.9-x86": { + "#import": [ + "ios.9", + "ios.8-x86" + ] + }, "linux": { "#import": [ "unix" @@ -1633,6 +1718,23 @@ "rhel.8.0-x64" ] }, + "rhel.9": { + "#import": [ + "rhel" + ] + }, + "rhel.9-arm64": { + "#import": [ + "rhel.9", + "rhel-arm64" + ] + }, + "rhel.9-x64": { + "#import": [ + "rhel.9", + "rhel-x64" + ] + }, "sles": { "#import": [ "linux" @@ -2244,6 +2346,122 @@ "ubuntu-x86" ] }, + "ubuntu.20.04": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.20.04-arm": { + "#import": [ + "ubuntu.20.04", + "ubuntu-arm" + ] + }, + "ubuntu.20.04-arm64": { + "#import": [ + "ubuntu.20.04", + "ubuntu-arm64" + ] + }, + "ubuntu.20.04-x64": { + "#import": [ + "ubuntu.20.04", + "ubuntu-x64" + ] + }, + "ubuntu.20.04-x86": { + "#import": [ + "ubuntu.20.04", + "ubuntu-x86" + ] + }, + "ubuntu.20.10": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.20.10-arm": { + "#import": [ + "ubuntu.20.10", + "ubuntu-arm" + ] + }, + "ubuntu.20.10-arm64": { + "#import": [ + "ubuntu.20.10", + "ubuntu-arm64" + ] + }, + "ubuntu.20.10-x64": { + "#import": [ + "ubuntu.20.10", + "ubuntu-x64" + ] + }, + "ubuntu.20.10-x86": { + "#import": [ + "ubuntu.20.10", + "ubuntu-x86" + ] + }, + "ubuntu.21.04": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.21.04-arm": { + "#import": [ + "ubuntu.21.04", + "ubuntu-arm" + ] + }, + "ubuntu.21.04-arm64": { + "#import": [ + "ubuntu.21.04", + "ubuntu-arm64" + ] + }, + "ubuntu.21.04-x64": { + "#import": [ + "ubuntu.21.04", + "ubuntu-x64" + ] + }, + "ubuntu.21.04-x86": { + "#import": [ + "ubuntu.21.04", + "ubuntu-x86" + ] + }, + "ubuntu.21.10": { + "#import": [ + "ubuntu" + ] + }, + "ubuntu.21.10-arm": { + "#import": [ + "ubuntu.21.10", + "ubuntu-arm" + ] + }, + "ubuntu.21.10-arm64": { + "#import": [ + "ubuntu.21.10", + "ubuntu-arm64" + ] + }, + "ubuntu.21.10-x64": { + "#import": [ + "ubuntu.21.10", + "ubuntu-x64" + ] + }, + "ubuntu.21.10-x86": { + "#import": [ + "ubuntu.21.10", + "ubuntu-x86" + ] + }, "unix": { "#import": [ "any" diff --git a/src/libraries/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props b/src/libraries/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props index fd339ac8c0df7..1cb561273e87a 100644 --- a/src/libraries/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props +++ b/src/libraries/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props @@ -16,7 +16,7 @@ linux-musl x64 - 3.6;3.7;3.8;3.9;3.10;3.11 + 3.6;3.7;3.8;3.9;3.10;3.11;3.12 @@ -38,7 +38,14 @@ rhel x64 - 7;8 + 7 + true + false + + + rhel + x64;arm64 + 8;9 true false @@ -53,7 +60,7 @@ linux x64;arm64 - 23;24;25;26;27;28;29;30;31;32;33 + 23;24;25;26;27;28;29;30;31;32;33;34 false @@ -64,7 +71,7 @@ unix - arm + arm;x86 8;9;10 @@ -140,6 +147,11 @@ x64;arm64 8;8.0;8.1 + + linux + x64;arm64 + 9 + linux @@ -168,7 +180,7 @@ debian x64;x86;arm;arm64 - 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10 + 16.04;16.10;17.04;17.10;18.04;18.10;19.04;19.10;20.04;20.10;21.04;21.10 false diff --git a/src/libraries/pkg/baseline/packageIndex.json b/src/libraries/pkg/baseline/packageIndex.json index 5a90065e0e664..d3fffa85b3feb 100644 --- a/src/libraries/pkg/baseline/packageIndex.json +++ b/src/libraries/pkg/baseline/packageIndex.json @@ -543,12 +543,14 @@ "3.1.0", "3.1.1", "3.1.2", - "3.1.3" + "3.1.3", + "3.1.4" ], "BaselineVersion": "5.0.0", "InboxOn": {}, "AssemblyVersionInPackageVersion": { - "3.1.3.0": "5.0.0", + "3.1.3.0": "3.1.3", + "3.1.4.0": "3.1.4", "5.0.0.0": "5.0.0" } }, diff --git a/src/libraries/pkg/descriptions.json b/src/libraries/pkg/descriptions.json index 87b23a37dad8c..6d2b58594de82 100644 --- a/src/libraries/pkg/descriptions.json +++ b/src/libraries/pkg/descriptions.json @@ -260,11 +260,6 @@ "Description": "Provides runtime information required to resolve target framework, platform, and runtime specific implementations of .NETCore packages.", "CommonTypes": [] }, - { - "Name": "Microsoft.NETCore.Platforms.Future", - "Description": "Provides runtime information required to resolve target framework, platform, and runtime specific implementations of .NETCore packages. This package represents future platforms not yet supported in .NETCore stable release and is subject to change.", - "CommonTypes": [] - }, { "Name": "Microsoft.NETCore.Portable.Compatibility", "Description": "Enables compatibility with portable libraries targeting previous .NET releases like .NET Framework 4.0 and Silverlight.\nThis package supports retargeting references to classic reference assemblies (mscorlib.dll, system.dll, etc) to new contract assemblies (System.Runtime.dll, System.IO, etc). It does this in a pay-for-play way to prevent consuming assemblies from having to reference all of the contracts that happen to overlap with mscorlib. As such, when using this package you may encounter errors like\n\terror CS0012: The type 'WebRequest' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Net.Requests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.\nTo resolve these errors install the package with the same name as the missing assembly.", diff --git a/src/libraries/pretest.proj b/src/libraries/pretest.proj index eeac3ea516223..7b8e5f9f9f38b 100644 --- a/src/libraries/pretest.proj +++ b/src/libraries/pretest.proj @@ -3,13 +3,22 @@ BuildAllProjects=true - $(TargetFrameworkIdentifier) + + + + + true + true + + + + + + @@ -67,22 +81,22 @@ AfterTargets="RestoreTestHost"> RuntimeList.xml - $(NETCoreAppRuntimePackPath)/data/$(FrameworkListFilename) + $(RuntimePackDir)/data/$(FrameworkListFilename) - <_runtimePackLibFiles Include="$(NETCoreAppRuntimePackLibPath)*.*"> - $(RuntimePackTargetFrameworkPath)/lib/$(NETCoreAppFramework) + <_runtimePackLibFiles Include="$(RuntimePackLibDir)*.*"> + $(RuntimePackTargetFrameworkPath)/lib/$(NetCoreAppCurrent) true - <_runtimePackNativeFiles Include="$(NETCoreAppRuntimePackNativePath)*.*"> + <_runtimePackNativeFiles Include="$(RuntimePackNativeDir)*.*"> $(RuntimePackTargetFrameworkPath)/native true - - - + + + diff --git a/src/libraries/restore/Directory.Build.props b/src/libraries/restore/Directory.Build.props index 059f4b48d8ca2..359dfd63da6af 100644 --- a/src/libraries/restore/Directory.Build.props +++ b/src/libraries/restore/Directory.Build.props @@ -2,10 +2,13 @@ - + + $([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)', '$(TargetFramework)-$(TargetFrameworkSuffix)-$(Configuration)')) + $([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)', '$(TargetFramework)-$(Configuration)')) $(IntermediateOutputPath) $(RestoreOutputPath)/project.assets.json $(IntermediateOutputPath) + true false netstandard2.0 @@ -18,4 +21,4 @@ Build - \ No newline at end of file + diff --git a/src/libraries/restore/runtime/runtime.depproj b/src/libraries/restore/runtime/runtime.depproj index 9fb53d1923b9d..10fc51ca95027 100644 --- a/src/libraries/restore/runtime/runtime.depproj +++ b/src/libraries/restore/runtime/runtime.depproj @@ -1,14 +1,8 @@  $(PackageRID) - - $(ToolRuntimeRID) $(NoWarn);NU1603;NU1605 true - $(TargetOS) - $(Configuration) - $(TargetOS) - $(Configuration) false netcoreapp3.0-Windows_NT;netcoreapp3.0-Unix;$(netcoreappCurrent)-Windows_NT;$(netcoreappCurrent)-Unix diff --git a/src/libraries/sendtohelix.proj b/src/libraries/sendtohelix.proj index b62ca7e716148..aba5711af7884 100644 --- a/src/libraries/sendtohelix.proj +++ b/src/libraries/sendtohelix.proj @@ -76,6 +76,10 @@ <_RuntimeInputs Include="$(TestHostRootPath)**/*.dll" /> + + + + true $([MSBuild]::NormalizeDirectory('$(ArtifactsObjDir)', '$(OutDirName)')) $(BaseIntermediateOutputPath)$(TargetFramework)-$(Configuration) - $(TargetOS) - $(TargetOS) $(NetCoreAppCurrent) diff --git a/src/libraries/src.proj b/src/libraries/src.proj index b3b5f8504fc6e..91225466df011 100644 --- a/src/libraries/src.proj +++ b/src/libraries/src.proj @@ -2,6 +2,7 @@ BuildAllProjects=true + BuildWasmRuntimes @@ -24,8 +25,11 @@ + + + AfterTargets="Build" + DependsOnTargets="$(NativeBinPlaceDependsOnTargets)"> @@ -45,5 +49,4 @@ Projects="@(ApiCompatProject)" Properties="$(TraversalGlobalProperties)" /> - diff --git a/src/mono/Directory.Build.props b/src/mono/Directory.Build.props index 63208b1a89c26..baa3cfc4c5dd1 100644 --- a/src/mono/Directory.Build.props +++ b/src/mono/Directory.Build.props @@ -39,7 +39,7 @@ true true true - true + true true true true @@ -101,4 +101,13 @@ $(ArtifactsObjDir)mono/$(PlatformConfigPathPart)/ $(MonoObjDir)llvm + + + + $([MSBuild]::NormalizeDirectory('$(RepoTasksDir)', 'mobile.tasks', 'AppleAppBuilder')) + $([MSBuild]::NormalizeDirectory('$(LibrariesProjectRoot)', 'Common', tests, 'AppleTestRunner')) + $([MSBuild]::NormalizeDirectory('$(RepoTasksDir)', 'mobile.tasks', 'AndroidAppBuilder')) + $([MSBuild]::NormalizeDirectory('$(LibrariesProjectRoot)', 'Common', tests, 'AndroidTestRunner')) + $([MSBuild]::NormalizeDirectory('$(RepoTasksDir)', 'mobile.tasks', 'AotCompilerTask')) + diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index b5754a613a877..e89b59c5f7100 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -1647,6 +1647,9 @@ /* Enable private types checked build */ #cmakedefine ENABLE_CHECKED_BUILD_CRASH_REPORTING 1 +/* Enable EventPipe library support */ +#cmakedefine ENABLE_PERFTRACING 1 + /* Define to 1 if you have /usr/include/malloc.h. */ #cmakedefine HAVE_USR_INCLUDE_MALLOC_H 1 diff --git a/src/mono/configure.ac b/src/mono/configure.ac index 42ceddb528e27..6eb961f9dda00 100644 --- a/src/mono/configure.ac +++ b/src/mono/configure.ac @@ -943,6 +943,16 @@ if test x$with_core = xonly; then fi AM_CONDITIONAL(ENABLE_NETCORE, test x$with_core = xonly) +if test x$with_core = xonly; then + if test -f $srcdir/mono/eventpipe/ep.h; then + enable_perftracing=yes + fi + if test x$enable_perftracing = xyes; then + AC_DEFINE(ENABLE_PERFTRACING,1,[Enables support for eventpipe library]) + fi +fi +AM_CONDITIONAL(ENABLE_PERFTRACING, test x$enable_perftracing = xyes) + # # A sanity check to catch cases where the package was unpacked # with an ancient tar program (Solaris) @@ -3921,6 +3931,8 @@ else AC_CHECK_LIB(advapi32, main, LIBS="$LIBS -ladvapi32", AC_ERROR(bad mingw install?)) AC_CHECK_LIB(version, main, LIBS="$LIBS -lversion", AC_ERROR(bad mingw install?)) + AC_CHECK_TYPES([struct sockaddr_in6], [AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6)], , [#include ]) + dnl ********************************* dnl *** Check for struct ip_mreqn *** dnl ********************************* @@ -6795,6 +6807,46 @@ AC_COMPILE_IFELSE( AC_MSG_RESULT(no) ]) +# for icu shim +ICU_SHIM_PATH=. +if test x$with_core = xonly; then + if test x$cross_compiling = xno; then + AC_CHECK_FILE($srcdir/../libraries/Native/Unix/System.Globalization.Native/pal_icushim.h, [have_shim_globalization=yes], [have_shim_globalization=no]) + fi + if test x$have_shim_globalization = xyes || test x$cross_compiling = xyes; then + ICU_SHIM_PATH=../../../libraries/Native/Unix/System.Globalization.Native + if test x$target_osx = xyes; then + ORIG_CPPFLAGS=$CPPFLAGS + # adding icu path to pkg_config_path + PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig + export PKG_CONFIG_PATH + CPPFLAGS="`pkg-config --cflags-only-I icu-uc`" + AC_CHECK_LIB(icucore, ucol_open, LIBS=$LIBS, + [AC_MSG_ERROR([Cannot find libicucore, skipping build for System.Globalization.Native. .NET globalization is not expected to function.])]) + AC_CHECK_HEADER(unicode/utypes.h, [have_sys_icu=yes], [have_sys_icu=no]) + if test x$have_sys_icu = xyes; then + ICU_CFLAGS="$CPPFLAGS -DOSX_ICU_LIBRARY_PATH=AS_ESCAPE(\"/usr/lib/libicucore.dylib\", '\"') -DTARGET_UNIX -DU_DISABLE_RENAMING -Wno-reserved-id-macro -Wno-documentation -Wno-documentation-unknown-command -Wno-switch-enum -Wno-covered-switch-default -Wno-covered-switch-default -Wno-extra-semi-stmt -Wno-unknown-warning-option -Wno-deprecated-declarations" + fi + CPPFLAGS=$ORIG_CPPFLAGS + elif test x$platform_android = xyes; then + ICU_CFLAGS="-DHAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS -DHAVE_SET_MAX_VARIABLE -DTARGET_UNIX -DTARGET_ANDROID -Wno-reserved-id-macro -Wno-documentation -Wno-documentation-unknown-command -Wno-switch-enum -Wno-covered-switch-default -Wno-covered-switch-default -Wno-extra-semi-stmt -Wno-unknown-warning-option" + have_sys_icu=yes + elif test x$host_linux = xyes; then + AC_CHECK_LIB(icuuc, main, LIBS=$LIBS, + [AC_MSG_ERROR([Cannot find libicuuc, try installing libicu-dev (or the appropriate package for your platform).])]) + AC_CHECK_LIB(icui18n, main, LIBS=$LIBS, + [AC_MSG_ERROR([Cannot find libicui18n, try installing libicu-dev (or the appropriate package for your platform).])]) + AC_CHECK_HEADER(unicode/utypes.h, [have_sys_icu=yes], [have_sys_icu=no]) + if test x$have_sys_icu = xyes; then + ICU_CFLAGS="-DTARGET_UNIX -Wno-reserved-id-macro -Wno-documentation -Wno-documentation-unknown-command -Wno-switch-enum -Wno-covered-switch-default -Wno-covered-switch-default -Wno-extra-semi-stmt -Wno-unknown-warning-option" + fi + fi + AC_SUBST(ICU_CFLAGS) + fi +fi +AC_SUBST(ICU_SHIM_PATH) +AM_CONDITIONAL(HAVE_SYS_ICU, test x$have_sys_icu = xyes) + AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) diff --git a/src/mono/m4/mono-output.m4 b/src/mono/m4/mono-output.m4 index 40d72ea7d6d14..128c16f33633e 100644 --- a/src/mono/m4/mono-output.m4 +++ b/src/mono/m4/mono-output.m4 @@ -12,6 +12,8 @@ AC_DEFUN([AC_MONO_OUTPUT], [ mono/utils/Makefile mono/metadata/Makefile mono/zlib/Makefile + mono/eventpipe/Makefile + mono/eventpipe/test/Makefile mono/arch/Makefile mono/arch/x86/Makefile mono/arch/amd64/Makefile diff --git a/src/mono/mono.proj b/src/mono/mono.proj index dce9417cfff83..446b216b77c93 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -14,32 +14,30 @@ coreclr.dll libcoreclr.dylib libcoreclr.so - libmono.dylib - libmono.dylib + libmonosgen-2.0.dylib libmonosgen-2.0.so - libmono.a - libmono.a - libmonosgen-2.0.a - libmono.a - libmono.a + libmonosgen-2.0.a $(CoreClrFileName) + libmonosgen-2.0.a $(Configuration) $(Configuration) $(ArtifactsDir)tests\coreclr\$(TargetOS).$(Platform).$(CoreClrTestConfig)\Tests\Core_Root $(ArtifactsDir)bin\testhost\$(NetCoreAppCurrent)-$(TargetOS)-$(LibrariesTestConfig)-$(Platform)\ $(LibrariesTesthostRoot)shared\Microsoft.NETCore.App\$(ProductVersion)\ /Applications/Xcode.app/Contents/Developer - true - true + true + true true + $(MonoObjDir)cross\config.h + true - + - + @@ -69,10 +67,13 @@ - <_MonoCFLAGS Include="-O2" /> + <_MonoCFLAGS Include="-O2" Condition="'$(TargetsMobile)' != 'true'" /> + <_MonoCFLAGS Include="-Os" Condition="'$(TargetsMobile)' == 'true'" /> <_MonoCFLAGS Include="-g" /> + <_MonoCFLAGS Include="-Wl,-s" Condition="'$(TargetsAndroid)' == 'true'" /> - <_MonoCXXFLAGS Include="-O2" /> + <_MonoCXXFLAGS Include="-O2" Condition="'$(TargetsMobile)' != 'true'" /> + <_MonoCXXFLAGS Include="-Os" Condition="'$(TargetsMobile)' == 'true'" /> <_MonoCXXFLAGS Include="-g" /> @@ -133,6 +134,7 @@ <_MonoCFLAGS Condition="'$(Platform)' == 'arm64'" Include="-arch arm64" /> <_MonoCFLAGS Include="-isysroot $(XcodeDir)/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS$(tvOSVersion).sdk" /> <_MonoCFLAGS Include="-mtvos-version-min=$(tvOSVersionMin)" /> + <_MonoCFLAGS Include="-Werror=partial-availability" /> <_MonoCFLAGS Include="-Wl,-application_extension" /> <_MonoCFLAGS Include="-fexceptions" /> <_MonoCFLAGS Include="-fembed-bitcode" /> @@ -157,69 +159,11 @@ <_MonoCPPFLAGS Include="-DHAVE_LARGE_FILE_SUPPORT=1" /> <_MonoLDFLAGS Condition="'$(Platform)' == 'arm64'" Include="-arch arm64" /> - <_MonoLDFLAGS Include="-Wl,-no_weak_imports" /> + <_MonoLDFLAGS Include="-Wl,-bitcode_bundle" /> <_MonoLDFLAGS Include="-framework CoreFoundation" /> <_MonoLDFLAGS Include="-lobjc" /> <_MonoLDFLAGS Include="-lc++" /> - - - - <_MonoAotCrossConfigureParams Include="--host=x86_64-apple-darwin10" /> - <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'arm64'" Include="--target=aarch64-darwin" /> - <_MonoAotCrossConfigureParams Include="--with-cross-offsets=$(MonoObjDir)cross/offsets-$(Platform)-darwin.h" /> - <_MonoAotCrossConfigureParams Include="--with-core=only" /> - <_MonoAotCrossConfigureParams Include="--enable-maintainer-mode" /> - <_MonoAotCrossConfigureParams Include="--enable-compile-warnings" /> - <_MonoAotCrossConfigureParams Include="--prefix=$(MonoObjDir)cross/out" /> - <_MonoAotCrossConfigureParams Include="--disable-boehm" /> - <_MonoAotCrossConfigureParams Include="--disable-btls" /> - <_MonoAotCrossConfigureParams Include="--disable-iconv" /> - <_MonoAotCrossConfigureParams Include="--disable-libraries" /> - <_MonoAotCrossConfigureParams Include="--disable-mcs-build" /> - <_MonoAotCrossConfigureParams Include="--disable-nls" /> - <_MonoAotCrossConfigureParams Include="--enable-dtrace=no" /> - <_MonoAotCrossConfigureParams Include="--enable-icall-symbol-map" /> - <_MonoAotCrossConfigureParams Include="--enable-minimal=com,remoting" /> - <_MonoAotCrossConfigureParams Include="--enable-monotouch" /> - <_MonoAotCrossConfigureParams Include="--disable-crash-reporting" /> - <_MonoAotCrossConfigureParams Include="--with-llvm=$(MonoLLVMDir)" /> - - <_MonoAotCrossAC_VARS Include="ac_cv_func_shm_open_working_with_mmap=no" /> - - <_MonoAotCrossCFLAGS Include="-O2" /> - <_MonoAotCrossCFLAGS Include="-g" /> - <_MonoAotCrossCFLAGS Include="-isysroot $(XcodeDir)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(macOSVersion).sdk" /> - <_MonoAotCrossCFLAGS Include="-mmacosx-version-min=$(macOSVersionMin)" /> - <_MonoAotCrossCFLAGS Include="-Qunused-arguments" /> - <_MonoAotCrossCFLAGS Include="-m64" /> - - <_MonoAotCrossCXXFLAGS Include="-O2" /> - <_MonoAotCrossCXXFLAGS Include="-g" /> - <_MonoAotCrossCXXFLAGS Include="-isysroot $(XcodeDir)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(macOSVersion).sdk" /> - <_MonoAotCrossCXXFLAGS Include="-mmacosx-version-min=$(macOSVersionMin)" /> - <_MonoAotCrossCXXFLAGS Include="-Qunused-arguments" /> - <_MonoAotCrossCXXFLAGS Include="-stdlib=libc++" /> - <_MonoAotCrossCXXFLAGS Include="-m64" /> - - <_MonoAotCrossCPPFLAGS Include="-O2" /> - <_MonoAotCrossCPPFLAGS Include="-g" /> - <_MonoAotCrossCPPFLAGS Include="-DMONOTOUCH=1" /> - <_MonoAotCrossCPPFLAGS Include="-m64" /> - - <_MonoAotCrossCXXPPFLAGS Include="-O2" /> - <_MonoAotCrossCXXPPFLAGS Include="-g" /> - <_MonoAotCrossCXXPPFLAGS Include="-m64" /> - - <_MonoAotCrossLDFLAGS Include="-stdlib=libc++" /> - - <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' == 'arm64'" Include="--abi=aarch64-apple-darwin10" /> - <_MonoAotCrossOffsetsToolParams Include="--netcore" /> - <_MonoAotCrossOffsetsToolParams Include="--targetdir="$(MonoObjDir)"" /> - <_MonoAotCrossOffsetsToolParams Include="--monodir="$(MonoProjectRoot)"" /> - <_MonoAotCrossOffsetsToolParams Include="--outfile="$(MonoObjDir)cross/offsets-$(Platform)-darwin.h"" /> - <_MonoAotCrossOffsetsToolParams Include="--libclang="$(XcodeDir)/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib"" /> - <_MonoAotCrossOffsetsToolParams Include="--sysroot="$(XcodeDir)/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS$(tvOSVersion).sdk"" /> @@ -326,6 +270,7 @@ <_MonoCFLAGS Condition="'$(Platform)' == 'arm'" Include="-arch armv7s" /> <_MonoCFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(iOSVersion).sdk" /> <_MonoCFLAGS Include="-miphoneos-version-min=$(iOSVersionMin)" /> + <_MonoCFLAGS Include="-Werror=partial-availability" /> <_MonoCFLAGS Include="-Wl,-application_extension" /> <_MonoCFLAGS Include="-fexceptions" /> @@ -351,17 +296,78 @@ <_MonoLDFLAGS Condition="'$(Platform)' == 'arm64'" Include="-arch arm64" /> <_MonoLDFLAGS Condition="'$(Platform)' == 'arm'" Include="-arch armv7" /> <_MonoLDFLAGS Condition="'$(Platform)' == 'arm'" Include="-arch armv7s" /> - <_MonoLDFLAGS Include="-Wl,-no_weak_imports" /> + <_MonoLDFLAGS Include="-framework CoreFoundation" /> <_MonoLDFLAGS Include="-lobjc" /> <_MonoLDFLAGS Include="-lc++" /> + + + + <_MonoConfigureParams Condition="'$(Platform)' == 'x64'" Include="--host=x86_64-apple-darwin10" /> + <_MonoConfigureParams Condition="'$(Platform)' == 'x86'" Include="--host=i386-apple-darwin10" /> + <_MonoConfigureParams Include="--disable-boehm" /> + <_MonoConfigureParams Include="--disable-btls" /> + <_MonoConfigureParams Include="--disable-executables" /> + <_MonoConfigureParams Include="--disable-iconv" /> + <_MonoConfigureParams Include="--disable-mcs-build" /> + <_MonoConfigureParams Include="--disable-nls" /> + <_MonoConfigureParams Include="--disable-visibility-hidden" /> + <_MonoConfigureParams Include="--enable-maintainer-mode" /> + <_MonoConfigureParams Include="--enable-minimal=com,remoting,shared_perfcounters,gac" /> + <_MonoConfigureParams Include="--enable-monotouch" /> + <_MonoConfigureParams Include="--with-tls=pthread" /> + <_MonoConfigureParams Include="--without-ikvm-native" /> + <_MonoConfigureParams Include="--disable-cooperative-suspend" /> + <_MonoConfigureParams Include="--disable-hybrid-suspend" /> + <_MonoConfigureParams Include="--disable-crash-reporting" /> + + <_MonoAC_VARS Include="ac_cv_func_clock_nanosleep=no" /> + <_MonoAC_VARS Include="ac_cv_func_fstatat=no" /> + <_MonoAC_VARS Include="ac_cv_func_readlinkat=no" /> + <_MonoAC_VARS Include="ac_cv_func_system=no" /> + <_MonoAC_VARS Include="ac_cv_func_getentropy=no" /> + <_MonoAC_VARS Include="ac_cv_func_futimens=no" /> + <_MonoAC_VARS Include="ac_cv_func_utimensat=no" /> + <_MonoAC_VARS Include="ac_cv_func_shm_open_working_with_mmap=no" /> + <_MonoAC_VARS Include="mono_cv_uscore=yes" /> + + <_MonoCFLAGS Condition="'$(Platform)' == 'x64'" Include="-arch x86_64" /> + <_MonoCFLAGS Condition="'$(Platform)' == 'x64'" Include="-m64" /> + <_MonoCFLAGS Condition="'$(Platform)' == 'x86'" Include="-arch i386" /> + <_MonoCFLAGS Condition="'$(Platform)' == 'x86'" Include="-m32" /> + <_MonoCFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk" /> + <_MonoCFLAGS Include="-mios-simulator-version-min=$(iOSVersionMin)" /> + <_MonoCFLAGS Include="-Wl,-application_extension" /> + + <_MonoCXXFLAGS Condition="'$(Platform)' == 'x64'" Include="-arch x86_64" /> + <_MonoCXXFLAGS Condition="'$(Platform)' == 'x64'" Include="-m64" /> + <_MonoCXXFLAGS Condition="'$(Platform)' == 'x86'" Include="-arch i386" /> + <_MonoCXXFLAGS Condition="'$(Platform)' == 'x86'" Include="-m32" /> + <_MonoCXXFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk" /> + <_MonoCXXFLAGS Include="-mios-simulator-version-min=$(iOSVersionMin)" /> + <_MonoCXXFLAGS Include="-Wl,-application_extension" /> + + <_MonoCPPFLAGS Condition="'$(Platform)' == 'x64'" Include="-arch x86_64" /> + <_MonoCPPFLAGS Condition="'$(Platform)' == 'x64'" Include="-m64" /> + <_MonoCPPFLAGS Condition="'$(Platform)' == 'x86'" Include="-arch i386" /> + <_MonoCPPFLAGS Condition="'$(Platform)' == 'x86'" Include="-m32" /> + <_MonoCPPFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk" /> + <_MonoCPPFLAGS Include="-mios-simulator-version-min=$(iOSVersionMin)" /> + <_MonoCPPFLAGS Include="-Wl,-application_extension" /> + <_MonoCPPFLAGS Include="-DMONOTOUCH=1" /> + <_MonoCPPFLAGS Include="-DHOST_IOS" /> + + + + <_MonoAotCrossConfigureParams Include="--host=x86_64-apple-darwin10" /> - <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'arm64'" Include="--target=aarch64-darwin" /> - <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'arm'" Include="--target=arm-darwin" /> - <_MonoAotCrossConfigureParams Include="--with-cross-offsets=$(MonoObjDir)cross/offsets-$(Platform)-darwin.h" /> + <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'arm64'" Include="--target=aarch64-apple-darwin10" /> + <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'arm'" Include="--target=arm-apple-darwin10" /> + <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'x86'" Include="--target=i386-apple-darwin10" /> + <_MonoAotCrossConfigureParams Condition="'$(Platform)' == 'arm64' or '$(Platform)' == 'arm' or '$(Platform)' == 'x86'" Include="--with-cross-offsets=$(MonoObjDir)cross/offsets-$(Platform)-darwin.h" /> <_MonoAotCrossConfigureParams Include="--with-core=only" /> <_MonoAotCrossConfigureParams Include="--enable-maintainer-mode" /> <_MonoAotCrossConfigureParams Include="--enable-compile-warnings" /> @@ -407,64 +413,18 @@ <_MonoAotCrossLDFLAGS Include="-stdlib=libc++" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' == 'arm64'" Include="--abi=aarch64-apple-darwin10" /> <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' == 'arm'" Include="--abi=arm-apple-darwin10" /> - <_MonoAotCrossOffsetsToolParams Include="--netcore" /> - <_MonoAotCrossOffsetsToolParams Include="--targetdir="$(MonoObjDir)"" /> - <_MonoAotCrossOffsetsToolParams Include="--monodir="$(MonoProjectRoot)"" /> - <_MonoAotCrossOffsetsToolParams Include="--outfile="$(MonoObjDir)cross/offsets-$(Platform)-darwin.h"" /> - <_MonoAotCrossOffsetsToolParams Include="--libclang="$(XcodeDir)/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib"" /> - <_MonoAotCrossOffsetsToolParams Include="--sysroot="$(XcodeDir)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(iOSVersion).sdk"" /> - - - - - <_MonoConfigureParams Include="--host=x86_64-apple-darwin10" /> - <_MonoConfigureParams Include="--disable-boehm" /> - <_MonoConfigureParams Include="--disable-btls" /> - <_MonoConfigureParams Include="--disable-executables" /> - <_MonoConfigureParams Include="--disable-iconv" /> - <_MonoConfigureParams Include="--disable-mcs-build" /> - <_MonoConfigureParams Include="--disable-nls" /> - <_MonoConfigureParams Include="--disable-visibility-hidden" /> - <_MonoConfigureParams Include="--enable-maintainer-mode" /> - <_MonoConfigureParams Include="--enable-minimal=com,remoting,shared_perfcounters,gac" /> - <_MonoConfigureParams Include="--enable-monotouch" /> - <_MonoConfigureParams Include="--with-tls=pthread" /> - <_MonoConfigureParams Include="--without-ikvm-native" /> - <_MonoConfigureParams Include="--disable-cooperative-suspend" /> - <_MonoConfigureParams Include="--disable-hybrid-suspend" /> - <_MonoConfigureParams Include="--disable-crash-reporting" /> - - <_MonoAC_VARS Include="ac_cv_func_clock_nanosleep=no" /> - <_MonoAC_VARS Include="ac_cv_func_fstatat=no" /> - <_MonoAC_VARS Include="ac_cv_func_readlinkat=no" /> - <_MonoAC_VARS Include="ac_cv_func_system=no" /> - <_MonoAC_VARS Include="ac_cv_func_getentropy=no" /> - <_MonoAC_VARS Include="ac_cv_func_futimens=no" /> - <_MonoAC_VARS Include="ac_cv_func_utimensat=no" /> - <_MonoAC_VARS Include="ac_cv_func_shm_open_working_with_mmap=no" /> - <_MonoAC_VARS Include="mono_cv_uscore=yes" /> - - <_MonoCFLAGS Include="-arch x86_64" /> - <_MonoCFLAGS Include="-m64" /> - <_MonoCFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk" /> - <_MonoCFLAGS Include="-mios-simulator-version-min=$(iOSVersionMin)" /> - <_MonoCFLAGS Include="-Wl,-application_extension" /> - - <_MonoCXXFLAGS Include="-arch x86_64" /> - <_MonoCXXFLAGS Include="-m64" /> - <_MonoCXXFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk" /> - <_MonoCXXFLAGS Include="-mios-simulator-version-min=$(iOSVersionMin)" /> - <_MonoCXXFLAGS Include="-Wl,-application_extension" /> - - <_MonoCPPFLAGS Include="-arch x86_64" /> - <_MonoCPPFLAGS Include="-m64" /> - <_MonoCPPFLAGS Include="-isysroot $(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk" /> - <_MonoCPPFLAGS Include="-mios-simulator-version-min=$(iOSVersionMin)" /> - <_MonoCPPFLAGS Include="-Wl,-application_extension" /> - <_MonoCPPFLAGS Include="-DMONOTOUCH=1" /> - <_MonoCPPFLAGS Include="-DHOST_IOS" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' == 'x86'" Include="--abi=i386-apple-darwin10" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64'" Include="--netcore" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64'" Include="--targetdir="$(MonoObjDir)"" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64'" Include="--monodir="$(MonoProjectRoot)"" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64'" Include="--outfile="$(MonoObjDir)cross/offsets-$(Platform)-darwin.h"" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64'" Include="--libclang="$(XcodeDir)/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib"" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64' and '$(TargetsiOS)' == 'true' and '$(TargetsiOSSimulator)' != 'true'" Include="--sysroot="$(XcodeDir)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(iOSVersion).sdk"" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64' and '$(TargetsiOS)' == 'true' and '$(TargetsiOSSimulator)' == 'true'" Include="--sysroot="$(XcodeDir)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$(iOSVersion).sdk"" /> + <_MonoAotCrossOffsetsToolParams Condition="'$(Platform)' != 'x64' and '$(TargetstvOS)' == 'true'" Include="--sysroot="$(XcodeDir)/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS$(tvOSVersion).sdk"" /> @@ -727,7 +687,7 @@ <_MonoAotCrossCCLDFLAGSOption Condition="@(_MonoAotCrossCCLDFLAGS->Count()) > 0">CCLDFLAGS="@(_MonoAotCrossCCLDFLAGS, ' ')" <_MonoAotCrossConfigureCommand>$(MonoProjectRoot)configure @(_MonoAotCrossConfigureParams, ' ') @(_MonoAotCrossAC_VARS, ' ') $(_MonoAotCrossCFLAGSOption) $(_MonoAotCrossCXXFLAGSOption) $(_MonoAotCrossCPPFLAGSOption) $(_MonoAotCrossCXXCPPFLAGSOption) $(_MonoAotCrossLDFLAGSOption) $(_MonoAotCrossCCLDFLAGSOption) $(_MonoCCOption) $(_MonoCXXOption) $(_MonoAROption) $(_MonoASOption) $(_MonoCPPOption) $(_MonoCXXCPPOption) $(_MonoDLLTOOLOption) $(_MonoLDOption) $(_MonoOBJDUMPOption) $(_MonoRANLIBOption) $(_MonoCMAKEOption) $(_MonoSTRIPOption) - <_MonoAotCrossOffsetsCommand>python3 $(MonoProjectRoot)mono/tools/offsets-tool/offsets-tool.py @(_MonoAotCrossOffsetsToolParams, ' ') + <_MonoAotCrossOffsetsCommand Condition="@(_MonoAotCrossOffsetsToolParams->Count()) > 0">python3 $(MonoProjectRoot)mono/tools/offsets-tool/offsets-tool.py @(_MonoAotCrossOffsetsToolParams, ' ') @@ -768,6 +728,7 @@ <_MonoBuildParams Include="/p:MONO_BUILD_DIR_PREFIX=""$(MonoObjDir)""" /> <_MonoBuildParams Include="/p:MONO_ENABLE_NETCORE=true" /> + <_MonoBuildParams Include="/p:MONO_ENABLE_PERFTRACING=true" /> <_MonoBuildParams Include="/p:MONO_USE_STATIC_C_RUNTIME=true" /> <_MonoBuildParams Include="/p:CL_MPCount=$([System.Environment]::ProcessorCount)" /> <_MonoBuildParams Include="/v:minimal" /> @@ -926,28 +887,9 @@ - - - - - - - - - - - - + <_MonoRuntimeFilePath Condition="'$(TargetsWindows)' == 'true' and '$(Platform)' == 'x64'">$(MonoObjDir)x64\Bin\$(Configuration)\mono-2.0-sgen.dll <_MonoRuntimeFilePath Condition="'$(TargetsWindows)' == 'true' and '$(Platform)' == 'x86'">$(MonoObjDir)Win32\Bin\$(Configuration)\mono-2.0-sgen.dll @@ -958,9 +900,12 @@ <_MonoRuntimeFilePath Condition="'$(TargetsBrowser)' == 'true'">$(MonoObjDir)mono\mini\.libs\libmonosgen-2.0.a <_MonoRuntimeFilePath Condition="'$(_MonoRuntimeFilePath)' == ''">$(MonoObjDir)mono\mini\.libs\libmonosgen-2.0.so <_MonoRuntimeStaticFilePath Condition="'$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsAndroid)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.a - <_MonoAotCrossFilePath Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'arm64'">$(MonoObjDir)cross\out\bin\aarch64-darwin-mono-sgen - <_MonoAotCrossFilePath Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'arm'">$(MonoObjDir)cross\out\bin\arm-darwin-mono-sgen - <_MonoAotCrossFilePath Condition="'$(TargetstvOS)' == 'true' and '$(Platform)' == 'arm64'">$(MonoObjDir)cross\out\bin\aarch64-darwin-mono-sgen + <_MonoAotCrossFilePath Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'arm64'">$(MonoObjDir)cross\out\bin\aarch64-apple-darwin10-mono-sgen + <_MonoAotCrossFilePath Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'arm'">$(MonoObjDir)cross\out\bin\arm-apple-darwin10-mono-sgen + <_MonoAotCrossFilePath Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'x86'">$(MonoObjDir)cross\out\bin\i386-apple-darwin10-mono-sgen + <_MonoAotCrossFilePath Condition="'$(TargetsiOS)' == 'true' and '$(Platform)' == 'x64'">$(MonoObjDir)cross\out\bin\mono-sgen + <_MonoAotCrossFilePath Condition="'$(TargetstvOS)' == 'true' and '$(Platform)' == 'arm64'">$(MonoObjDir)cross\out\bin\aarch64-apple-darwin10-mono-sgen + <_MonoAotCrossFilePath Condition="'$(TargetstvOS)' == 'true' and '$(Platform)' == 'x64'">$(MonoObjDir)cross\out\bin\mono-sgen <_MonoAotCrossFilePath Condition="'$(TargetsBrowser)' == 'true'">$(MonoObjDir)cross\out\bin\wasm32-unknown-none-mono-sgen @@ -975,6 +920,12 @@ <_MonoRuntimeArtifacts Include="$(_MonoAotCrossFilePath)"> $(BinDir)cross\mono-aot-cross + <_MonoRuntimeArtifacts Condition="'$(MonoBundleLLVMOptimizer)' == 'true'" Include="$(MonoLLVMDir)\bin\llc"> + $(BinDir)\llc + + <_MonoRuntimeArtifacts Condition="'$(MonoBundleLLVMOptimizer)' == 'true'" Include="$(MonoLLVMDir)\bin\opt"> + $(BinDir)\opt + <_MonoRuntimeArtifacts Condition="'$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS'" Include="$(MonoLLVMDir)\bin\llc"> $(BinDir)cross\llc @@ -982,6 +933,18 @@ $(BinDir)cross\opt <_MonoIncludeArtifacts Include="$(MonoObjDir)out\include\**" /> + <_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true'" Include="$(MonoObjDir)out\lib\libmono-ee-interp.a"> + $(BinDir)libmono-ee-interp.a + + <_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true'" Include="$(MonoObjDir)out\lib\libmono-icall-table.a"> + $(BinDir)libmono-icall-table.a + + <_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true'" Include="$(MonoObjDir)out\lib\libmono-ilgen.a"> + $(BinDir)libmono-ilgen.a + + <_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true'" Include="$(MonoObjDir)out\lib\libmono-profiler-aot.a"> + $(BinDir)libmono-profiler-aot.a + + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +block_base_fast_serialize_func ( + void *object, + FastSerializer *fast_serializer); + +static +void +block_base_clear_func (void *object); + +static +void +block_base_serialize_header_func ( + void *object, + FastSerializer *fast_serializer); + +static +uint32_t +block_base_get_header_size_func (void *object); + +static +const ep_char8_t * +event_block_get_type_name_func (void *object); + +static +void +event_block_free_func (void *object); + +static +void +metadata_block_free_func (void *object); + +static +const ep_char8_t * +metadata_block_get_type_name_func (void *object); + +static +int32_t +sequence_point_get_block_size (EventPipeSequencePoint *sequence_point); + +static +void +sequence_point_block_free_func (void *object); + +static +const ep_char8_t * +sequence_point_block_get_type_name_func (void *object); + +static +void +stack_block_free_func (void *object); + +static +const ep_char8_t * +stack_block_get_type_name_func (void *object); + +static +void +stack_block_clear_func (void *object); + +static +uint32_t +stack_block_get_header_size_func (void *object); + +static +void +stack_block_serialize_header_func (void *object, FastSerializer *fast_serializer); + +/* + * EventPipeBlock + */ + +EventPipeBlock * +ep_block_init ( + EventPipeBlock *block, + EventPipeBlockVtable *vtable, + uint32_t max_block_size, + EventPipeSerializationFormat format) +{ + EP_ASSERT (block != NULL && vtable != NULL); + + ep_raise_error_if_nok (ep_fast_serializable_object_init ( + &block->fast_serializer_object, + (FastSerializableObjectVtable *)vtable, + ep_file_get_file_version (format), + ep_file_get_file_minimum_version (format), + format >= EP_SERIALIZATION_FORMAT_NETTRACE_V4) != NULL); + + block->block = ep_rt_byte_array_alloc (max_block_size); + ep_raise_error_if_nok (block->block != NULL); + + memset (block->block, 0, max_block_size); + block->write_pointer = block->block; + block->end_of_the_buffer = block->block + max_block_size; + block->format = format; + +ep_on_exit: + return block; + +ep_on_error: + block = NULL; + ep_exit_error_handler (); +} + +void +ep_block_fini (EventPipeBlock *block) +{ + ep_return_void_if_nok (block != NULL); + ep_rt_byte_array_free (block->block); +} + +void +ep_block_clear_vcall (EventPipeBlock *block) +{ + EP_ASSERT (block != NULL && block->fast_serializer_object.vtable != NULL); + EventPipeBlockVtable *vtable = (EventPipeBlockVtable *)block->fast_serializer_object.vtable; + + EP_ASSERT (vtable->clear_func != NULL); + vtable->clear_func (block); +} + +uint32_t +ep_block_get_header_size_vcall (EventPipeBlock *block) +{ + EP_ASSERT (block != NULL && block->fast_serializer_object.vtable != NULL); + EventPipeBlockVtable *vtable = (EventPipeBlockVtable *)block->fast_serializer_object.vtable; + + EP_ASSERT (vtable->get_header_size_func != NULL); + return vtable->get_header_size_func (block); +} + +void +ep_block_serialize_header_vcall ( + EventPipeBlock *block, + FastSerializer *fast_serializer) +{ + EP_ASSERT (block != NULL && block->fast_serializer_object.vtable != NULL); + EventPipeBlockVtable *vtable = (EventPipeBlockVtable *)block->fast_serializer_object.vtable; + + EP_ASSERT (vtable->serialize_header_func != NULL); + vtable->serialize_header_func (block, fast_serializer); +} + +void +ep_block_fast_serialize_vcall ( + EventPipeBlock *block, + FastSerializer *fast_serializer) +{ + EP_ASSERT (block != NULL); + ep_fast_serializable_object_fast_serialize_vcall (&block->fast_serializer_object, fast_serializer); +} + +/* + * EventPipeEventBlockBase + */ + +static +void +block_base_fast_serialize_func ( + void *object, + FastSerializer *fast_serializer) +{ + EP_ASSERT (object != NULL && fast_serializer != NULL); + ep_block_fast_serialize (&((EventPipeEventBlockBase *)object)->block, fast_serializer); +} + +static +void +block_base_clear_func (void *object) +{ + EP_ASSERT (object != NULL); + ep_event_block_base_clear ((EventPipeEventBlockBase *)object); +} + +static +void +block_base_serialize_header_func ( + void *object, + FastSerializer *fast_serializer) +{ + EP_ASSERT (object != NULL && fast_serializer != NULL); + ep_event_block_base_serialize_header ((EventPipeEventBlockBase *)object, fast_serializer); +} + +static +uint32_t +block_base_get_header_size_func (void *object) +{ + EP_ASSERT (object != NULL); + return ep_event_block_base_get_header_size ((EventPipeEventBlockBase *)object); +} + +EventPipeEventBlockBase * +ep_event_block_base_init ( + EventPipeEventBlockBase *event_block_base, + EventPipeBlockVtable *vtable, + uint32_t max_block_size, + EventPipeSerializationFormat format, + bool use_header_compression) +{ + EP_ASSERT (event_block_base != NULL && vtable != NULL); + + ep_raise_error_if_nok (ep_block_init ( + &event_block_base->block, + vtable, + max_block_size, + format) != NULL); + + event_block_base->use_header_compression = use_header_compression; + + memset (event_block_base->compressed_header, 0, EP_ARRAY_SIZE (event_block_base->compressed_header)); + ep_event_block_base_clear (event_block_base); + +ep_on_exit: + return event_block_base; + +ep_on_error: + event_block_base = NULL; + ep_exit_error_handler (); +} + +void +ep_event_block_base_fini (EventPipeEventBlockBase *event_block_base) +{ + ep_return_void_if_nok (event_block_base != NULL); + ep_block_fini (&event_block_base->block); +} + +/* + * EventPipeEventBlock + */ + +static +const ep_char8_t * +event_block_get_type_name_func (void *object) +{ + EP_ASSERT (object != NULL); + return "EventBlock"; +} + +static +void +event_block_free_func (void *object) +{ + ep_event_block_free ((EventPipeEventBlock *)object); +} + +static EventPipeBlockVtable event_block_vtable = { + { + event_block_free_func, + block_base_fast_serialize_func, + event_block_get_type_name_func }, + block_base_clear_func, + block_base_get_header_size_func, + block_base_serialize_header_func }; + +EventPipeEventBlock * +ep_event_block_alloc ( + uint32_t max_block_size, + EventPipeSerializationFormat format) +{ + EventPipeEventBlock *instance = ep_rt_object_alloc (EventPipeEventBlock); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_event_block_base_init ( + &instance->event_block_base, + &event_block_vtable, + max_block_size, + format, + format >= EP_SERIALIZATION_FORMAT_NETTRACE_V4) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + ep_event_block_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_event_block_free (EventPipeEventBlock *event_block) +{ + ep_return_void_if_nok (event_block != NULL); + + ep_event_block_base_fini (&event_block->event_block_base); + ep_rt_object_free (event_block); +} + +/* + * EventPipeMetadataBlock + */ + +static +void +metadata_block_free_func (void *object) +{ + ep_metadata_block_free ((EventPipeMetadataBlock *)object); +} + +static +const ep_char8_t * +metadata_block_get_type_name_func (void *object) +{ + EP_ASSERT (object != NULL); + return "MetadataBlock"; +} + +static EventPipeBlockVtable metadata_block_vtable = { + { + metadata_block_free_func, + block_base_fast_serialize_func, + metadata_block_get_type_name_func }, + block_base_clear_func, + block_base_get_header_size_func, + block_base_serialize_header_func }; + +EventPipeMetadataBlock * +ep_metadata_block_alloc (uint32_t max_block_size) +{ + EventPipeMetadataBlock *instance = ep_rt_object_alloc (EventPipeMetadataBlock); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_event_block_base_init ( + &instance->event_block_base, + &metadata_block_vtable, + max_block_size, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + true) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + ep_metadata_block_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_metadata_block_free (EventPipeMetadataBlock *metadata_block) +{ + ep_return_void_if_nok (metadata_block != NULL); + + ep_event_block_base_fini (&metadata_block->event_block_base); + ep_rt_object_free (metadata_block); +} + +/* + * EventPipeSequencePointBlock. + */ + +static +int32_t +sequence_point_get_block_size (EventPipeSequencePoint *sequence_point) +{ + EP_ASSERT (sequence_point != NULL); + + const uint32_t size_of_sequence_number = + sizeof (uint64_t) + //thread id + sizeof (uint32_t); //sequence number + + const uint32_t thread_count = ep_rt_thread_sequence_number_map_count (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point)); + + return sizeof (sequence_point->timestamp) + + sizeof (uint32_t) + //thread count + thread_count * size_of_sequence_number; +} + +static +void +sequence_point_block_free_func (void *object) +{ + ep_sequence_point_block_free ((EventPipeSequencePointBlock *)object); +} + +static +const ep_char8_t * +sequence_point_block_get_type_name_func (void *object) +{ + EP_ASSERT (object != NULL); + return "SPBlock"; +} + +static EventPipeBlockVtable sequence_point_block_vtable = { + { + sequence_point_block_free_func, + block_base_fast_serialize_func, + sequence_point_block_get_type_name_func }, + block_base_clear_func, + block_base_get_header_size_func, + block_base_serialize_header_func }; + +EventPipeSequencePointBlock * +ep_sequence_point_block_alloc (EventPipeSequencePoint *sequence_point) +{ + ep_return_null_if_nok (sequence_point != NULL); + + EventPipeSequencePointBlock *instance = ep_rt_object_alloc (EventPipeSequencePointBlock); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_sequence_point_block_init (instance, sequence_point) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + ep_sequence_point_block_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +EventPipeSequencePointBlock * +ep_sequence_point_block_init ( + EventPipeSequencePointBlock *sequence_point_block, + EventPipeSequencePoint *sequence_point) +{ + EP_ASSERT (sequence_point_block != NULL); + ep_return_null_if_nok (sequence_point != NULL); + + ep_raise_error_if_nok (ep_event_block_base_init ( + &sequence_point_block->event_block_base, + &sequence_point_block_vtable, + sequence_point_get_block_size (sequence_point), + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + true) != NULL); + + const int64_t timestamp = sequence_point->timestamp; + memcpy (sequence_point_block->event_block_base.block.write_pointer, ×tamp, sizeof (timestamp)); + sequence_point_block->event_block_base.block.write_pointer += sizeof (timestamp); + + const uint32_t thread_count = ep_rt_thread_sequence_number_map_count (ep_sequence_point_get_thread_sequence_numbers_cref (sequence_point)); + memcpy (sequence_point_block->event_block_base.block.write_pointer, &thread_count, sizeof (thread_count)); + sequence_point_block->event_block_base.block.write_pointer += sizeof (thread_count); + + ep_rt_thread_sequence_number_hash_map_iterator_t iterator; + for (ep_rt_thread_sequence_number_map_iterator_begin (&sequence_point->thread_sequence_numbers, &iterator); + !ep_rt_thread_sequence_number_map_iterator_end (&sequence_point->thread_sequence_numbers, &iterator); + ep_rt_thread_sequence_number_map_iterator_next (&sequence_point->thread_sequence_numbers, &iterator)) { + + const EventPipeThreadSessionState *key = ep_rt_thread_sequence_number_map_iterator_key (&iterator); + + const uint64_t thread_id = ep_thread_get_os_thread_id (ep_thread_session_state_get_thread (key)); + memcpy (sequence_point_block->event_block_base.block.write_pointer, &thread_id, sizeof (thread_id)); + sequence_point_block->event_block_base.block.write_pointer += sizeof (thread_id); + + const uint32_t sequence_number = ep_rt_thread_sequence_number_map_iterator_value (&iterator); + memcpy (sequence_point_block->event_block_base.block.write_pointer, &sequence_number, sizeof (sequence_number)); + sequence_point_block->event_block_base.block.write_pointer += sizeof (sequence_number); + } + +ep_on_exit: + return sequence_point_block; + +ep_on_error: + sequence_point_block = NULL; + ep_exit_error_handler (); +} + +void +ep_sequence_point_block_fini (EventPipeSequencePointBlock *sequence_point_block) +{ + ep_return_void_if_nok (sequence_point_block != NULL); + ep_event_block_base_fini (&sequence_point_block->event_block_base); +} + +void +ep_sequence_point_block_free (EventPipeSequencePointBlock *sequence_point_block) +{ + ep_return_void_if_nok (sequence_point_block != NULL); + + ep_sequence_point_block_fini (sequence_point_block); + ep_rt_object_free (sequence_point_block); +} + +/* + * EventPipeStackBlock. + */ + +static +void +stack_block_free_func (void *object) +{ + ep_stack_block_free ((EventPipeStackBlock *)object); +} + +static +const ep_char8_t * +stack_block_get_type_name_func (void *object) +{ + EP_ASSERT (object != NULL); + return "StackBlock"; +} + +static +void +stack_block_clear_func (void *object) +{ + EP_ASSERT (object != NULL); + + EventPipeStackBlock *stack_block = (EventPipeStackBlock *)object; + + stack_block->has_initial_index = false; + stack_block->has_initial_index = 0; + stack_block->count = 0; + + ep_block_clear (&stack_block->event_block_base.block); +} + +static +uint32_t +stack_block_get_header_size_func (void *object) +{ + EP_ASSERT (object != NULL); + return sizeof (uint32_t) + // start index + sizeof (uint32_t); // count of indices +} + +static +void +stack_block_serialize_header_func (void *object, FastSerializer *fast_serializer) +{ + EP_ASSERT (object != NULL && fast_serializer != NULL); + + EventPipeStackBlock *stack_block = (EventPipeStackBlock *)object; + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&stack_block->initial_index, sizeof (stack_block->initial_index)); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&stack_block->count, sizeof (stack_block->count)); +} + +static EventPipeBlockVtable stack_block_vtable = { + { + stack_block_free_func, + block_base_fast_serialize_func, + stack_block_get_type_name_func }, + stack_block_clear_func, + stack_block_get_header_size_func, + stack_block_serialize_header_func }; + +EventPipeStackBlock * +ep_stack_block_alloc (uint32_t max_block_size) +{ + EventPipeStackBlock *instance = ep_rt_object_alloc (EventPipeStackBlock); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_event_block_base_init ( + &instance->event_block_base, + &stack_block_vtable, + max_block_size, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + true) != NULL); + + stack_block_clear_func (instance); + +ep_on_exit: + return instance; + +ep_on_error: + ep_stack_block_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_stack_block_free (EventPipeStackBlock *stack_block) +{ + ep_return_void_if_nok (stack_block != NULL); + + ep_event_block_base_fini (&stack_block->event_block_base); + ep_rt_object_free (stack_block); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_block_internals; +const char quiet_linker_empty_file_warning_eventpipe_block_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-block.c b/src/mono/mono/eventpipe/ep-block.c new file mode 100644 index 0000000000000..214d3817fa645 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-block.c @@ -0,0 +1,398 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +uint8_t * +event_block_base_write_var_uint32 ( + uint8_t * write_pointer, + uint32_t value); + +static +uint8_t * +event_block_base_write_var_uint64 ( + uint8_t * write_pointer, + uint64_t value); + +/* + * EventPipeBlock + */ + +void +ep_block_clear (EventPipeBlock *block) +{ + ep_return_void_if_nok (block != NULL); + ep_return_void_if_nok (ep_block_get_block (block) != NULL); + + EP_ASSERT (ep_block_get_write_pointer (block) <= ep_block_get_end_of_the_buffer (block)); + + memset (ep_block_get_block (block), 0, ep_block_get_end_of_the_buffer (block) - ep_block_get_block (block)); + ep_block_set_write_pointer (block, ep_block_get_block (block)); +} + +uint32_t +ep_block_get_header_size (EventPipeBlock *block) +{ + return 0; +} + +void +ep_block_serialize_header ( + EventPipeBlock *block, + FastSerializer *fast_serializer) +{ + ; +} + +void +ep_block_fast_serialize ( + EventPipeBlock *block, + FastSerializer *fast_serializer) +{ + ep_return_void_if_nok (block != NULL && fast_serializer != NULL && ep_block_get_block (block) != NULL); + + uint32_t data_size = ep_block_get_bytes_written (block); + EP_ASSERT (data_size != 0); + + uint32_t header_size = ep_block_get_header_size_vcall (block); + uint32_t total_size = data_size + header_size; + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&total_size, sizeof (total_size)); + + uint32_t required_padding = ep_fast_serializer_get_required_padding (fast_serializer); + if (required_padding != 0) { + uint8_t max_padding [FAST_SERIALIZER_ALIGNMENT_SIZE - 1] = { 0 }; // it's longest possible padding, we are going to use only part of it + + EP_ASSERT (required_padding <= FAST_SERIALIZER_ALIGNMENT_SIZE - 1); + ep_fast_serializer_write_buffer (fast_serializer, max_padding, required_padding); // we write zeros here, the reader is going to always read from the first aligned address of the serialized content + + EP_ASSERT (ep_fast_serializer_get_write_error_encountered (fast_serializer) || ep_fast_serializer_get_required_padding (fast_serializer)); + } + + ep_block_serialize_header_vcall (block, fast_serializer); + ep_fast_serializer_write_buffer (fast_serializer, ep_block_get_block (block), data_size); +} + +/* + * EventPipeEventBlockBase + */ + +static +uint8_t * +event_block_base_write_var_uint32 ( + uint8_t * write_pointer, + uint32_t value) +{ + while (value >= 0x80) { + *write_pointer = (uint8_t)(value | 0x80); + write_pointer++; + value >>= 7; + } + *write_pointer = (uint8_t)value; + write_pointer++; + return write_pointer; +} + +static +uint8_t * +event_block_base_write_var_uint64 ( + uint8_t * write_pointer, + uint64_t value) +{ + while (value >= 0x80) { + *write_pointer = (uint8_t)(value | 0x80); + write_pointer++; + value >>= 7; + } + *write_pointer = (uint8_t)value; + write_pointer++; + return write_pointer; +} + +void +ep_event_block_base_clear (EventPipeEventBlockBase *event_block_base) +{ + ep_return_void_if_nok (event_block_base != NULL); + + ep_block_clear (ep_event_block_base_get_block_ref (event_block_base)); + memset (ep_event_block_base_get_last_header_ref (event_block_base), 0, sizeof (EventPipeEventHeader)); + ep_event_block_base_set_min_timestamp (event_block_base, INT64_MAX); + ep_event_block_base_set_max_timestamp (event_block_base, INT64_MIN); +} + +uint32_t +ep_event_block_base_get_header_size (const EventPipeEventBlockBase *event_block_base) +{ + ep_return_zero_if_nok (event_block_base != NULL && ep_block_get_format ((EventPipeBlock *)event_block_base) != EP_SERIALIZATION_FORMAT_NETPERF_V3); + + return sizeof(uint16_t) + // header size + sizeof(uint16_t) + // flags + sizeof(int64_t) + // min timestamp + sizeof(int64_t); // max timestamp +} + +void +ep_event_block_base_serialize_header ( + EventPipeEventBlockBase *event_block_base, + FastSerializer *fast_serializer) +{ + ep_return_void_if_nok (event_block_base != NULL && ep_block_get_format ((EventPipeBlock *)event_block_base) != EP_SERIALIZATION_FORMAT_NETPERF_V3 && fast_serializer != NULL); + + const uint16_t header_size = (uint16_t)ep_block_get_header_size_vcall ((EventPipeBlock *)event_block_base); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&header_size, sizeof (header_size)); + + const uint16_t flags = ep_event_block_base_get_use_header_compression (event_block_base) ? 1 : 0; + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&flags, sizeof (flags)); + + uint64_t min_timestamp = ep_event_block_base_get_min_timestamp (event_block_base); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&min_timestamp, sizeof (min_timestamp)); + + uint64_t max_timestamp = ep_event_block_base_get_max_timestamp (event_block_base); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&max_timestamp, sizeof (max_timestamp)); +} + +bool +ep_event_block_base_write_event ( + EventPipeEventBlockBase *event_block_base, + EventPipeEventInstance *event_instance, + uint64_t capture_thread_id, + uint32_t sequence_number, + int32_t stack_id, + bool is_sorted_event) +{ + ep_return_false_if_nok (event_block_base != NULL && event_instance != NULL); + + EventPipeBlock *block = ep_event_block_base_get_block_ref (event_block_base); + ep_raise_error_if_nok (ep_block_get_block (block) != NULL); + + uint32_t data_len = 0; + uint8_t * aligned_end = NULL; + uint32_t capture_proc_number = ep_event_instance_get_proc_num (event_instance); + uint8_t * write_pointer = ep_block_get_write_pointer (block); + + if (!ep_event_block_base_get_use_header_compression (event_block_base)) { + uint32_t total_size = ep_event_instance_get_aligned_total_size (event_instance, ep_block_get_format (block)); + ep_raise_error_if_nok (write_pointer + total_size < ep_block_get_end_of_the_buffer (block)); + + aligned_end = write_pointer + total_size + sizeof (total_size); + + memcpy (write_pointer, &total_size, sizeof (total_size)); + write_pointer += sizeof (total_size); + + uint32_t metadata_id = ep_event_instance_get_metadata_id (event_instance); + EP_ASSERT ((metadata_id & (1 << 31)) == 0); + + metadata_id |= (!is_sorted_event ? 1 << 31 : 0); + memcpy (write_pointer, &metadata_id, sizeof (metadata_id)); + write_pointer += sizeof (metadata_id); + + if (ep_block_get_format (block) == EP_SERIALIZATION_FORMAT_NETPERF_V3) { + int32_t thread_id = (int32_t)ep_event_instance_get_thread_id (event_instance); + memcpy (write_pointer, &thread_id, sizeof (thread_id)); + write_pointer += sizeof (thread_id); + } else if (ep_block_get_format (block) == EP_SERIALIZATION_FORMAT_NETTRACE_V4) { + memcpy (write_pointer, &sequence_number, sizeof (sequence_number)); + write_pointer += sizeof (sequence_number); + + uint64_t thread_id = ep_event_instance_get_thread_id (event_instance); + memcpy (write_pointer, &thread_id, sizeof (thread_id)); + write_pointer += sizeof (thread_id); + + memcpy (write_pointer, &capture_thread_id, sizeof (capture_thread_id)); + write_pointer += sizeof (capture_thread_id); + + memcpy (write_pointer, &capture_proc_number, sizeof (capture_proc_number)); + write_pointer += sizeof (capture_proc_number); + + memcpy (write_pointer, &stack_id, sizeof (stack_id)); + write_pointer += sizeof (stack_id); + } + + int64_t timestamp = ep_event_instance_get_timestamp (event_instance); + memcpy (write_pointer, ×tamp, sizeof (timestamp)); + write_pointer += sizeof (timestamp); + + const uint8_t *activity_id = ep_event_instance_get_activity_id_cref (event_instance); + memcpy (write_pointer, activity_id, EP_ACTIVITY_ID_SIZE); + write_pointer += EP_ACTIVITY_ID_SIZE; + + const uint8_t *relative_activity_id = ep_event_instance_get_related_activity_id_cref (event_instance); + memcpy (write_pointer, relative_activity_id, EP_ACTIVITY_ID_SIZE); + write_pointer += EP_ACTIVITY_ID_SIZE; + + data_len = ep_event_instance_get_data_len (event_instance); + memcpy (write_pointer, &data_len, sizeof (data_len)); + write_pointer += sizeof (data_len); + } else { // using header compression + uint8_t flags = 0; + uint8_t *header_write_pointer = ep_event_block_base_get_compressed_header_ref (event_block_base); + EventPipeEventHeader *last_header = ep_event_block_base_get_last_header_ref (event_block_base); + + if (ep_event_instance_get_metadata_id (event_instance) != last_header->metadata_id) { + header_write_pointer = event_block_base_write_var_uint32 (header_write_pointer, ep_event_instance_get_metadata_id (event_instance)); + flags |= 1; + } + + if (is_sorted_event) { + flags |= (1 << 6); + } + + if (last_header->sequence_number + (ep_event_instance_get_metadata_id (event_instance) != 0 ? 1 : 0) != sequence_number || + last_header->capture_thread_id != capture_thread_id || last_header->capture_proc_number != capture_proc_number) { + header_write_pointer = event_block_base_write_var_uint32 (header_write_pointer, sequence_number - last_header->sequence_number - 1); + header_write_pointer = event_block_base_write_var_uint32 (header_write_pointer, (uint32_t)capture_thread_id); + header_write_pointer = event_block_base_write_var_uint32 (header_write_pointer, capture_proc_number); + flags |= (1 << 1); + } + + if (last_header->thread_id != ep_event_instance_get_thread_id (event_instance)) { + header_write_pointer = event_block_base_write_var_uint64 (header_write_pointer, ep_event_instance_get_thread_id (event_instance)); + flags |= (1 << 2); + } + + if (last_header->stack_id != stack_id) { + header_write_pointer = event_block_base_write_var_uint32 (header_write_pointer, stack_id); + flags |= (1 << 3); + } + + int64_t timestamp = ep_event_instance_get_timestamp (event_instance); + header_write_pointer = event_block_base_write_var_uint64 (header_write_pointer, timestamp - last_header->timestamp); + + if (memcmp (&last_header->activity_id, ep_event_instance_get_activity_id_cref (event_instance), EP_ACTIVITY_ID_SIZE) != 0) { + memcpy (header_write_pointer, ep_event_instance_get_activity_id_cref (event_instance), EP_ACTIVITY_ID_SIZE ); + header_write_pointer += EP_ACTIVITY_ID_SIZE; + flags |= (1 << 4); + } + + if (memcmp (&last_header->related_activity_id, ep_event_instance_get_related_activity_id_cref (event_instance), EP_ACTIVITY_ID_SIZE) != 0) { + memcpy (header_write_pointer, ep_event_instance_get_related_activity_id_cref (event_instance), EP_ACTIVITY_ID_SIZE ); + header_write_pointer += EP_ACTIVITY_ID_SIZE; + flags |= (1 << 5); + } + + data_len = ep_event_instance_get_data_len (event_instance); + if (last_header->data_len != data_len) { + header_write_pointer = event_block_base_write_var_uint32 (header_write_pointer, data_len); + flags |= (1 << 7); + } + + uint32_t bytes_written = (uint32_t)(header_write_pointer - ep_event_block_base_get_compressed_header_cref (event_block_base)); + uint32_t total_size = 1 + bytes_written + data_len; + + if (write_pointer + total_size >= ep_block_get_end_of_the_buffer (block)) { + //TODO: Orignal EP updates blocks write pointer continiously, doing the same here before + //bailing out. Question is if that is intentional or just a side effect of directly updating + //the member. + ep_block_set_write_pointer (block, write_pointer); + ep_raise_error (); + } + + last_header->metadata_id = ep_event_instance_get_metadata_id (event_instance); + last_header->sequence_number = sequence_number; + last_header->thread_id = ep_event_instance_get_thread_id (event_instance); + last_header->capture_thread_id = capture_thread_id; + last_header->capture_proc_number = capture_proc_number; + last_header->stack_id = stack_id; + last_header->timestamp = timestamp; + memcpy (&last_header->activity_id, ep_event_instance_get_activity_id_cref (event_instance), EP_ACTIVITY_ID_SIZE); + memcpy (&last_header->related_activity_id, ep_event_instance_get_related_activity_id_cref (event_instance), EP_ACTIVITY_ID_SIZE); + last_header->data_len = data_len; + + aligned_end = write_pointer + total_size; + *write_pointer = flags; + write_pointer++; + memcpy (write_pointer, ep_event_block_base_get_compressed_header_cref (event_block_base), bytes_written); + write_pointer += bytes_written; + } + + if (data_len > 0) { + memcpy (write_pointer, ep_event_instance_get_data (event_instance), data_len); + write_pointer += data_len; + } + + if (ep_block_get_format (block) == EP_SERIALIZATION_FORMAT_NETPERF_V3) { + uint32_t stack_size = ep_stack_contents_get_size (ep_event_instance_get_stack_contents_ref (event_instance)); + memcpy (write_pointer, &stack_size, sizeof (stack_size)); + write_pointer += sizeof (stack_size); + + if (stack_size > 0) { + memcpy (write_pointer, ep_event_instance_get_stack_contents_ref (event_instance), stack_size); + write_pointer += stack_size; + } + } + + while (write_pointer < aligned_end) + *write_pointer++ = (uint8_t)0; // put padding at the end to get 4 bytes alignment of the payload + + EP_ASSERT (write_pointer == aligned_end); + + int64_t instance_timestamp = ep_event_instance_get_timestamp (event_instance); + if (ep_event_block_base_get_min_timestamp (event_block_base) > instance_timestamp) + ep_event_block_base_set_min_timestamp (event_block_base, instance_timestamp); + if (ep_event_block_base_get_max_timestamp (event_block_base) > instance_timestamp) + ep_event_block_base_set_max_timestamp (event_block_base, instance_timestamp); + + ep_block_set_write_pointer (block, write_pointer); + return true; + +ep_on_error: + return false; +} + +/* + * EventPipeStackBlock. + */ + +bool +ep_stack_block_write_stack ( + EventPipeStackBlock *stack_block, + int32_t stack_id, + EventPipeStackContents *stack) +{ + ep_return_false_if_nok (stack_block != NULL); + + EventPipeBlock *block = ep_event_block_base_get_block_ref (ep_stack_block_get_event_block_base_ref (stack_block)); + ep_raise_error_if_nok (block != NULL && ep_block_get_block (block) != NULL); + + uint32_t stack_size = ep_stack_contents_get_size (stack); + uint32_t total_size = sizeof (stack_size) + stack_size; + uint8_t *write_pointer = ep_block_get_write_pointer (block); + + ep_raise_error_if_nok (write_pointer + total_size < ep_block_get_end_of_the_buffer (block)); + + if (!ep_stack_block_get_has_initial_index (stack_block)) { + ep_stack_block_set_has_initial_index (stack_block, true); + ep_stack_block_set_initial_index (stack_block, stack_id); + } + + ep_stack_block_set_count (stack_block, ep_stack_block_get_count (stack_block) + 1); + + memcpy (write_pointer, &stack_size, sizeof (stack_size)); + write_pointer += sizeof (stack_size); + + if (stack_size > 0) { + memcpy (write_pointer, ep_stack_contents_get_pointer (stack), stack_size); + write_pointer += stack_size; + } + + ep_block_set_write_pointer (block, write_pointer); + return true; + +ep_on_error: + return false; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_block; +const char quiet_linker_empty_file_warning_eventpipe_block = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-block.h b/src/mono/mono/eventpipe/ep-block.h new file mode 100644 index 0000000000000..f114cfd4eabba --- /dev/null +++ b/src/mono/mono/eventpipe/ep-block.h @@ -0,0 +1,375 @@ +#ifndef __EVENTPIPE_BLOCK_H__ +#define __EVENTPIPE_BLOCK_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeBlock + */ + +typedef void (*EventPipeBlockClearFunc)(void *object); +typedef uint32_t (*EventPipeBlockGetHeaderSizeFunc)(void *object); +typedef void (*EventPipeBlockSerializeHeaderFunc)(void *object, FastSerializer *fast_serializer); + +struct _EventPipeBlockVtable { + FastSerializableObjectVtable fast_serializable_object_vtable; + EventPipeBlockClearFunc clear_func; + EventPipeBlockGetHeaderSizeFunc get_header_size_func; + EventPipeBlockSerializeHeaderFunc serialize_header_func; +}; + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeBlock { +#else +struct _EventPipeBlock_Internal { +#endif + FastSerializableObject fast_serializer_object; + uint8_t *block; + uint8_t *write_pointer; + uint8_t *end_of_the_buffer; + EventPipeSerializationFormat format; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeBlock { + uint8_t _internal [sizeof (struct _EventPipeBlock_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeBlock *, block, uint8_t*, block) +EP_DEFINE_GETTER(EventPipeBlock *, block, uint8_t*, write_pointer) +EP_DEFINE_SETTER(EventPipeBlock *, block, uint8_t*, write_pointer) +EP_DEFINE_GETTER(EventPipeBlock *, block, uint8_t*, end_of_the_buffer) +EP_DEFINE_GETTER(EventPipeBlock *, block, EventPipeSerializationFormat, format) + +static +inline +uint32_t +ep_block_get_bytes_written (const EventPipeBlock *block) +{ + return block == NULL ? 0 : (uint32_t)(ep_block_get_write_pointer (block) - ep_block_get_block (block)); +} + +EventPipeBlock * +ep_block_init ( + EventPipeBlock *block, + EventPipeBlockVtable *vtable, + uint32_t max_block_size, + EventPipeSerializationFormat format); + +void +ep_block_fini (EventPipeBlock *block); + +void +ep_block_clear (EventPipeBlock *block); + +uint32_t +ep_block_get_header_size (EventPipeBlock *block); + +void +ep_block_serialize_header ( + EventPipeBlock *block, + FastSerializer *fast_serializer); + +void +ep_block_fast_serialize ( + EventPipeBlock *block, + FastSerializer *fast_serializer); + +void +ep_block_clear_vcall (EventPipeBlock *block); + +uint32_t +ep_block_get_header_size_vcall (EventPipeBlock *block); + +void +ep_block_serialize_header_vcall ( + EventPipeBlock *block, + FastSerializer *fast_serializer); + +void +ep_block_fast_serialize_vcall ( + EventPipeBlock *block, + FastSerializer *fast_serializer); + +/* + * EventPipeEventHeader. + */ + +struct _EventPipeEventHeader { + int32_t metadata_id; + int32_t sequence_number; + uint64_t thread_id; + uint64_t capture_thread_id; + int32_t capture_proc_number; + int32_t stack_id; + uint64_t timestamp; + uint8_t activity_id [EP_ACTIVITY_ID_SIZE]; + uint8_t related_activity_id [EP_ACTIVITY_ID_SIZE]; + int32_t data_len; +}; + +/* + * EventPipeEventBlockBase + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventBlockBase { +#else +struct _EventPipeEventBlockBase_Internal { +#endif + EventPipeBlock block; + EventPipeEventHeader last_header; + uint8_t compressed_header [100]; + bool use_header_compression; + uint64_t min_timestamp; + uint64_t max_timestamp; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventBlockBase { + uint8_t _internal [sizeof (struct _EventPipeEventBlockBase_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeEventBlockBase *, event_block_base, EventPipeBlock *, block) +EP_DEFINE_GETTER_REF(EventPipeEventBlockBase *, event_block_base, EventPipeEventHeader *, last_header) +EP_DEFINE_GETTER(EventPipeEventBlockBase *, event_block_base, bool, use_header_compression) +EP_DEFINE_GETTER_ARRAY_REF(EventPipeEventBlockBase *, event_block_base, uint8_t *, const uint8_t *, compressed_header, compressed_header[0]) +EP_DEFINE_GETTER(EventPipeEventBlockBase *, event_block_base, uint64_t, min_timestamp) +EP_DEFINE_SETTER(EventPipeEventBlockBase *, event_block_base, uint64_t, min_timestamp) +EP_DEFINE_GETTER(EventPipeEventBlockBase *, event_block_base, uint64_t, max_timestamp) +EP_DEFINE_SETTER(EventPipeEventBlockBase *, event_block_base, uint64_t, max_timestamp) + +EventPipeEventBlockBase * +ep_event_block_base_init ( + EventPipeEventBlockBase *event_block_base, + EventPipeBlockVtable *vtable, + uint32_t max_block_size, + EventPipeSerializationFormat format, + bool use_header_compression); + +void +ep_event_block_base_fini (EventPipeEventBlockBase *event_block_base); + +void +ep_event_block_base_clear (EventPipeEventBlockBase *event_block_base); + +uint32_t +ep_event_block_base_get_header_size (const EventPipeEventBlockBase *event_block_base); + +void +ep_event_block_base_serialize_header ( + EventPipeEventBlockBase *event_block_base, + FastSerializer *fast_serializer); + +bool +ep_event_block_base_write_event ( + EventPipeEventBlockBase *event_block_base, + EventPipeEventInstance *event_instance, + uint64_t capture_thread_id, + uint32_t sequence_number, + int32_t stack_id, + bool is_sorted_event); + +/* + * EventPipeEventBlock. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventBlock { +#else +struct _EventPipeEventBlock_Internal { +#endif + EventPipeEventBlockBase event_block_base; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventBlock { + uint8_t _internal [sizeof (struct _EventPipeEventBlock_Internal)]; +}; +#endif + +EventPipeEventBlock * +ep_event_block_alloc ( + uint32_t max_block_size, + EventPipeSerializationFormat format); + +void +ep_event_block_free (EventPipeEventBlock *event_block); + +static +inline +uint32_t +ep_event_block_get_bytes_written (EventPipeEventBlock *event_block) +{ + return ep_block_get_bytes_written ((const EventPipeBlock *)event_block); +} + +static +inline +void +ep_event_block_serialize (EventPipeEventBlock *event_block, FastSerializer *fast_serializer) +{ + ep_fast_serializer_write_object (fast_serializer, (FastSerializableObject*)event_block); +} + +static +inline +void +ep_event_block_clear (EventPipeEventBlock *event_block) +{ + ep_block_clear_vcall ((EventPipeBlock *)event_block); +} + +/* + * EventPipeMetadataBlock. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeMetadataBlock { +#else +struct _EventPipeMetadataBlock_Internal { +#endif + EventPipeEventBlockBase event_block_base; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeMetadataBlock { + uint8_t _internal [sizeof (struct _EventPipeMetadataBlock_Internal)]; +}; +#endif + +EventPipeMetadataBlock * +ep_metadata_block_alloc (uint32_t max_block_size); + +void +ep_metadata_block_free (EventPipeMetadataBlock *metadata_block); + +static +inline +uint32_t +ep_metadata_block_get_bytes_written (EventPipeMetadataBlock *metadata_block) +{ + return ep_block_get_bytes_written ((const EventPipeBlock *)metadata_block); +} + +static +inline +void +ep_metadata_block_serialize (EventPipeMetadataBlock *metadata_block, FastSerializer *fast_serializer) +{ + ep_fast_serializer_write_object (fast_serializer, (FastSerializableObject *)metadata_block); +} + +static +inline +void +ep_metadata_block_clear (EventPipeMetadataBlock *metadata_block) +{ + ep_block_clear_vcall ((EventPipeBlock *)metadata_block); +} + +/* + * EventPipeSequencePointBlock. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSequencePointBlock { +#else +struct _EventPipeSequencePointBlock_Internal { +#endif + EventPipeEventBlockBase event_block_base; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSequencePointBlock { + uint8_t _internal [sizeof (struct _EventPipeSequencePointBlock_Internal)]; +}; +#endif + +EventPipeSequencePointBlock * +ep_sequence_point_block_alloc (EventPipeSequencePoint *sequence_point); + +EventPipeSequencePointBlock * +ep_sequence_point_block_init ( + EventPipeSequencePointBlock *sequence_point_block, + EventPipeSequencePoint *sequence_point); + +void +ep_sequence_point_block_fini (EventPipeSequencePointBlock *sequence_point_block); + +void +ep_sequence_point_block_free (EventPipeSequencePointBlock *sequence_point_block); + +/* + * EventPipeStackBlock. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeStackBlock { +#else +struct _EventPipeStackBlock_Internal { +#endif + EventPipeEventBlockBase event_block_base; + uint32_t initial_index; + uint32_t count; + bool has_initial_index; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeStackBlock { + uint8_t _internal [sizeof (struct _EventPipeStackBlock_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeStackBlock *, stack_block, EventPipeEventBlockBase *, event_block_base) +EP_DEFINE_GETTER(EventPipeStackBlock *, stack_block, uint32_t, initial_index) +EP_DEFINE_SETTER(EventPipeStackBlock *, stack_block, uint32_t, initial_index) +EP_DEFINE_GETTER(EventPipeStackBlock *, stack_block, uint32_t, count) +EP_DEFINE_SETTER(EventPipeStackBlock *, stack_block, uint32_t, count) +EP_DEFINE_GETTER(EventPipeStackBlock *, stack_block, bool, has_initial_index) +EP_DEFINE_SETTER(EventPipeStackBlock *, stack_block, bool, has_initial_index) + +EventPipeStackBlock * +ep_stack_block_alloc (uint32_t max_block_size); + +void +ep_stack_block_free (EventPipeStackBlock *stack_block); + +bool +ep_stack_block_write_stack ( + EventPipeStackBlock *stack_block, + int32_t stack_id, + EventPipeStackContents *stack); + +static +inline +uint32_t +ep_stack_block_get_bytes_written (EventPipeStackBlock *stack_block) +{ + return ep_block_get_bytes_written ((const EventPipeBlock *)stack_block); +} + +static +inline +void +ep_stack_block_serialize (EventPipeStackBlock *stack_block, FastSerializer *fast_serializer) +{ + ep_fast_serializer_write_object (fast_serializer, (FastSerializableObject *)stack_block); +} + +static +inline +void +ep_stack_block_clear (EventPipeStackBlock *stack_block) +{ + ep_block_clear_vcall ((EventPipeBlock *)stack_block); +} + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_BLOCK_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-buffer-manager-internals.c b/src/mono/mono/eventpipe/ep-buffer-manager-internals.c new file mode 100644 index 0000000000000..aabec9ad60379 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-buffer-manager-internals.c @@ -0,0 +1,38 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventPipeBufferManager. + */ + +EventPipeBufferManager * +ep_buffer_manager_alloc ( + EventPipeSession *session, + size_t max_size_of_all_buffers, + size_t sequence_point_allocation_budget) +{ + //TODO: Implement. + return ep_rt_object_alloc (EventPipeBufferManager); +} + +void +ep_buffer_manager_free (EventPipeBufferManager * buffer_manager) +{ + //TODO: Implement. + ep_return_void_if_nok (buffer_manager != NULL); + ep_rt_object_free (buffer_manager); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_buffer_manager_internals; +const char quiet_linker_empty_file_warning_eventpipe_buffer_manager_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-buffer-manager.c b/src/mono/mono/eventpipe/ep-buffer-manager.c new file mode 100644 index 0000000000000..3e151790d6afb --- /dev/null +++ b/src/mono/mono/eventpipe/ep-buffer-manager.c @@ -0,0 +1,28 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * EventPipeBufferManager. + */ + +#ifdef EP_CHECKED_BUILD +void +ep_buffer_manager_requires_lock_held (const EventPipeBufferManager *buffer_manager) +{ + EP_ASSERT (buffer_manager != NULL); + ep_rt_spin_lock_requires_lock_held (ep_buffer_manager_get_rt_lock_cref (buffer_manager)); +} +#endif + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_buffer_manager; +const char quiet_linker_empty_file_warning_eventpipe_buffer_manager = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-buffer-manager.h b/src/mono/mono/eventpipe/ep-buffer-manager.h new file mode 100644 index 0000000000000..2676114076bf4 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-buffer-manager.h @@ -0,0 +1,69 @@ +#ifndef __EVENTPIPE_BUFFERMANAGER_H__ +#define __EVENTPIPE_BUFFERMANAGER_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeBufferList. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +//TODO: Implement. +struct _EventPipeBufferList { +#else +struct _EventPipeBufferList_Internal { +#endif + uint8_t x; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeBufferList { + uint8_t _internal [sizeof (struct _EventPipeBufferList_Internal)]; +}; +#endif + +/* + * EventPipeBufferManager. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +//TODO: Implement. +struct _EventPipeBufferManager { +#else +struct _EventPipeBufferManager_Internal { +#endif + ep_rt_wait_event_handle_t rt_wait_event; + ep_rt_spin_lock_handle_t rt_lock; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeBufferManager { + uint8_t _internal [sizeof (struct _EventPipeBufferManager_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeBufferManager *, buffer_manager, ep_rt_wait_event_handle_t *, rt_wait_event) +EP_DEFINE_GETTER_REF(EventPipeBufferManager *, buffer_manager, ep_rt_spin_lock_handle_t *, rt_lock); + +EventPipeBufferManager * +ep_buffer_manager_alloc ( + EventPipeSession *session, + size_t max_size_of_all_buffers, + size_t sequence_point_allocation_budget); + +void +ep_buffer_manager_free (EventPipeBufferManager *buffer_manager); + +#ifdef EP_CHECKED_BUILD +void +ep_buffer_manager_requires_lock_held (const EventPipeBufferManager *buffer_manager); +#else +#define ep_buffer_manager_requires_lock_held(x) +#endif + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_BUFFERMANAGER_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-buffer.h b/src/mono/mono/eventpipe/ep-buffer.h new file mode 100644 index 0000000000000..cfc5f66c3e193 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-buffer.h @@ -0,0 +1,40 @@ +#ifndef __EVENTPIPE_BUFFER_H__ +#define __EVENTPIPE_BUFFER_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeBuffer. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +//TODO: Implement. +struct _EventPipeBuffer { +#else +struct _EventPipeBuffer_Internal { +#endif + volatile uint32_t state; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeBuffer { + uint8_t _internal [sizeof (struct _EventPipeBuffer_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeBuffer *, buffer, volatile uint32_t *, state) + +static +inline +void +ep_buffer_convert_to_read_only (EventPipeBuffer *buffer) +{ + //TODO: Implement. +} + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_BUFFER_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-config-internals.c b/src/mono/mono/eventpipe/ep-config-internals.c new file mode 100644 index 0000000000000..a26d76a7c0ac9 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-config-internals.c @@ -0,0 +1,68 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +EventPipeConfiguration _ep_config = { { 0 }, 0 }; + +/* + * EventPipeEventMetadataEvent. + */ + +EventPipeEventMetadataEvent * +ep_event_metdata_event_alloc ( + EventPipeEvent *ep_event, + uint32_t proc_num, + uint64_t thread_id, + uint8_t *data, + uint32_t data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id) +{ + EventPipeEventMetadataEvent *instance = ep_rt_object_alloc (EventPipeEventMetadataEvent); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_event_instance_init ( + &instance->event_instance, + ep_event, + proc_num, + thread_id, + data, + data_len, + activity_id, + related_activity_id) != NULL); + + instance->payload_buffer = data; + instance->payload_buffer_len = data_len; + +ep_on_exit: + return instance; + +ep_on_error: + ep_event_metdata_event_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_event_metdata_event_free (EventPipeEventMetadataEvent *metadata_event) +{ + ep_return_void_if_nok (metadata_event != NULL); + + ep_event_instance_fini (&metadata_event->event_instance); + ep_rt_byte_array_free (metadata_event->payload_buffer); + ep_rt_object_free (metadata_event); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_configuration_internals; +const char quiet_linker_empty_file_warning_eventpipe_configuration_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-config.c b/src/mono/mono/eventpipe/ep-config.c new file mode 100644 index 0000000000000..24b6461adfed0 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-config.c @@ -0,0 +1,553 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +config_compute_keyword_and_level_lock_held ( + const EventPipeConfiguration *config, + const EventPipeProvider *provider, + int64_t *keyword_for_all_sessions, + EventPipeEventLevel *level_for_all_sessions); + +static +bool +config_register_provider_lock_held ( + EventPipeConfiguration *config, + EventPipeProvider *provider, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +static +bool +config_unregister_provider_lock_held ( + EventPipeConfiguration *config, + EventPipeProvider *provider); + +/* + * EventPipeConfiguration. + */ + +static +void +config_compute_keyword_and_level_lock_held ( + const EventPipeConfiguration *config, + const EventPipeProvider *provider, + int64_t *keyword_for_all_sessions, + EventPipeEventLevel *level_for_all_sessions) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (provider != NULL); + EP_ASSERT (keyword_for_all_sessions != NULL); + EP_ASSERT (level_for_all_sessions != NULL); + + *keyword_for_all_sessions = 0; + *level_for_all_sessions = EP_EVENT_LEVEL_LOG_ALWAYS; + + for (int i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; i++) { + // Entering EventPipe lock gave us a barrier, we don't need more of them. + EventPipeSession *session = ep_volatile_load_session_without_barrier (i); + if (session) { + EventPipeSessionProviderList *providers = ep_session_get_providers (session); + EP_ASSERT (providers != NULL); + + EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (providers), ep_provider_get_provider_name (provider)); + if (session_provider) { + *keyword_for_all_sessions = *keyword_for_all_sessions | ep_session_provider_get_keywords (session_provider); + *level_for_all_sessions = (ep_session_provider_get_logging_level (session_provider) > *level_for_all_sessions) ? ep_session_provider_get_logging_level (session_provider) : *level_for_all_sessions; + } + } + } + + ep_rt_config_requires_lock_held (); + return; +} + +static +bool +config_register_provider_lock_held ( + EventPipeConfiguration *config, + EventPipeProvider *provider, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (config != NULL); + EP_ASSERT (provider != NULL); + + // See if we've already registered this provider. + EventPipeProvider *existing_provider = ep_config_get_provider_lock_held (config, ep_provider_get_provider_name (provider)); + if (existing_provider) + return false; + + // The provider has not been registered, so register it. + ep_rt_provider_list_append (ep_config_get_provider_list_ref (config), provider); + + int64_t keyword_for_all_sessions; + EventPipeEventLevel level_for_all_sessions; + config_compute_keyword_and_level_lock_held (config, provider, &keyword_for_all_sessions, &level_for_all_sessions); + + for (int i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; i++) { + // Entering EventPipe lock gave us a barrier, we don't need more of them. + EventPipeSession *session = ep_volatile_load_session_without_barrier (i); + if (session) { + EventPipeSessionProviderList *providers = ep_session_get_providers (session); + EP_ASSERT (providers != NULL); + + EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (providers), ep_provider_get_provider_name (provider)); + if (session_provider) { + EventPipeProviderCallbackData provider_callback_data; + ep_provider_set_config_lock_held ( + provider, + keyword_for_all_sessions, + level_for_all_sessions, + ((uint64_t)1 << ep_session_get_index (session)), + ep_session_provider_get_keywords (session_provider), + ep_session_provider_get_logging_level (session_provider), + ep_session_provider_get_filter_data (session_provider), + &provider_callback_data); + ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, &provider_callback_data); + } + } + } + + ep_rt_config_requires_lock_held (); + return true; +} + +static +bool +config_unregister_provider_lock_held ( + EventPipeConfiguration *config, + EventPipeProvider *provider) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (config != NULL); + + EventPipeProvider *existing_provider = NULL; + ep_rt_provider_list_t *provider_list = ep_config_get_provider_list_ref (config); + + // The provider list should be non-NULL, but can be NULL on shutdown. + if (!ep_rt_provider_list_is_empty (provider_list)) { + // If we found the provider, remove it. + if (ep_rt_provider_list_find (provider_list, provider, &existing_provider)) + ep_rt_provider_list_remove (provider_list, existing_provider); + } + + ep_rt_config_requires_lock_held (); + return (existing_provider != NULL); +} + +EventPipeConfiguration * +ep_config_init (EventPipeConfiguration *config) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_false_if_nok (config != NULL); + + ep_config_set_config_provider (config, ep_create_provider (ep_config_get_default_provider_name_utf8 (), NULL, NULL)); + ep_raise_error_if_nok (ep_config_get_config_provider (config) != NULL); + + // Create the metadata event. + ep_config_set_metadata_event (config, ep_provider_add_event ( + ep_config_get_config_provider (config), + 0, /* event_id */ + 0, /* keywords */ + 0, /* event_version */ + EP_EVENT_LEVEL_LOG_ALWAYS, + false, /* need_stack */ + NULL, /* meatadata */ + 0)); /* metadata_len */ + ep_raise_error_if_nok (ep_config_get_metadata_event (config) != NULL); + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return config; + +ep_on_error: + ep_config_shutdown (config); + + config = NULL; + ep_exit_error_handler (); +} + +void +ep_config_shutdown (EventPipeConfiguration *config) +{ + ep_rt_config_requires_lock_not_held (); + + ep_event_free (ep_config_get_metadata_event (config)); + ep_config_set_metadata_event (config, NULL); + + ep_delete_provider (ep_config_get_config_provider (config)); + ep_config_set_config_provider (config, NULL); + + // Take the lock before manipulating the list. + EP_CONFIG_LOCK_ENTER + // We don't delete provider itself because it can be in-use + ep_rt_provider_list_free (ep_config_get_provider_list_ref (config), NULL); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +EventPipeProvider * +ep_config_create_provider ( + EventPipeConfiguration *config, + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_null_if_nok (config != NULL && provider_name != NULL); + + EventPipeProvider *provider = NULL; + EP_CONFIG_LOCK_ENTER + provider = ep_config_create_provider_lock_held (config, provider_name, callback_func, callback_data, provider_callback_data_queue); + ep_raise_error_if_nok_holding_lock (provider != NULL); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return provider; + +ep_on_error: + ep_config_delete_provider (config, provider); + + provider = NULL; + ep_exit_error_handler (); +} + +void +ep_config_delete_provider ( + EventPipeConfiguration *config, + EventPipeProvider *provider) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_void_if_nok (config != NULL && provider != NULL); + + EP_CONFIG_LOCK_ENTER + ep_config_delete_provider_lock_held (config, provider); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +void +ep_config_enable ( + EventPipeConfiguration *config, + const EventPipeSession *session, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_void_if_nok (config != NULL && session != NULL); + + EP_CONFIG_LOCK_ENTER + ep_config_enable_disable_lock_held (config, session, provider_callback_data_queue, true); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +void +ep_config_disable ( + EventPipeConfiguration *config, + const EventPipeSession *session, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_void_if_nok (config != NULL && session != NULL); + + EP_CONFIG_LOCK_ENTER + ep_config_enable_disable_lock_held (config, session, provider_callback_data_queue, false); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +EventPipeEventMetadataEvent * +ep_config_build_event_metadata_event ( + EventPipeConfiguration *config, + const EventPipeEventInstance *source_instance, + uint32_t metadata_id) +{ + ep_return_null_if_nok (config != NULL && source_instance != NULL); + + // The payload of the event should contain: + // - Metadata ID + // - GUID ProviderID. + // - Optional event description payload. + + uint8_t *instance_payload = NULL; + + // Calculate the size of the event. + EventPipeEvent *source_event = ep_event_instance_get_ep_event (source_instance); + EventPipeProvider *provider = ep_event_get_provider (source_event); + const ep_char16_t *provider_name_utf16 = ep_provider_get_provider_name_utf16 (provider); + const uint8_t *payload_data = ep_event_instance_get_data (source_instance); + uint32_t payload_data_len = ep_event_instance_get_data_len (source_instance); + uint32_t provider_name_len = (ep_rt_utf16_string_len (provider_name_utf16) + 1) * sizeof (ep_char16_t); + uint32_t instance_payload_size = sizeof (metadata_id) + provider_name_len + payload_data_len; + + // Allocate the payload. + instance_payload = ep_rt_byte_array_alloc (instance_payload_size); + ep_raise_error_if_nok (instance_payload != NULL); + + // Fill the buffer with the payload. + uint8_t *current = instance_payload; + + memcpy(current, &metadata_id, sizeof(metadata_id)); + current += sizeof(metadata_id); + + memcpy(current, provider_name_utf16, provider_name_len); + current += provider_name_len; + + // Write the incoming payload data. + memcpy(current, payload_data, payload_data_len); + + // Construct the metadata event instance. + EventPipeEventMetadataEvent *instance = ep_event_metdata_event_alloc ( + ep_config_get_metadata_event (config), + ep_rt_current_processor_get_number (), + ep_rt_current_thread_get_id (), + instance_payload, + instance_payload_size, + NULL /* pActivityId */, + NULL /* pRelatedActivityId */); + + ep_raise_error_if_nok (instance != NULL); + instance_payload = NULL; + + EP_ASSERT (ep_event_get_need_stack (ep_config_get_metadata_event (config)) == false); + + // Set the timestamp to match the source event, because the metadata event + // will be emitted right before the source event. + ep_event_instance_set_timestamp ((EventPipeEventInstance *)instance, ep_event_instance_get_timestamp (source_instance)); + +ep_on_exit: + return instance; + +ep_on_error: + ep_rt_byte_array_free (instance_payload); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_config_delete_deferred_providers (EventPipeConfiguration *config) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_void_if_nok (config != NULL); + + EP_CONFIG_LOCK_ENTER + ep_config_delete_deferred_providers_lock_held (config); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +EventPipeSessionProvider * +ep_config_get_session_provider_lock_held ( + const EventPipeConfiguration *config, + const EventPipeSession *session, + const EventPipeProvider *provider) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (config != NULL && session != NULL); + + EventPipeSessionProvider *existing_provider = ep_session_get_session_provider_lock_held (session, provider); + + ep_rt_config_requires_lock_held (); + return existing_provider; +} + +EventPipeProvider * +ep_config_get_provider_lock_held ( + EventPipeConfiguration *config, + const ep_char8_t *name) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (config != NULL && name != NULL); + + // The provider list should be non-NULL, but can be NULL on shutdown. + ep_return_null_if_nok (ep_rt_provider_list_is_empty (ep_config_get_provider_list_cref (config)) != true); + EventPipeProvider *provider = ep_rt_provider_list_find_by_name (ep_config_get_provider_list_cref (config), name); + + ep_rt_config_requires_lock_held (); + return provider; +} + +EventPipeProvider * +ep_config_create_provider_lock_held ( + EventPipeConfiguration *config, + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (config != NULL && provider_name != NULL); + + EventPipeProvider *provider = ep_provider_alloc (config, provider_name, callback_func, callback_data); + ep_raise_error_if_nok (provider != NULL); + ep_raise_error_if_nok (config_register_provider_lock_held (config, provider, provider_callback_data_queue) == true); + +ep_on_exit: + ep_rt_config_requires_lock_held (); + return provider; + +ep_on_error: + ep_config_delete_provider_lock_held (config, provider); + + provider = NULL; + ep_exit_error_handler (); +} + +void +ep_config_delete_provider_lock_held ( + EventPipeConfiguration *config, + EventPipeProvider *provider) +{ + ep_rt_config_requires_lock_held (); + + ep_return_void_if_nok (config != NULL); + + config_unregister_provider_lock_held (config, provider); + ep_provider_free (provider); + + ep_rt_config_requires_lock_held (); + return; +} + +void +ep_config_delete_deferred_providers_lock_held (EventPipeConfiguration *config) +{ + ep_rt_config_requires_lock_held (); + + ep_return_void_if_nok (config != NULL); + + // The provider list should be non-NULL, but can be NULL on shutdown. + const ep_rt_provider_list_t *provider_list = ep_config_get_provider_list_ref (config); + if (!ep_rt_provider_list_is_empty (provider_list)) { + ep_rt_provider_list_iterator_t iterator; + ep_rt_provider_list_iterator_begin (provider_list, &iterator); + + while (!ep_rt_provider_list_iterator_end (provider_list, &iterator)) { + EventPipeProvider *provider = ep_rt_provider_list_iterator_value (&iterator); + EP_ASSERT (provider != NULL); + + // Get next item before deleting current. + ep_rt_provider_list_iterator_next (provider_list, &iterator); + if (ep_provider_get_delete_deferred (provider)) + ep_config_delete_provider_lock_held (config, provider); + } + } + + ep_rt_config_requires_lock_held (); + return; +} + +void +ep_config_enable_disable_lock_held ( + EventPipeConfiguration *config, + const EventPipeSession *session, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue, + bool enable) +{ + ep_rt_config_requires_lock_held (); + + ep_return_void_if_nok (config != NULL && session != NULL); + + // The provider list should be non-NULL, but can be NULL on shutdown. + const ep_rt_provider_list_t *provider_list = ep_config_get_provider_list_cref (config); + if (!ep_rt_provider_list_is_empty (provider_list)) { + ep_rt_provider_list_iterator_t iterator; + for (ep_rt_provider_list_iterator_begin (provider_list, &iterator); !ep_rt_provider_list_iterator_end (provider_list, &iterator); ep_rt_provider_list_iterator_next (provider_list, &iterator)) { + EventPipeProvider *provider = ep_rt_provider_list_iterator_value (&iterator); + if (provider) { + // Enable/Disable the provider if it has been configured. + EventPipeSessionProvider *session_provider = ep_config_get_session_provider_lock_held (config, session, provider); + if (session_provider) { + int64_t keyword_for_all_sessions; + EventPipeEventLevel level_for_all_sessions; + EventPipeProviderCallbackData provider_callback_data; + config_compute_keyword_and_level_lock_held (config, provider, &keyword_for_all_sessions, &level_for_all_sessions); + if (enable) { + ep_provider_set_config_lock_held ( + provider, + keyword_for_all_sessions, + level_for_all_sessions, + ep_session_get_mask (session), + ep_session_provider_get_keywords (session_provider), + ep_session_provider_get_logging_level (session_provider), + ep_session_provider_get_filter_data (session_provider), + &provider_callback_data); + } else { + ep_provider_unset_config_lock_held ( + provider, + keyword_for_all_sessions, + level_for_all_sessions, + ep_session_get_mask (session), + ep_session_provider_get_keywords (session_provider), + ep_session_provider_get_logging_level (session_provider), + ep_session_provider_get_filter_data (session_provider), + &provider_callback_data); + } + ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, &provider_callback_data); + } + } + } + } + + ep_rt_config_requires_lock_held (); + return; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_configuration; +const char quiet_linker_empty_file_warning_eventpipe_configuration = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-config.h b/src/mono/mono/eventpipe/ep-config.h new file mode 100644 index 0000000000000..577b78f8643bc --- /dev/null +++ b/src/mono/mono/eventpipe/ep-config.h @@ -0,0 +1,184 @@ +#ifndef __EVENTPIPE_CONFIGURATION_H__ +#define __EVENTPIPE_CONFIGURATION_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeConfiguration. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeConfiguration { +#else +struct _EventPipeConfiguration_Internal { +#endif + ep_rt_provider_list_t provider_list; + EventPipeProvider *config_provider; + EventPipeEvent *metadata_event; + ep_char8_t *config_provider_name; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeConfiguration { + uint8_t _internal [sizeof (struct _EventPipeConfiguration_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeConfiguration *, config, ep_rt_provider_list_t *, provider_list) +EP_DEFINE_GETTER(EventPipeConfiguration *, config, EventPipeProvider *, config_provider) +EP_DEFINE_SETTER(EventPipeConfiguration *, config, EventPipeProvider *, config_provider) +EP_DEFINE_GETTER(EventPipeConfiguration *, config, EventPipeEvent *, metadata_event) +EP_DEFINE_SETTER(EventPipeConfiguration *, config, EventPipeEvent *, metadata_event) +EP_DEFINE_GETTER(EventPipeConfiguration *, config, const ep_char8_t *, config_provider_name) + +static +inline +const ep_char8_t * +ep_config_get_default_provider_name_utf8 (void) +{ + return "Microsoft-DotNETCore-EventPipeConfiguration"; +} + +static +inline +const ep_char8_t * +ep_config_get_public_provider_name_utf8 (void) +{ + return "Microsoft-Windows-DotNETRuntime"; +} + +static +inline +const ep_char8_t * +ep_config_get_rundown_provider_name_utf8 (void) +{ + return "Microsoft-Windows-DotNETRuntimeRundown"; +} + +static +inline +EventPipeConfiguration * +ep_config_get (void) +{ + // Singelton. + extern EventPipeConfiguration _ep_config; + return &_ep_config; +} + +EventPipeConfiguration * +ep_config_init (EventPipeConfiguration *config); + +void +ep_config_shutdown (EventPipeConfiguration *config); + +EventPipeProvider * +ep_config_create_provider ( + EventPipeConfiguration *config, + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +void +ep_config_delete_provider ( + EventPipeConfiguration *config, + EventPipeProvider *provider); + +void +ep_config_enable ( + EventPipeConfiguration *config, + const EventPipeSession *session, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +void +ep_config_disable ( + EventPipeConfiguration *config, + const EventPipeSession *session, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +EventPipeEventMetadataEvent * +ep_config_build_event_metadata_event ( + EventPipeConfiguration *config, + const EventPipeEventInstance *source_instance, + uint32_t metadata_id); + +void +ep_config_delete_deferred_providers (EventPipeConfiguration *config); + +EventPipeSessionProvider * +ep_config_get_session_provider_lock_held ( + const EventPipeConfiguration *config, + const EventPipeSession *session, + const EventPipeProvider *provider); + +EventPipeProvider * +ep_config_get_provider_lock_held ( + EventPipeConfiguration *config, + const ep_char8_t *name); + +EventPipeProvider * +ep_config_create_provider_lock_held ( + EventPipeConfiguration *config, + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +void +ep_config_delete_provider_lock_held ( + EventPipeConfiguration *config, + EventPipeProvider *provider); + +void +ep_config_delete_deferred_providers_lock_held (EventPipeConfiguration *config); + +void +ep_config_enable_disable_lock_held ( + EventPipeConfiguration *config, + const EventPipeSession *session, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue, + bool enable); + +/* + * EventPipeEventMetadataEvent. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventMetadataEvent { +#else +struct _EventPipeEventMetadataEvent_Internal { +#endif + EventPipeEventInstance event_instance; + uint8_t *payload_buffer; + uint32_t payload_buffer_len; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventMetadataEvent { + uint8_t _internal [sizeof (struct _EventPipeEventMetadataEvent_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeEventMetadataEvent *, event_metadata_event, uint8_t *, payload_buffer) +EP_DEFINE_GETTER(EventPipeEventMetadataEvent *, event_instance, uint32_t, payload_buffer_len) + + +EventPipeEventMetadataEvent * +ep_event_metdata_event_alloc ( + EventPipeEvent *ep_event, + uint32_t proc_num, + uint64_t thread_id, + uint8_t *data, + uint32_t data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id); + +void +ep_event_metdata_event_free (EventPipeEventMetadataEvent *metadata_event); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_CONFIGURATION_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-event-instance-internals.c b/src/mono/mono/eventpipe/ep-event-instance-internals.c new file mode 100644 index 0000000000000..123675616d8f9 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-instance-internals.c @@ -0,0 +1,143 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventPipeEventInstance. + */ + +EventPipeEventInstance * +ep_event_instance_alloc ( + EventPipeEvent *ep_event, + uint32_t proc_num, + uint64_t thread_id, + const uint8_t *data, + uint32_t data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id) +{ + EventPipeEventInstance *instance = ep_rt_object_alloc (EventPipeEventInstance); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_event_instance_init ( + instance, + ep_event, + proc_num, + thread_id, + data, + data_len, + activity_id, + related_activity_id) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + ep_event_instance_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +EventPipeEventInstance * +ep_event_instance_init ( + EventPipeEventInstance *event_instance, + EventPipeEvent *ep_event, + uint32_t proc_num, + uint64_t thread_id, + const uint8_t *data, + uint32_t data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id) +{ + EP_ASSERT (event_instance != NULL); + ep_return_null_if_nok (ep_event != NULL); + +#ifdef EP_CHECKED_BUILD + event_instance->debug_event_start = 0xDEADBEEF; + event_instance->debug_event_end = 0xCAFEBABE; +#endif + + event_instance->ep_event = ep_event; + event_instance->proc_num = proc_num; + event_instance->thread_id = thread_id; + + if (activity_id) + memcpy (&(event_instance->activity_id), activity_id, EP_ACTIVITY_ID_SIZE); + + if (related_activity_id) + memcpy (&(event_instance->related_activity_id), related_activity_id, EP_ACTIVITY_ID_SIZE); + + event_instance->data = data; + event_instance->data_len = data_len; + + event_instance->timestamp = ep_perf_counter_query (); + EP_ASSERT (event_instance->timestamp > 0); + + ep_event_instance_ensure_consistency (event_instance); + + return event_instance; +} + +void +ep_event_instance_fini (EventPipeEventInstance *ep_event_instance) +{ + ; +} + +void +ep_event_instance_free (EventPipeEventInstance *ep_event_instance) +{ + ep_return_void_if_nok (ep_event_instance != NULL); + + ep_event_instance_fini (ep_event_instance); + ep_rt_object_free (ep_event_instance); +} + +/* + * EventPipeSequencePoint. + */ + +EventPipeSequencePoint * +ep_sequence_point_init (EventPipeSequencePoint *sequence_point) +{ + EP_ASSERT (sequence_point != NULL); + + sequence_point->timestamp = 0; + sequence_point->thread_sequence_numbers.table = NULL; + sequence_point->thread_sequence_numbers.count = 0; + + return sequence_point; +} + +void +ep_sequence_point_fini (EventPipeSequencePoint *sequence_point) +{ + ep_return_void_if_nok (sequence_point != NULL); + + // Each entry in the map owns a ref-count on the corresponding thread + if (sequence_point->thread_sequence_numbers.table) { + ep_rt_thread_sequence_number_hash_map_iterator_t iterator; + for ( + ep_rt_thread_sequence_number_map_iterator_begin (&sequence_point->thread_sequence_numbers, &iterator); + !ep_rt_thread_sequence_number_map_iterator_end (&sequence_point->thread_sequence_numbers, &iterator); + ep_rt_thread_sequence_number_map_iterator_next (&sequence_point->thread_sequence_numbers, &iterator)) { + + EventPipeThreadSessionState *key = ep_rt_thread_sequence_number_map_iterator_key (&iterator); + ep_thread_release (ep_thread_session_state_get_thread (key)); + } + } +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_event_instance_internals; +const char quiet_linker_empty_file_warning_eventpipe_event_instance_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-event-instance.c b/src/mono/mono/eventpipe/ep-event-instance.c new file mode 100644 index 0000000000000..1702b5d922c87 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-instance.c @@ -0,0 +1,93 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * EventPipeEventInstance. + */ + +bool +ep_event_instance_ensure_consistency (const EventPipeEventInstance *ep_event_instance) +{ +#ifdef EP_CHECKED_BUILD + EP_ASSERT (ep_event_instance_get_debug_event_start (ep_event_instance) == 0xDEADBEEF); + EP_ASSERT (ep_event_instance_get_debug_event_end (ep_event_instance) == 0xCAFEBABE); +#endif + + return true; +} + +uint32_t +ep_event_instance_get_aligned_total_size ( + const EventPipeEventInstance *ep_event_instance, + EventPipeSerializationFormat format) +{ + // Calculate the size of the total payload so that it can be written to the file. + uint32_t payload_len = 0; + + if (format == EP_SERIALIZATION_FORMAT_NETPERF_V3) { + payload_len = + // Metadata ID + ep_event_instance_sizeof_metadata_id (ep_event_instance) + + // Thread ID + sizeof (int32_t) + + // TimeStamp + ep_event_instance_sizeof_timestamp (ep_event_instance) + + // Activity ID + EP_ACTIVITY_ID_SIZE + + // Related Activity ID + EP_ACTIVITY_ID_SIZE + + // Data payload length + ep_event_instance_sizeof_data_len (ep_event_instance) + + // Event payload data + ep_event_instance_get_data_len (ep_event_instance) + + // Prepended stack payload size in bytes + sizeof (uint32_t) + + // Stack payload size + ep_stack_contents_get_size (ep_event_instance_get_stack_contents_cref (ep_event_instance)); + } else if (format == EP_SERIALIZATION_FORMAT_NETTRACE_V4) { + payload_len = + // Metadata ID + ep_event_instance_sizeof_metadata_id (ep_event_instance) + + // Sequence number (implied by the buffer containing the event instance) + sizeof (uint32_t) + + // Thread ID + sizeof (int32_t) + + // Capture Thread ID (implied by the buffer containing the event instance) + sizeof (uint64_t) + + // ProcNumber + ep_event_instance_sizeof_proc_num (ep_event_instance) + + // Stack intern table id + sizeof (uint32_t) + + // TimeStamp + ep_event_instance_sizeof_timestamp (ep_event_instance) + + // Activity ID + EP_ACTIVITY_ID_SIZE + + // Related Activity ID + EP_ACTIVITY_ID_SIZE + + // Data payload length + ep_event_instance_sizeof_data_len (ep_event_instance) + + // Event payload data + ep_event_instance_get_data_len (ep_event_instance); + } else { + EP_ASSERT (!"Unrecognized format"); + } + + // round up to FAST_SERIALIZER_ALIGNMENT_SIZE bytes + if (payload_len % FAST_SERIALIZER_ALIGNMENT_SIZE != 0) + payload_len += FAST_SERIALIZER_ALIGNMENT_SIZE - (payload_len % FAST_SERIALIZER_ALIGNMENT_SIZE); + + return payload_len; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_event_instance; +const char quiet_linker_empty_file_warning_eventpipe_event_instance = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-event-instance.h b/src/mono/mono/eventpipe/ep-event-instance.h new file mode 100644 index 0000000000000..391e7d36f3774 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-instance.h @@ -0,0 +1,122 @@ +#ifndef __EVENTPIPE_EVENTINSTANCE_H__ +#define __EVENTPIPE_EVENTINSTANCE_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeEventInstance. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventInstance { +#else +struct _EventPipeEventInstance_Internal { +#endif +#ifdef EP_CHECKED_BUILD + uint32_t debug_event_start; + uint32_t debug_event_end; +#endif + EventPipeEvent *ep_event; + uint32_t metadata_id; + uint32_t proc_num; + uint64_t thread_id; + uint64_t timestamp; + uint8_t activity_id [EP_ACTIVITY_ID_SIZE]; + uint8_t related_activity_id [EP_ACTIVITY_ID_SIZE]; + const uint8_t *data; + uint32_t data_len; + EventPipeStackContents stack_contents; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventInstance { + uint8_t _internal [sizeof (struct _EventPipeEventInstance_Internal)]; +}; +#endif + +#ifdef EP_CHECKED_BUILD +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint32_t, debug_event_start) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint32_t, debug_event_end) +#endif +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, EventPipeEvent *, ep_event) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint32_t, metadata_id) +EP_DEFINE_SETTER(EventPipeEventInstance *, event_instance, uint32_t, metadata_id) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint32_t, proc_num) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint64_t, thread_id) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint64_t, timestamp) +EP_DEFINE_SETTER(EventPipeEventInstance *, event_instance, uint64_t, timestamp) +EP_DEFINE_GETTER_ARRAY_REF(EventPipeEventInstance *, event_instance, uint8_t *, const uint8_t *, activity_id, activity_id[0]) +EP_DEFINE_GETTER_ARRAY_REF(EventPipeEventInstance *, event_instance, uint8_t *, const uint8_t *, related_activity_id, related_activity_id[0]) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, const uint8_t *, data) +EP_DEFINE_GETTER(EventPipeEventInstance *, event_instance, uint32_t, data_len) +EP_DEFINE_GETTER_REF(EventPipeEventInstance *, event_instance, EventPipeStackContents *, stack_contents) + +EventPipeEventInstance * +ep_event_instance_alloc ( + EventPipeEvent *ep_event, + uint32_t proc_num, + uint64_t thread_id, + const uint8_t *data, + uint32_t data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id); + +EventPipeEventInstance * +ep_event_instance_init ( + EventPipeEventInstance *ep_event_instance, + EventPipeEvent *ep_event, + uint32_t proc_num, + uint64_t thread_id, + const uint8_t *data, + uint32_t data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id); + +void +ep_event_instance_fini (EventPipeEventInstance *ep_event_instance); + +void +ep_event_instance_free (EventPipeEventInstance *ep_event_instance); + +bool +ep_event_instance_ensure_consistency (const EventPipeEventInstance *ep_event_instance); + +uint32_t +ep_event_instance_get_aligned_total_size ( + const EventPipeEventInstance *ep_event_instance, + EventPipeSerializationFormat format); + +/* + * EventPipeSequencePoint. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSequencePoint { +#else +struct _EventPipeSequencePoint_Internal { +#endif + uint64_t timestamp; + ep_rt_thread_sequence_number_hash_map_t thread_sequence_numbers; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSequencePoint { + uint8_t _internal [sizeof (struct _EventPipeSequencePoint_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeSequencePoint *, sequence_point, uint64_t, timestamp) +EP_DEFINE_GETTER_REF(EventPipeSequencePoint *, sequence_point, ep_rt_thread_sequence_number_hash_map_t *, thread_sequence_numbers) + +EventPipeSequencePoint * +ep_sequence_point_init (EventPipeSequencePoint *sequence_point); + +void +ep_sequence_point_fini (EventPipeSequencePoint *sequence_point); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_EVENTINSTANCE_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-event-internals.c b/src/mono/mono/eventpipe/ep-event-internals.c new file mode 100644 index 0000000000000..02c9469d28f59 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-internals.c @@ -0,0 +1,111 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +event_build_minimum_metadata ( + EventPipeEvent *ep_event, + uint8_t **metadata, + uint32_t *metadata_len); + +/* + * EventPipeEvent. + */ + +static +void +event_build_minimum_metadata ( + EventPipeEvent *ep_event, + uint8_t **metadata, + uint32_t *metadata_len) +{ + EP_ASSERT (ep_event != NULL); + EP_ASSERT (metadata != NULL); + EP_ASSERT (metadata_len != NULL); + + size_t output_len = 0; + ep_char16_t empty_string [1] = { 0 }; + *metadata = ep_metadata_generator_generate_event_metadata ( + ep_event->event_id, + empty_string, + ep_event->keywords, + ep_event->event_version, + ep_event->level, + NULL, + 0, + &output_len); + + *metadata_len = (uint32_t)output_len; +} + +EventPipeEvent * +ep_event_alloc ( + EventPipeProvider *provider, + uint64_t keywords, + uint32_t event_id, + uint32_t event_version, + EventPipeEventLevel level, + bool need_stack, + const uint8_t *metadata, + uint32_t metadata_len) +{ + ep_return_null_if_nok (provider != NULL); + + EventPipeEvent *instance = ep_rt_object_alloc (EventPipeEvent); + ep_raise_error_if_nok (instance != NULL); + + instance->provider = provider; + instance->keywords = keywords; + instance->event_id = event_id; + instance->event_version = event_version; + instance->level = level; + instance->need_stack = need_stack; + instance->enabled_mask = 0; + + if (metadata != NULL) { + instance->metadata = ep_rt_byte_array_alloc (metadata_len); + ep_raise_error_if_nok (instance->metadata != NULL); + + memcpy (instance->metadata, metadata, metadata_len); + instance->metadata_len = metadata_len; + } else { + // if metadata is not provided, we have to build the minimum version. It's required by the serialization contract. + event_build_minimum_metadata (instance, &(instance->metadata), &(instance->metadata_len)); + } + +ep_on_exit: + return instance; + +ep_on_error: + ep_event_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_event_free (EventPipeEvent *ep_event) +{ + ep_return_void_if_nok (ep_event != NULL); + + ep_rt_byte_array_free (ep_event->metadata); + ep_rt_object_free (ep_event); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_event_internals; +const char quiet_linker_empty_file_warning_eventpipe_event_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-event-payload-internals.c b/src/mono/mono/eventpipe/ep-event-payload-internals.c new file mode 100644 index 0000000000000..1be0b43138e75 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-payload-internals.c @@ -0,0 +1,70 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventData. + */ + +EventData * +ep_event_data_alloc ( + uint64_t ptr, + uint32_t size, + uint32_t reserved) +{ + EventData *instance = ep_rt_object_alloc (EventData); + ep_raise_error_if_nok (ep_event_data_init (instance, ptr, size,reserved)); + +ep_on_exit: + return instance; + +ep_on_error: + ep_event_data_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +EventData * +ep_event_data_init ( + EventData *event_data, + uint64_t ptr, + uint32_t size, + uint32_t reserved) +{ + EP_ASSERT (event_data != NULL); + + event_data->ptr = ptr; + event_data->size = size; + event_data->reserved = reserved; + + return event_data; +} + +void +ep_event_data_fini (EventData *event_data) +{ + ; +} + +void +ep_event_data_free (EventData *event_data) +{ + ep_return_void_if_nok (event_data != NULL); + + ep_event_data_fini (event_data); + ep_rt_object_free (event_data); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_event_payload_internals; +const char quiet_linker_empty_file_warning_eventpipe_event_payload_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-event-payload.h b/src/mono/mono/eventpipe/ep-event-payload.h new file mode 100644 index 0000000000000..58532d7b1416a --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-payload.h @@ -0,0 +1,54 @@ +#ifndef __EVENTPIPE_EVENT_PAYLOAD_H__ +#define __EVENTPIPE_EVENT_PAYLOAD_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventData. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventData { +#else +struct _EventData_Internal { +#endif + uint64_t ptr; + uint32_t size; + uint32_t reserved; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventData { + uint8_t _internal [sizeof (struct _EventData_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventData *, event_data, uint64_t, ptr) +EP_DEFINE_GETTER(EventData *, event_data, uint32_t, size) +EP_DEFINE_GETTER(EventData *, event_data, uint32_t, reserved) + +EventData * +ep_event_data_alloc ( + uint64_t ptr, + uint32_t size, + uint32_t reserved); + +EventData * +ep_event_data_init ( + EventData *event_data, + uint64_t ptr, + uint32_t size, + uint32_t reserved); + +void +ep_event_data_fini (EventData *event_data); + +void +ep_event_data_free (EventData *event_data); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_EVENT_PAYLOAD_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-event-source-internals.c b/src/mono/mono/eventpipe/ep-event-source-internals.c new file mode 100644 index 0000000000000..e283a37030a34 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-source-internals.c @@ -0,0 +1,99 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventPipeEventSource. + */ + +EventPipeEventSource * +ep_event_source_alloc (void) +{ + ep_char16_t *command_line_arg_utf16 = NULL; + ep_char16_t *event_name_utf16 = NULL; + uint8_t *metadata = NULL; + + EventPipeEventSource *instance = ep_rt_object_alloc (EventPipeEventSource); + ep_raise_error_if_nok (instance != NULL); + + instance->provider = ep_create_provider (ep_provider_get_default_name_utf8 (), NULL, NULL); + ep_raise_error_if_nok (instance->provider != NULL); + + // Generate metadata. + EventPipeParameterDesc params [1]; + const uint32_t params_len = EP_ARRAY_SIZE (params); + + command_line_arg_utf16 = ep_rt_utf8_to_utf16_string ("CommandLine", -1); + ep_raise_error_if_nok (command_line_arg_utf16 != NULL); + + ep_parameter_desc_init (params, EP_PARAMETER_TYPE_STRING, command_line_arg_utf16); + + event_name_utf16 = ep_rt_utf8_to_utf16_string ("ProcessInfo", -1); + ep_raise_error_if_nok (event_name_utf16 != NULL); + + size_t metadata_len = 0; + metadata = ep_metadata_generator_generate_event_metadata ( + 1, /* eventID */ + event_name_utf16, + 0, /* keywords */ + 0, /* version */ + EP_EVENT_LEVEL_LOG_ALWAYS, + params, + params_len, + &metadata_len); + + ep_raise_error_if_nok (metadata != NULL); + + // Add the event. + instance->process_info_event = ep_provider_add_event ( + instance->provider, + 1, /* eventID */ + 0, /* keywords */ + 0, /* eventVersion */ + EP_EVENT_LEVEL_LOG_ALWAYS, + false, /* needStack */ + metadata, + (uint32_t)metadata_len); + + ep_raise_error_if_nok (instance->process_info_event); + + // Delete the metadata after the event is created. + // The metadata blob will be copied into EventPipe-owned memory. + ep_rt_byte_array_free (metadata); + + // Delete the strings after the event is created. + // The strings will be copied into EventPipe-owned memory. + ep_rt_utf16_string_free (event_name_utf16); + ep_rt_utf16_string_free (command_line_arg_utf16); + +ep_on_exit: + return instance; + +ep_on_error: + ep_rt_byte_array_free (metadata); + ep_rt_utf16_string_free (event_name_utf16); + ep_rt_utf16_string_free (command_line_arg_utf16); + ep_event_source_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_event_source_free (EventPipeEventSource *event_source) +{ + ep_provider_free (event_source->provider); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_event_source_internals; +const char quiet_linker_empty_file_warning_eventpipe_event_source_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-event-source.c b/src/mono/mono/eventpipe/ep-event-source.c new file mode 100644 index 0000000000000..94b1283e3b414 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-source.c @@ -0,0 +1,52 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * EventPipeEventSource. + */ + +static EventPipeEventSource *event_source_instance; + +void +ep_event_source_enable ( + EventPipeEventSource *event_source, + EventPipeSession *session) +{ + ep_return_void_if_nok (event_source != NULL); + ep_return_void_if_nok (session != NULL); + + EventPipeSessionProvider *session_provider = ep_session_provider_alloc (ep_event_source_get_provider_name (event_source), (uint64_t)-1, EP_EVENT_LEVEL_LOG_ALWAYS, NULL); + if (session_provider != NULL) + ep_session_add_session_provider (session, session_provider); +} + +void +ep_event_source_send_process_info ( + EventPipeEventSource * event_source, + const ep_char16_t *command_line) +{ + ep_return_void_if_nok (event_source != NULL); + + EventData data [1]; + ep_event_data_init (data, (uint64_t)command_line, (uint32_t)((ep_rt_utf16_string_len (command_line) + 1) * sizeof (ep_char16_t)), 0); + ep_write_event (ep_event_source_get_process_info_event (event_source), data, EP_ARRAY_SIZE (data), NULL, NULL); +} + +EventPipeEventSource * +ep_event_source_get (void) +{ + return event_source_instance; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_event_source; +const char quiet_linker_empty_file_warning_eventpipe_event_source = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-event-source.h b/src/mono/mono/eventpipe/ep-event-source.h new file mode 100644 index 0000000000000..3a2195c27778f --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event-source.h @@ -0,0 +1,51 @@ +#ifndef __EVENTPIPE_EVENT_SOURCE_H__ +#define __EVENTPIPE_EVENT_SOURCE_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeEventSource. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventSource { +#else +struct _EventPipeEventSource_Internal { +#endif + const ep_char8_t *provider_name; + EventPipeProvider *provider; + const ep_char8_t *process_info_event_name; + EventPipeEvent *process_info_event; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEventSource { + uint8_t _internal [sizeof (struct _EventPipeEventSource_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeEventSource *, event_source, const ep_char8_t *, provider_name) +EP_DEFINE_GETTER(EventPipeEventSource *, event_source, const ep_char8_t *, process_info_event_name) +EP_DEFINE_GETTER(EventPipeEventSource *, event_source, EventPipeEvent *, process_info_event) + +EventPipeEventSource * +ep_event_source_alloc (void); + +void +ep_event_source_free (EventPipeEventSource *event_source); + +void +ep_event_source_enable (EventPipeEventSource *event_source, EventPipeSession *session); + +void +ep_event_source_send_process_info (EventPipeEventSource *event_source, const ep_char16_t *command_line); + +EventPipeEventSource * +ep_event_source_get (void); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_EVENT_SOURCE_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-event.h b/src/mono/mono/eventpipe/ep-event.h new file mode 100644 index 0000000000000..8f0418b638ab9 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-event.h @@ -0,0 +1,64 @@ +#ifndef __EVENTPIPE_EVENT_H__ +#define __EVENTPIPE_EVENT_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeEvent. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEvent { +#else +struct _EventPipeEvent_Internal { +#endif + EventPipeProvider *provider; + uint64_t keywords; + uint32_t event_id; + uint32_t event_version; + EventPipeEventLevel level; + bool need_stack; + volatile int64_t enabled_mask; + uint8_t *metadata; + uint32_t metadata_len; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeEvent { + uint8_t _internal [sizeof (struct _EventPipeEvent_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeEvent *, event, EventPipeProvider *, provider) +EP_DEFINE_GETTER(EventPipeEvent *, event, uint64_t, keywords) +EP_DEFINE_GETTER(EventPipeEvent *, event, uint32_t, event_id) +EP_DEFINE_GETTER(EventPipeEvent *, event, uint32_t, event_version) +EP_DEFINE_GETTER(EventPipeEvent *, event, EventPipeEventLevel, level) +EP_DEFINE_GETTER(EventPipeEvent *, event, bool, need_stack) +EP_DEFINE_GETTER(EventPipeEvent *, event, int64_t, enabled_mask) +EP_DEFINE_SETTER(EventPipeEvent *, event, int64_t, enabled_mask) +EP_DEFINE_GETTER(EventPipeEvent *, event, uint8_t *, metadata) +EP_DEFINE_SETTER(EventPipeEvent *, event, uint8_t *, metadata) +EP_DEFINE_GETTER(EventPipeEvent *, event, uint32_t, metadata_len) +EP_DEFINE_SETTER(EventPipeEvent *, event, uint32_t, metadata_len) + +EventPipeEvent * +ep_event_alloc ( + EventPipeProvider *provider, + uint64_t keywords, + uint32_t event_id, + uint32_t event_version, + EventPipeEventLevel level, + bool need_stack, + const uint8_t *metadata, + uint32_t metadata_len); + +void +ep_event_free (EventPipeEvent * ep_event); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_EVENT_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-file-internals.c b/src/mono/mono/eventpipe/ep-file-internals.c new file mode 100644 index 0000000000000..b10351d792ea3 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-file-internals.c @@ -0,0 +1,295 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +file_fast_serialize_func (void *object, FastSerializer *fast_serializer); + +static +const ep_char8_t * +file_get_type_name_func (void *object); + +static +void +file_free_func (void *object); + +static +uint32_t +stack_hash_key_hash_func (const void *key); + +static +bool +stack_hash_key_eq_func (const void *key1, const void *key2); + +static +void +stack_hash_value_free_func (void *entry); + +/* + * EventPipeFile. + */ + +static +void +file_free_func (void *object) +{ + ep_file_free ((EventPipeFile*)object); +} + +static +void +file_fast_serialize_func (void *object, FastSerializer *fast_serializer) +{ + EP_ASSERT (object != NULL && fast_serializer != NULL); + + EventPipeFile *file = (EventPipeFile *)object; + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->file_open_system_time, sizeof (file->file_open_system_time)); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->file_open_timestamp, sizeof (file->file_open_timestamp)); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->timestamp_frequency, sizeof (file->timestamp_frequency)); + + // the beginning of V3 + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->pointer_size, sizeof (file->pointer_size)); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->current_process_id, sizeof (file->current_process_id)); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->number_of_processors, sizeof (file->number_of_processors)); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&file->sampling_rate_in_ns, sizeof (file->sampling_rate_in_ns)); +} + +static +const ep_char8_t * +file_get_type_name_func (void *object) +{ + EP_ASSERT (object != NULL); + return "Trace"; +} + +static +FastSerializableObjectVtable +file_vtable = { + file_free_func, + file_fast_serialize_func, + file_get_type_name_func }; + +static +uint32_t +stack_hash_key_hash_func (const void *key) +{ + EP_ASSERT (key != NULL); + return ((const StackHashKey *)key)->hash; +} + +static +bool +stack_hash_key_eq_func (const void *key1, const void *key2) +{ + EP_ASSERT (key1 != NULL && key2 != NULL); + + const StackHashKey * stack_hash_key1 = (const StackHashKey *)key1; + const StackHashKey * stack_hash_key2 = (const StackHashKey *)key2; + + return stack_hash_key1->stack_size_in_bytes == stack_hash_key2->stack_size_in_bytes && + !memcmp (stack_hash_key1->stack_bytes, stack_hash_key2->stack_bytes, stack_hash_key1->stack_size_in_bytes); +} + +static +void +stack_hash_value_free_func (void *entry) +{ + ep_stack_hash_entry_free ((StackHashEntry *)entry); +} + +static +void +file_write_end (EventPipeFile *file) +{ + EP_ASSERT (file != NULL && ep_file_get_fast_serializer (file) != NULL); + + ep_file_flush (file, EP_FILE_FLUSH_FLAGS_ALL_BLOCKS); + + // "After the last EventBlock is emitted, the stream is ended by emitting a NullReference Tag which indicates that there are no more objects in the stream to read." + // see https://github.com/Microsoft/perfview/blob/master/src/TraceEvent/EventPipe/EventPipeFormat.md for more + ep_fast_serializer_write_tag (ep_file_get_fast_serializer (file), FAST_SERIALIZER_TAGS_NULL_REFERENCE, NULL, 0); +} + +EventPipeFile * +ep_file_alloc ( + StreamWriter *stream_writer, + EventPipeSerializationFormat format) +{ + EventPipeFile *instance = ep_rt_object_alloc (EventPipeFile); + ep_raise_error_if_nok (instance != NULL); + + ep_fast_serializable_object_init ( + &instance->fast_serializable_object, + &file_vtable, + ep_file_get_file_version (format), + ep_file_get_file_minimum_version (format), + format >= EP_SERIALIZATION_FORMAT_NETTRACE_V4); + + instance->stream_writer = stream_writer; + instance->format = format; + + instance->event_block = ep_event_block_alloc (100 * 1024, format); + ep_raise_error_if_nok (instance->event_block != NULL); + + instance->metadata_block = ep_metadata_block_alloc (100 * 1024); + ep_raise_error_if_nok (instance->metadata_block); + + instance->stack_block = ep_stack_block_alloc (100 * 1024); + ep_raise_error_if_nok (instance->stack_block != NULL); + + // File start time information. + instance->file_open_system_time = ep_rt_system_time_get (); + instance->file_open_timestamp = ep_perf_counter_query (); + instance->timestamp_frequency = ep_perf_frequency_query (); + + instance->pointer_size = SIZEOF_VOID_P; + instance->current_process_id = ep_rt_current_process_get_id (); + instance->number_of_processors = ep_rt_processors_get_count (); + + instance->sampling_rate_in_ns = ep_rt_sample_profiler_get_sampling_rate (); + + ep_rt_metadata_labels_alloc (&instance->metadata_ids, NULL, NULL, NULL, NULL); + ep_raise_error_if_nok (instance->metadata_ids.table); + + ep_rt_stack_hash_alloc (&instance->stack_hash, stack_hash_key_hash_func, stack_hash_key_eq_func, NULL, stack_hash_value_free_func); + ep_raise_error_if_nok (instance->stack_hash.table); + + // Start at 0 - The value is always incremented prior to use, so the first ID will be 1. + ep_rt_volatile_store_uint32_t (&instance->metadata_id_counter, 0); + + // Start at 0 - The value is always incremented prior to use, so the first ID will be 1. + instance->stack_id_counter = 0; + +#ifdef EP_CHECKED_BUILD + instance->last_sorted_timestamp = ep_perf_counter_query (); +#endif + +ep_on_exit: + return instance; + +ep_on_error: + ep_file_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_file_free (EventPipeFile *file) +{ + ep_return_void_if_nok (file != NULL); + + if (file->event_block != NULL && file->fast_serializer != NULL) + file_write_end (file); + + ep_event_block_free (file->event_block); + ep_metadata_block_free (file->metadata_block); + ep_stack_block_free (file->stack_block); + ep_fast_serializer_free (file->fast_serializer); + ep_rt_metadata_labels_free (&file->metadata_ids); + ep_rt_stack_hash_free (&file->stack_hash); + + // If there's no fast_serializer, stream_writer ownership + // have not been passed along and needs to be freed by file. + if (!file->fast_serializer) + ep_stream_writer_free_vcall (file->stream_writer); + + ep_fast_serializable_object_fini (&file->fast_serializable_object); + ep_rt_object_free (file); +} + +/* + * StackHashEntry. + */ + +StackHashEntry * +ep_stack_hash_entry_alloc ( + const EventPipeStackContents *stack_contents, + uint32_t id, + uint32_t hash) +{ + ep_return_null_if_nok (stack_contents != NULL); + + uint32_t stack_size = ep_stack_contents_get_size (stack_contents); + StackHashEntry *entry = (StackHashEntry *)ep_rt_byte_array_alloc (offsetof (StackHashEntry, stack_bytes) + stack_size); + ep_raise_error_if_nok (entry != NULL); + + entry->id = id; + entry->key.hash = hash; + entry->key.stack_size_in_bytes = stack_size; + entry->key.stack_bytes = entry->stack_bytes; + memcpy (entry->stack_bytes, ep_stack_contents_get_pointer (stack_contents), stack_size); + +ep_on_exit: + return entry; + +ep_on_error: + ep_stack_hash_entry_free (entry); + + entry = NULL; + ep_exit_error_handler (); +} + +void +ep_stack_hash_entry_free (StackHashEntry *stack_hash_entry) +{ + ep_return_void_if_nok (stack_hash_entry != NULL); + ep_rt_byte_array_free ((uint8_t *)stack_hash_entry); +} + +/* + * StackHashKey. + */ + +static +inline +uint32_t +hash_bytes (const uint8_t *data, size_t data_len) +{ + EP_ASSERT (data != NULL); + + uint32_t hash = 5381; + const uint8_t *data_end = data + data_len; + for (/**/ ; data < data_end; data++) + hash = ((hash << 5) + hash) ^ *data; + return hash; +} + +StackHashKey * +ep_stack_hash_key_init ( + StackHashKey *key, + const EventPipeStackContents *stack_contents) +{ + EP_ASSERT (key != NULL); + ep_return_null_if_nok (stack_contents != NULL); + + key->stack_bytes = ep_stack_contents_get_pointer (stack_contents); + key->stack_size_in_bytes = ep_stack_contents_get_size (stack_contents); + key->hash = hash_bytes (key->stack_bytes, key->stack_size_in_bytes); + + return key; +} + +void +ep_stack_hash_key_fini (StackHashKey *key) +{ + ; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_file_internals; +const char quiet_linker_empty_file_warning_eventpipe_file_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-file.c b/src/mono/mono/eventpipe/ep-file.c new file mode 100644 index 0000000000000..e16acabc0b0d2 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-file.c @@ -0,0 +1,331 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +uint32_t +file_get_stack_id ( + EventPipeFile *file, + EventPipeEventInstance *event_instance); + +static +uint32_t +file_generate_metadata_id (EventPipeFile *file); + +static +uint32_t +file_get_metadata_id ( + EventPipeFile *file, + EventPipeEvent *ep_event); + +static +void +file_write_event_to_block ( + EventPipeFile *file, + EventPipeEventInstance *event_instance, + uint32_t metadata_id, + uint64_t capture_thread_id, + uint32_t sequence_number, + uint32_t stack_id, + bool is_sotred_event); + +static +void +file_save_metadata_id ( + EventPipeFile *file, + EventPipeEvent *ep_event, + uint32_t metadata_id); + +/* + * EventPipeFile. + */ + +static +uint32_t +file_get_stack_id ( + EventPipeFile *file, + EventPipeEventInstance * event_instance) +{ + EP_ASSERT (file != NULL && event_instance != NULL); + EP_ASSERT (ep_file_get_format (file) >= EP_SERIALIZATION_FORMAT_NETTRACE_V4); + EP_ASSERT (ep_file_get_stack_block (file) != NULL); + + uint32_t stack_id = 0; + EventPipeStackContents *stack_contents = ep_event_instance_get_stack_contents_ref (event_instance); + EventPipeStackBlock *stack_block = ep_file_get_stack_block (file); + ep_rt_stack_hash_map_t *stack_hash = ep_file_get_stack_hash_ref (file); + StackHashEntry *entry = NULL; + StackHashKey key; + ep_stack_hash_key_init (&key, stack_contents); + if (!ep_rt_stack_hash_lookup (stack_hash, &key, &entry)) { + stack_id = ep_file_get_stack_id_counter (file) + 1; + ep_file_set_stack_id_counter (file, stack_id); + entry = ep_stack_hash_entry_alloc (stack_contents, stack_id, ep_stack_hash_key_get_hash (&key)); + if (entry) + ep_rt_stack_hash_add (stack_hash, ep_stack_hash_entry_get_key_ref (entry), entry); + + if (!ep_stack_block_write_stack (stack_block, stack_id, stack_contents)) { + // we can't write this stack to the current block (it's full) + // so we write what we have in the block to the serializer + ep_file_flush (file, EP_FILE_FLUSH_FLAGS_STACK_BLOCK); + bool result = ep_stack_block_write_stack (stack_block, stack_id, stack_contents); + EP_ASSERT (result == true); // we should never fail to add event to a clear block (if we do the max size is too small) + } + } else { + stack_id = ep_stack_hash_entry_get_id (entry); + } + + ep_stack_hash_key_fini (&key); + return stack_id; +} + +static +uint32_t +file_get_metadata_id ( + EventPipeFile *file, + EventPipeEvent *ep_event) +{ + EP_ASSERT (file != NULL && ep_event != NULL); + EP_ASSERT (ep_file_get_metadata_ids_cref (file) != NULL); + + uint32_t metadata_ids; + if (ep_rt_metadata_labels_lookup (ep_file_get_metadata_ids_cref (file), ep_event, &metadata_ids)) { + EP_ASSERT (metadata_ids != 0); + return metadata_ids; + } + + return 0; +} + +static +uint32_t +file_generate_metadata_id (EventPipeFile *file) +{ + return ep_rt_atomic_inc_uint32_t (ep_file_get_metadata_id_counter_ref (file)); +} + +static +void +file_write_event_to_block ( + EventPipeFile *file, + EventPipeEventInstance *event_instance, + uint32_t metadata_id, + uint64_t capture_thread_id, + uint32_t sequence_number, + uint32_t stack_id, + bool is_sotred_event) +{ + EP_ASSERT (file != NULL && event_instance != NULL); + EP_ASSERT (ep_file_get_event_block (file) != NULL); + EP_ASSERT (ep_file_get_metadata_block (file) != NULL); + + ep_event_instance_set_metadata_id (event_instance, metadata_id); + + // If we are flushing events we need to flush metadata and stacks as well + // to ensure referenced metadata/stacks were written to the file before the + // event which referenced them. + EventPipeFileFlushFlags flags = EP_FILE_FLUSH_FLAGS_ALL_BLOCKS; + EventPipeEventBlockBase *block = (EventPipeEventBlockBase *)ep_file_get_event_block (file); + if(metadata_id == 0 && ep_file_get_format (file) >= EP_SERIALIZATION_FORMAT_NETTRACE_V4) { + flags = EP_FILE_FLUSH_FLAGS_METADATA_BLOCK; + block = (EventPipeEventBlockBase *)ep_file_get_metadata_block (file); + } + + if (ep_event_block_base_write_event (block, event_instance, capture_thread_id, sequence_number, stack_id, is_sotred_event)) + return; // the block is not full, we added the event and continue + + // we can't write this event to the current block (it's full) + // so we write what we have in the block to the serializer + ep_file_flush (file, flags); + + bool result = ep_event_block_base_write_event (block, event_instance, capture_thread_id, sequence_number, stack_id, is_sotred_event); + EP_ASSERT (result == true); // we should never fail to add event to a clear block (if we do the max size is too small) +} + +static +void +file_save_metadata_id ( + EventPipeFile *file, + EventPipeEvent *ep_event, + uint32_t metadata_id) +{ + EP_ASSERT (file != NULL && ep_event != NULL); + EP_ASSERT (metadata_id > 0); + EP_ASSERT (ep_file_get_metadata_ids_cref (file) != NULL); + + // If a pre-existing metadata label exists, remove it. + uint32_t old_id; + if (ep_rt_metadata_labels_lookup (ep_file_get_metadata_ids_cref (file), ep_event, &old_id)) + ep_rt_metadata_labels_remove (ep_file_get_metadata_ids_ref (file), ep_event); + + // Add the metadata label. + ep_rt_metadata_labels_add (ep_file_get_metadata_ids_ref (file), ep_event, metadata_id); +} + +bool +ep_file_initialize_file (EventPipeFile *file) +{ + ep_return_false_if_nok (file != NULL); + + EP_ASSERT (ep_file_get_stream_writer (file) != NULL); + EP_ASSERT (ep_file_get_fast_serializer (file) == NULL); + + bool success = true; + if (ep_file_get_format (file) >= EP_SERIALIZATION_FORMAT_NETTRACE_V4) { + const ep_char8_t header[] = "Nettrace"; + const uint32_t bytes_to_write = EP_ARRAY_SIZE (header) - 1; + uint32_t bytes_written = 0; + success = ep_stream_writer_write (ep_file_get_stream_writer (file), (const uint8_t *)header, bytes_to_write, &bytes_written) && bytes_written == bytes_to_write; + } + + if (success) { + // Create the file stream and write the FastSerialization header. + ep_file_set_fast_serializer (file, ep_fast_serializer_alloc (ep_file_get_stream_writer (file))); + + // Write the first object to the file. + if (ep_file_get_fast_serializer (file)) + ep_fast_serializer_write_object (ep_file_get_fast_serializer (file), (FastSerializableObject *)file); + } + + return success; +} + +void +ep_file_write_event ( + EventPipeFile *file, + EventPipeEventInstance *event_instance, + uint64_t capture_thread_id, + uint32_t sequence_number, + bool is_sorted_event) +{ + ep_return_void_if_nok (file != NULL && event_instance != NULL); + EP_ASSERT (ep_file_get_fast_serializer (file) != NULL); + + EventPipeEventMetadataEvent *metadata_instance = NULL; + +#ifdef EP_CHECKED_BUILD + EP_ASSERT (ep_event_instance_get_timestamp (event_instance) >= ep_file_get_last_sorted_timestamp (file)); + if (is_sorted_event) + ep_file_set_last_sorted_timestamp (file, ep_event_instance_get_timestamp (event_instance)); +#endif + + uint32_t stack_id = 0; + if (ep_file_get_format (file) >= EP_SERIALIZATION_FORMAT_NETTRACE_V4) + stack_id = file_get_stack_id (file, event_instance); + + // Check to see if we've seen this event type before. + // If not, then write the event metadata to the event stream first. + unsigned int metadata_id = file_get_metadata_id (file, ep_event_instance_get_ep_event (event_instance)); + if(metadata_id == 0) { + metadata_id = file_generate_metadata_id (file); + + metadata_instance = ep_build_event_metadata_event (event_instance, metadata_id); + ep_raise_error_if_nok (metadata_instance != NULL); + + file_write_event_to_block (file, (EventPipeEventInstance *)metadata_instance, 0, 0, 0, 0, true); // metadataId=0 breaks recursion and represents the metadata event. + file_save_metadata_id (file, ep_event_instance_get_ep_event (event_instance), metadata_id); + } + + file_write_event_to_block (file, event_instance, metadata_id, capture_thread_id, sequence_number, stack_id, is_sorted_event); + +ep_on_exit: + ep_event_metdata_event_free (metadata_instance); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +void +ep_file_write_sequence_point ( + EventPipeFile *file, + EventPipeSequencePoint *sequence_point) +{ + ep_return_void_if_nok (file != NULL && sequence_point != NULL); + EP_ASSERT (ep_file_get_fast_serializer (file) != NULL); + + if (ep_file_get_format (file) < EP_SERIALIZATION_FORMAT_NETTRACE_V4) + return; // sequence points aren't used in NetPerf format + + ep_file_flush (file, EP_FILE_FLUSH_FLAGS_ALL_BLOCKS); + EventPipeSequencePointBlock sequence_point_block; + + ep_sequence_point_block_init (&sequence_point_block, sequence_point); + ep_fast_serializer_write_object (ep_file_get_fast_serializer (file), (FastSerializableObject *)&sequence_point_block); + ep_sequence_point_block_fini (&sequence_point_block); + + // stack cache resets on sequence points + ep_file_set_stack_id_counter (file, 0); + ep_rt_stack_hash_remove_all (ep_file_get_stack_hash_ref (file)); +} + +void +ep_file_flush ( + EventPipeFile *file, + EventPipeFileFlushFlags flags) +{ + // Write existing buffer to the stream/file regardless of whether it is full or not. + ep_return_void_if_nok (file != NULL && ep_file_get_fast_serializer (file) != NULL && ep_file_get_metadata_block (file) != NULL && + ep_file_get_stack_block (file) != NULL && ep_file_get_event_block (file) != NULL); + + if ((ep_metadata_block_get_bytes_written (ep_file_get_metadata_block (file)) != 0) && ((flags & EP_FILE_FLUSH_FLAGS_METADATA_BLOCK) != 0)) { + EP_ASSERT (ep_file_get_format (file) >= EP_SERIALIZATION_FORMAT_NETTRACE_V4); + ep_metadata_block_serialize (ep_file_get_metadata_block (file), ep_file_get_fast_serializer (file)); + ep_metadata_block_clear (ep_file_get_metadata_block (file)); + } + + if ((ep_stack_block_get_bytes_written (ep_file_get_stack_block (file)) != 0) && ((flags & EP_FILE_FLUSH_FLAGS_STACK_BLOCK) != 0)) { + EP_ASSERT (ep_file_get_format (file) >= EP_SERIALIZATION_FORMAT_NETTRACE_V4); + ep_stack_block_serialize (ep_file_get_stack_block (file), ep_file_get_fast_serializer (file)); + ep_stack_block_clear (ep_file_get_stack_block (file)); + } + + if ((ep_event_block_get_bytes_written (ep_file_get_event_block (file)) != 0) && ((flags & EP_FILE_FLUSH_FLAGS_EVENT_BLOCK) != 0)) { + ep_event_block_serialize (ep_file_get_event_block (file), ep_file_get_fast_serializer (file)); + ep_event_block_clear (ep_file_get_event_block (file)); + } +} + +int32_t +ep_file_get_file_version (EventPipeSerializationFormat format) +{ + switch (format) { + case EP_SERIALIZATION_FORMAT_NETPERF_V3 : + return 3; + case EP_SERIALIZATION_FORMAT_NETTRACE_V4 : + return 4; + default : + EP_ASSERT (!"Unrecognized EventPipeSerializationFormat"); + return 0; + } +} + +int32_t +ep_file_get_file_minimum_version (EventPipeSerializationFormat format) +{ + switch (format) { + case EP_SERIALIZATION_FORMAT_NETPERF_V3 : + return 0; + case EP_SERIALIZATION_FORMAT_NETTRACE_V4 : + return 4; + default : + EP_ASSERT (!"Unrecognized EventPipeSerializationFormat"); + return 0; + } +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_file; +const char quiet_linker_empty_file_warning_eventpipe_file = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-file.h b/src/mono/mono/eventpipe/ep-file.h new file mode 100644 index 0000000000000..7c78e405e9464 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-file.h @@ -0,0 +1,164 @@ +#ifndef __EVENTPIPE_FILE_H__ +#define __EVENTPIPE_FILE_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeFile. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeFile { +#else +struct _EventPipeFile_Internal { +#endif + FastSerializableObject fast_serializable_object; + StreamWriter *stream_writer; + FastSerializer *fast_serializer; + EventPipeEventBlock *event_block; + EventPipeMetadataBlock *metadata_block; + EventPipeStackBlock *stack_block; + ep_rt_metadata_labels_hash_map_t metadata_ids; + ep_rt_stack_hash_map_t stack_hash; + uint64_t file_open_system_time; + uint64_t file_open_timestamp; + uint64_t timestamp_frequency; +#ifdef EP_CHECKED_BUILD + uint64_t last_sorted_timestamp; +#endif + uint32_t pointer_size; + uint32_t current_process_id; + uint32_t number_of_processors; + uint32_t sampling_rate_in_ns; + uint32_t stack_id_counter; + volatile uint32_t metadata_id_counter; + EventPipeSerializationFormat format; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeFile { + uint8_t _internal [sizeof (struct _EventPipeFile_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeFile *, file, StreamWriter *, stream_writer) +EP_DEFINE_GETTER(EventPipeFile *, file, FastSerializer *, fast_serializer) +EP_DEFINE_SETTER(EventPipeFile *, file, FastSerializer *, fast_serializer) +EP_DEFINE_GETTER(EventPipeFile *, file, EventPipeEventBlock *, event_block) +EP_DEFINE_GETTER(EventPipeFile *, file, EventPipeMetadataBlock *, metadata_block) +EP_DEFINE_GETTER_REF(EventPipeFile *, file, ep_rt_metadata_labels_hash_map_t *, metadata_ids) +EP_DEFINE_GETTER_REF(EventPipeFile *, file, ep_rt_stack_hash_map_t *, stack_hash) +EP_DEFINE_GETTER(EventPipeFile *, file, EventPipeStackBlock *, stack_block) +EP_DEFINE_GETTER(EventPipeFile *, file, EventPipeSerializationFormat, format) +EP_DEFINE_GETTER(EventPipeFile *, file, uint32_t, stack_id_counter); +EP_DEFINE_SETTER(EventPipeFile *, file, uint32_t, stack_id_counter); +EP_DEFINE_GETTER_REF(EventPipeFile *, file, volatile uint32_t *, metadata_id_counter) +#ifdef EP_CHECKED_BUILD +EP_DEFINE_GETTER(EventPipeFile *, file, uint64_t, last_sorted_timestamp) +EP_DEFINE_SETTER(EventPipeFile *, file, uint64_t, last_sorted_timestamp) +#endif + +EventPipeFile * +ep_file_alloc ( + StreamWriter *stream_writer, + EventPipeSerializationFormat format); + +void +ep_file_free (EventPipeFile *file); + +bool +ep_file_initialize_file (EventPipeFile *file); + +void +ep_file_write_event ( + EventPipeFile *file, + EventPipeEventInstance * event_instance, + uint64_t capture_thread_id, + uint32_t sequence_number, + bool is_sorted_event); + +void +ep_file_write_sequence_point ( + EventPipeFile *file, + EventPipeSequencePoint *sequence_point); + +void +ep_file_flush ( + EventPipeFile *file, + EventPipeFileFlushFlags flags); + +int32_t +ep_file_get_file_version (EventPipeSerializationFormat format); + +int32_t +ep_file_get_file_minimum_version (EventPipeSerializationFormat format); + +/* + * StackHashKey. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _StackHashKey { +#else +struct _StackHashKey_Internal { +#endif + uint8_t *stack_bytes; + uint32_t hash; + uint32_t stack_size_in_bytes; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _StackHashKey { + uint8_t _internal [sizeof (struct _StackHashKey_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(StackHashKey *, stack_hash_key, uint32_t, hash) + +StackHashKey * +ep_stack_hash_key_init ( + StackHashKey *key, + const EventPipeStackContents *stack_contents); + +void +ep_stack_hash_key_fini (StackHashKey *key); + +/* + * StackHashEntry. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _StackHashEntry { +#else +struct _StackHashEntry_Internal { +#endif + StackHashKey key; + uint32_t id; + // This is the first byte of StackSizeInBytes bytes of stack data + uint8_t stack_bytes[1]; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _StackHashEntry { + uint8_t _internal [sizeof (struct _StackHashEntry_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(StackHashEntry *, stack_hash_entry, StackHashKey *, key) +EP_DEFINE_GETTER(StackHashEntry *, stack_hash_entry, uint32_t, id) + +StackHashEntry * +ep_stack_hash_entry_alloc ( + const EventPipeStackContents *stack_contents, + uint32_t id, + uint32_t hash); + +void +ep_stack_hash_entry_free (StackHashEntry *stack_hash_entry); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_FILE_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-internals.c b/src/mono/mono/eventpipe/ep-internals.c new file mode 100644 index 0000000000000..58bc70df0e89b --- /dev/null +++ b/src/mono/mono/eventpipe/ep-internals.c @@ -0,0 +1,242 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" + +#ifndef EP_INLINE_GETTER_SETTER +#define EP_IMPL_GETTER_SETTER +#define EP_DEFINE_GETTER(instance_type, instance_type_name, return_type, instance_field_name) \ + return_type ep_ ## instance_type_name ## _get_ ## instance_field_name (const instance_type instance) { return instance-> instance_field_name; } \ + size_t ep_ ## instance_type_name ## _sizeof_ ## instance_field_name (const instance_type instance) { return sizeof (instance-> instance_field_name); } +#define EP_DEFINE_GETTER_REF(instance_type, instance_type_name, return_type, instance_field_name) \ + return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _ref (instance_type instance) { return &(instance-> instance_field_name); } \ + const return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _cref (const instance_type instance) { return &(instance-> instance_field_name); } +#define EP_DEFINE_GETTER_ARRAY_REF(instance_type, instance_type_name, return_type, const_return_type, instance_field_name, instance_field) \ + return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _ref (instance_type instance) { return &(instance-> instance_field); } \ + const_return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _cref (const instance_type instance) { return &(instance-> instance_field); } +#define EP_DEFINE_SETTER(instance_type, instance_type_name, instance_field_type, instance_field_name) \ + void ep_ ## instance_type_name ## _set_ ## instance_field_name (instance_type instance, instance_field_type instance_field_name) { instance-> instance_field_name = instance_field_name; } +#endif + +#include "ep.h" + +// Option to include all internal source files into ep-internals.c. +#ifdef EP_INCLUDE_SOURCE_FILES +#define EP_FORCE_INCLUDE_SOURCE_FILES +#include "ep-block-internals.c" +#include "ep-buffer-manager-internals.c" +#include "ep-config-internals.c" +#include "ep-event-internals.c" +#include "ep-event-instance-internals.c" +#include "ep-event-payload-internals.c" +#include "ep-event-source-internals.c" +#include "ep-file-internals.c" +#include "ep-metadata-generator-internals.c" +#include "ep-provider-internals.c" +#include "ep-session-internals.c" +#include "ep-session-provider-internals.c" +#include "ep-stream-internals.c" +#include "ep-thread-internals.c" +#endif + +/* + * EventFilterDescriptor. + */ + +EventFilterDescriptor * +ep_event_filter_desc_alloc ( + uint64_t ptr, + uint32_t size, + uint32_t type) +{ + EventFilterDescriptor *instance = ep_rt_object_alloc (EventFilterDescriptor); + ep_raise_error_if_nok (ep_event_filter_desc_init (instance, ptr, size, type) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + ep_event_filter_desc_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +EventFilterDescriptor * +ep_event_filter_desc_init ( + EventFilterDescriptor *event_filter_desc, + uint64_t ptr, + uint32_t size, + uint32_t type) +{ + EP_ASSERT (event_filter_desc != NULL); + + event_filter_desc->ptr = ptr; + event_filter_desc->size = size; + event_filter_desc->type = type; + + return event_filter_desc; +} + +void +ep_event_filter_desc_fini (EventFilterDescriptor * filter_desc) +{ + ; +} + +void +ep_event_filter_desc_free (EventFilterDescriptor * filter_desc) +{ + ep_return_void_if_nok (filter_desc != NULL); + + ep_event_filter_desc_fini (filter_desc); + ep_rt_object_free (filter_desc); +} + +/* + * EventPipeProviderCallbackDataQueue. + */ + +EventPipeProviderCallbackDataQueue * +ep_provider_callback_data_queue_init (EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_return_null_if_nok (provider_callback_data_queue != NULL); + ep_rt_provider_callback_data_queue_alloc (&provider_callback_data_queue->queue); + return provider_callback_data_queue; +} + +void +ep_provider_callback_data_queue_fini (EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_return_void_if_nok (provider_callback_data_queue != NULL); + ep_rt_provider_callback_data_queue_free (&provider_callback_data_queue->queue); +} + +/* + * EventPipeProviderCallbackData. + */ + +EventPipeProviderCallbackData * +ep_provider_callback_data_alloc ( + const ep_char8_t *filter_data, + EventPipeCallback callback_function, + void *callback_data, + int64_t keywords, + EventPipeEventLevel provider_level, + bool enabled) +{ + EventPipeProviderCallbackData *instance = ep_rt_object_alloc (EventPipeProviderCallbackData); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_provider_callback_data_init ( + instance, + filter_data, + callback_function, + callback_data, + keywords, + provider_level, + enabled) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + instance = NULL; + ep_exit_error_handler (); +} + +EventPipeProviderCallbackData * +ep_provider_callback_data_alloc_copy (EventPipeProviderCallbackData *provider_callback_data_src) +{ + EventPipeProviderCallbackData *instance = ep_rt_object_alloc (EventPipeProviderCallbackData); + ep_raise_error_if_nok (instance != NULL); + + if (provider_callback_data_src) + *instance = *provider_callback_data_src; + +ep_on_exit: + return instance; + +ep_on_error: + instance = NULL; + ep_exit_error_handler (); +} + +EventPipeProviderCallbackData * +ep_provider_callback_data_init ( + EventPipeProviderCallbackData *provider_callback_data, + const ep_char8_t *filter_data, + EventPipeCallback callback_function, + void *callback_data, + int64_t keywords, + EventPipeEventLevel provider_level, + bool enabled) +{ + ep_return_null_if_nok (provider_callback_data != NULL); + + provider_callback_data->filter_data = filter_data; + provider_callback_data->callback_function = callback_function; + provider_callback_data->callback_data = callback_data; + provider_callback_data->keywords = keywords; + provider_callback_data->provider_level = provider_level; + provider_callback_data->enabled = enabled; + + return provider_callback_data; +} + +EventPipeProviderCallbackData * +ep_provider_callback_data_init_copy ( + EventPipeProviderCallbackData *provider_callback_data_dst, + EventPipeProviderCallbackData *provider_callback_data_src) +{ + ep_return_null_if_nok (provider_callback_data_dst != NULL && provider_callback_data_src != NULL); + *provider_callback_data_dst = *provider_callback_data_src; + return provider_callback_data_dst; +} + +void +ep_provider_callback_data_fini (EventPipeProviderCallbackData *provider_callback_data) +{ + ; +} + +void +ep_provider_callback_data_free (EventPipeProviderCallbackData *provider_callback_data) +{ + ep_return_void_if_nok (provider_callback_data != NULL); + ep_rt_object_free (provider_callback_data); +} + +/* + * EventPipeProviderConfiguration. + */ + +EventPipeProviderConfiguration * +ep_provider_config_init ( + EventPipeProviderConfiguration *provider_config, + const ep_char8_t *provider_name, + uint64_t keywords, + uint32_t logging_level, + const ep_char8_t *filter_data) +{ + EP_ASSERT (provider_config != NULL); + ep_return_null_if_nok (provider_name != NULL); + + provider_config->provider_name = provider_name; + provider_config->keywords = keywords; + provider_config->logging_level = logging_level; + provider_config->filter_data = filter_data; + + return provider_config; +} + +void +ep_provider_config_fini (EventPipeProviderConfiguration *provider_config) +{ + ; +} + +#endif /* ENABLE_PERFTRACING */ + +extern const char quiet_linker_empty_file_warning_eventpipe_internals; +const char quiet_linker_empty_file_warning_eventpipe_internals = 0; diff --git a/src/mono/mono/eventpipe/ep-metadata-generator-internals.c b/src/mono/mono/eventpipe/ep-metadata-generator-internals.c new file mode 100644 index 0000000000000..e2c8e76421d16 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-metadata-generator-internals.c @@ -0,0 +1,40 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventPipeParameterDesc. + */ + +EventPipeParameterDesc * +ep_parameter_desc_init ( + EventPipeParameterDesc *parameter_desc, + EventPipeParameterType type, + const ep_char16_t *name) +{ + EP_ASSERT (parameter_desc != NULL); + + parameter_desc->type = type; + parameter_desc->name = name; + + return parameter_desc; +} + +void +ep_parameter_desc_fini (EventPipeParameterDesc *parameter_desc) +{ + ; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_metadata_generator_internals; +const char quiet_linker_empty_file_warning_eventpipe_metadata_generator_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-metadata-generator.c b/src/mono/mono/eventpipe/ep-metadata-generator.c new file mode 100644 index 0000000000000..4fd80356e9649 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-metadata-generator.c @@ -0,0 +1,106 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * EventPipeMetadataGenerator. + */ + +uint8_t * +ep_metadata_generator_generate_event_metadata ( + uint32_t event_id, + const ep_char16_t *event_name, + uint64_t keywords, + uint32_t version, + EventPipeEventLevel level, + EventPipeParameterDesc *params, + uint32_t params_len, + size_t *metadata_len) +{ + ep_return_null_if_nok (event_name != NULL); + ep_return_null_if_nok (params_len == 0 || params != NULL); + ep_return_null_if_nok (metadata_len != NULL); + + // The order of fields is defined in coreclr\src\mscorlib\shared\System\Diagnostics\Tracing\EventSource.cs DefineEventPipeEvents method + // eventID : 4 bytes + // eventName : (eventName.Length + 1) * 2 bytes + // keywords : 8 bytes + // eventVersion : 4 bytes + // level : 4 bytes + // parameterCount : 4 bytes + size_t event_name_len = ep_rt_utf16_string_len (event_name); + *metadata_len = 24 + ((event_name_len + 1) * sizeof (ep_char16_t)); + + // Each parameter has a 4 byte TypeCode + (parameterName.Length + 1) * 2 bytes. + for (uint32_t i = 0; i < params_len; ++i) { + EP_ASSERT (ep_parameter_desc_get_name (¶ms [i]) != NULL); + *metadata_len += (4 + ((ep_rt_utf16_string_len (ep_parameter_desc_get_name (¶ms [i])) + 1) * sizeof (ep_char16_t))); + } + + // Allocate a metadata blob. + uint8_t *buffer = ep_rt_byte_array_alloc (*metadata_len); + ep_raise_error_if_nok (buffer != NULL); + + uint8_t * current = buffer; + + // Write the event ID. + memcpy (current, &event_id, sizeof (event_id)); + current += sizeof (event_id); + + // Write the event name. + memcpy (current, event_name, (event_name_len + 1) * sizeof (ep_char16_t)); + current += (event_name_len + 1) * sizeof (ep_char16_t); + + // Write the keywords. + memcpy (current, &keywords, sizeof (keywords)); + current += sizeof (keywords); + + // Write the version. + memcpy (current, &version, sizeof (version)); + current += sizeof (version); + + // Write the level. + memcpy (current, &level, sizeof (level)); + current += sizeof (level); + + // Write the parameter count. + memcpy(current, ¶ms_len, sizeof (params_len)); + current += sizeof (params_len); + + // Write the parameter descriptions. + for (uint32_t i = 0; i < params_len; ++i) { + EventPipeParameterType const param_type = ep_parameter_desc_get_type (¶ms [i]); + const ep_char16_t *const param_name = ep_parameter_desc_get_name (¶ms [i]); + size_t const param_name_len = ep_rt_utf16_string_len (param_name); + + memcpy (current, ¶m_type, sizeof (param_type)); + current += sizeof (param_type); + + memcpy (current, param_name, (param_name_len + 1) * sizeof (ep_char16_t)); + current += (param_name_len + 1) * sizeof (ep_char16_t); + } + + EP_ASSERT (*metadata_len == (size_t)(current - buffer)); + +ep_on_exit: + return buffer; + +ep_on_error: + ep_rt_byte_array_free (buffer); + *metadata_len = 0; + + buffer = NULL; + ep_exit_error_handler (); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_metadata_generator; +const char quiet_linker_empty_file_warning_eventpipe_metadata_generator = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-metadata-generator.h b/src/mono/mono/eventpipe/ep-metadata-generator.h new file mode 100644 index 0000000000000..5f1d90a7ca27b --- /dev/null +++ b/src/mono/mono/eventpipe/ep-metadata-generator.h @@ -0,0 +1,57 @@ +#ifndef __EVENTPIPE_METADATA_GENERATOR_H__ +#define __EVENTPIPE_METADATA_GENERATOR_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeMetadataGenerator. + */ + +uint8_t * +ep_metadata_generator_generate_event_metadata ( + uint32_t event_id, + const ep_char16_t *event_name, + uint64_t keywords, + uint32_t version, + EventPipeEventLevel level, + EventPipeParameterDesc *params, + uint32_t params_len, + size_t *metadata_len); + +/* + * EventPipeParameterDesc. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeParameterDesc { +#else +struct _EventPipeParameterDesc_Internal { +#endif + EventPipeParameterType type; + const ep_char16_t *name; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeParameterDesc { + uint8_t _internal [sizeof (struct _EventPipeParameterDesc_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeParameterDesc *, parameter_desc, EventPipeParameterType, type) +EP_DEFINE_GETTER(EventPipeParameterDesc *, parameter_desc, const ep_char16_t *, name) + +EventPipeParameterDesc * +ep_parameter_desc_init ( + EventPipeParameterDesc *parameter_desc, + EventPipeParameterType type, + const ep_char16_t *name); + +void +ep_parameter_desc_fini (EventPipeParameterDesc *parameter_desc); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_METADATA_GENERATOR_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-provider-internals.c b/src/mono/mono/eventpipe/ep-provider-internals.c new file mode 100644 index 0000000000000..a93197ae76663 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-provider-internals.c @@ -0,0 +1,86 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +event_free_func (void *ep_event); + +/* + * EventPipeProvider. + */ + +static +void +event_free_func (void *ep_event) +{ + ep_event_free ((EventPipeEvent *)ep_event); +} + +EventPipeProvider * +ep_provider_alloc ( + EventPipeConfiguration *config, + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data) +{ + ep_return_false_if_nok (config != NULL && provider_name != NULL); + + EventPipeProvider *instance = ep_rt_object_alloc (EventPipeProvider); + ep_raise_error_if_nok (instance != NULL); + + instance->provider_name = ep_rt_utf8_string_dup (provider_name); + ep_raise_error_if_nok (instance->provider_name != NULL); + + instance->provider_name_utf16 = ep_rt_utf8_to_utf16_string (provider_name, ep_rt_utf8_string_len (provider_name)); + ep_raise_error_if_nok (instance->provider_name_utf16 != NULL); + + instance->keywords = 0; + instance->provider_level = EP_EVENT_LEVEL_CRITICAL; + instance->callback_func = callback_func; + instance->callback_data = callback_data; + instance->config = config; + instance->delete_deferred = false; + instance->sessions = 0; + +ep_on_exit: + return instance; + +ep_on_error: + ep_provider_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_provider_free (EventPipeProvider * provider) +{ + ep_return_void_if_nok (provider != NULL); + + //TODO: CoreCLR takes the lock before manipulating the list, but since complete object is + // going away and list is only owned by provider, meaning that if we had a race related + // to the list, it will crash anyways once lock is released and list is gone. + ep_rt_event_list_free (&provider->event_list, event_free_func); + + ep_rt_utf16_string_free (provider->provider_name_utf16); + ep_rt_utf8_string_free (provider->provider_name); + ep_rt_object_free (provider); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_provider_internals; +const char quiet_linker_empty_file_warning_eventpipe_provider_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-provider.c b/src/mono/mono/eventpipe/ep-provider.c new file mode 100644 index 0000000000000..5e87cfbf7619d --- /dev/null +++ b/src/mono/mono/eventpipe/ep-provider.c @@ -0,0 +1,317 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +const EventPipeProviderCallbackData * +provider_prepare_callback_data ( + EventPipeProvider *provider, + int64_t keywords, + EventPipeEventLevel provider_level, + const ep_char8_t *filter_data, + EventPipeProviderCallbackData *provider_callback_data); + +static +void +provider_refresh_all_events (EventPipeProvider *provider); + +static +void +provider_refresh_event_state_lock_held (EventPipeEvent *ep_event); + +static +int64_t +provider_compute_event_enable_mask_lock_held ( + const EventPipeConfiguration *config, + const EventPipeProvider *provider, + int64_t keywords, + EventPipeEventLevel event_level); + +/* + * EventPipeProvider. + */ + +static +const EventPipeProviderCallbackData * +provider_prepare_callback_data ( + EventPipeProvider *provider, + int64_t keywords, + EventPipeEventLevel provider_level, + const ep_char8_t *filter_data, + EventPipeProviderCallbackData *provider_callback_data) +{ + EP_ASSERT (provider != NULL && provider_callback_data != NULL); + + return ep_provider_callback_data_init ( + provider_callback_data, + filter_data, + ep_provider_get_callback_func (provider), + ep_provider_get_callback_data (provider), + keywords, + provider_level, + (ep_provider_get_sessions (provider) != 0)); +} + +static +void +provider_refresh_all_events (EventPipeProvider *provider) +{ + EP_ASSERT (provider != NULL); + ep_rt_config_requires_lock_held (); + + const ep_rt_event_list_t *event_list = ep_provider_get_event_list_cref (provider); + EP_ASSERT (event_list != NULL); + + ep_rt_event_list_iterator_t iterator; + for (ep_rt_event_list_iterator_begin (event_list, &iterator); !ep_rt_provider_list_iterator_end (event_list, &iterator); ep_rt_provider_list_iterator_next (event_list, &iterator)) + provider_refresh_event_state_lock_held(ep_rt_event_list_iterator_value (&iterator)); + + ep_rt_config_requires_lock_held (); + return; +} + +static +void +provider_refresh_event_state_lock_held (EventPipeEvent *ep_event) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (ep_event != NULL); + + EventPipeProvider *provider = ep_event_get_provider (ep_event); + EP_ASSERT (provider != NULL); + + EventPipeConfiguration *config = ep_provider_get_config (provider); + EP_ASSERT (config != NULL); + + int64_t enable_mask = provider_compute_event_enable_mask_lock_held (config, provider, ep_event_get_keywords (ep_event), ep_event_get_level (ep_event)); + ep_event_set_enabled_mask (ep_event, enable_mask); + + ep_rt_config_requires_lock_held (); + return; +} + +static +int64_t +provider_compute_event_enable_mask_lock_held ( + const EventPipeConfiguration *config, + const EventPipeProvider *provider, + int64_t keywords, + EventPipeEventLevel event_level) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (provider != NULL); + + int64_t result = 0; + bool provider_enabled = ep_provider_get_enabled (provider); + for (int i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; i++) { + // Entering EventPipe lock gave us a barrier, we don't need more of them. + EventPipeSession *session = ep_volatile_load_session_without_barrier (i); + if (session) { + EventPipeSessionProvider *session_provider = ep_config_get_session_provider_lock_held (config, session, provider); + if (session_provider) { + int64_t session_keyword = ep_session_provider_get_keywords (session_provider); + EventPipeEventLevel session_level = ep_session_provider_get_logging_level (session_provider); + // The event is enabled if: + // - The provider is enabled. + // - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0. + // - The event level is LogAlways or the provider's verbosity level is set to greater than the event's verbosity level in the manifest. + bool keyword_enabled = (keywords == 0) || ((session_keyword & keywords) != 0); + bool level_enabled = ((event_level == EP_EVENT_LEVEL_LOG_ALWAYS) || (session_level >= event_level)); + if (provider_enabled && keyword_enabled && level_enabled) + result = result | ep_session_get_mask (session); + } + } + } + + ep_rt_config_requires_lock_held (); + return result; +} + +EventPipeEvent * +ep_provider_add_event ( + EventPipeProvider *provider, + uint32_t event_id, + uint64_t keywords, + uint32_t event_version, + EventPipeEventLevel level, + bool need_stack, + const uint8_t *metadata, + uint32_t metadata_len) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_null_if_nok (provider != NULL); + + EventPipeEvent *instance = ep_event_alloc ( + provider, + keywords, + event_id, + event_version, + level, + need_stack, + metadata, + metadata_len); + + ep_return_null_if_nok (instance != NULL); + + // Take the config lock before inserting a new event. + EP_CONFIG_LOCK_ENTER + ep_rt_event_list_append (ep_provider_get_event_list_ref (provider), instance); + provider_refresh_event_state_lock_held (instance); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return instance; + +ep_on_error: + instance = NULL; + ep_exit_error_handler (); +} + +const EventPipeProviderCallbackData * +ep_provider_set_config_lock_held ( + EventPipeProvider *provider, + int64_t keywords_for_all_sessions, + EventPipeEventLevel level_for_all_sessions, + uint64_t session_mask, + int64_t keywords, + EventPipeEventLevel level, + const ep_char8_t *filter_data, + EventPipeProviderCallbackData *callback_data) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (provider != NULL); + + EP_ASSERT ((ep_provider_get_sessions (provider) & session_mask) == 0); + ep_provider_set_sessions (provider, (ep_provider_get_sessions (provider) | session_mask)); + ep_provider_set_keywords (provider, keywords_for_all_sessions); + ep_provider_set_provider_level (provider, level_for_all_sessions); + + provider_refresh_all_events (provider); + provider_prepare_callback_data (provider, ep_provider_get_keywords (provider), ep_provider_get_provider_level (provider), filter_data, callback_data); + + ep_rt_config_requires_lock_held (); + return callback_data; +} + +const EventPipeProviderCallbackData * +ep_provider_unset_config_lock_held ( + EventPipeProvider *provider, + int64_t keywords_for_all_sessions, + EventPipeEventLevel level_for_all_sessions, + uint64_t session_mask, + int64_t keywords, + EventPipeEventLevel level, + const ep_char8_t *filter_data, + EventPipeProviderCallbackData *callback_data) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (provider != NULL); + + EP_ASSERT ((ep_provider_get_sessions (provider) & session_mask) != 0); + if (ep_provider_get_sessions (provider) & session_mask) + ep_provider_set_sessions (provider, (ep_provider_get_sessions (provider) & ~session_mask)); + + ep_provider_set_keywords (provider, keywords_for_all_sessions); + ep_provider_set_provider_level (provider, level_for_all_sessions); + + provider_refresh_all_events (provider); + provider_prepare_callback_data (provider, ep_provider_get_keywords (provider), ep_provider_get_provider_level (provider), filter_data, callback_data); + + ep_rt_config_requires_lock_held (); + return callback_data; +} + +void +ep_provider_invoke_callback (EventPipeProviderCallbackData *provider_callback_data) +{ + // Lock should not be held when invoking callback. + ep_rt_config_requires_lock_not_held (); + + ep_return_void_if_nok (provider_callback_data != NULL); + + const ep_char8_t *filter_data = ep_provider_callback_data_get_filter_data (provider_callback_data); + EventPipeCallback callback_function = ep_provider_callback_data_get_callback_function (provider_callback_data); + bool enabled = ep_provider_callback_data_get_enabled (provider_callback_data); + int64_t keywords = ep_provider_callback_data_get_keywords (provider_callback_data); + EventPipeEventLevel provider_level = ep_provider_callback_data_get_provider_level (provider_callback_data); + void *callback_data = ep_provider_callback_data_get_callback_data (provider_callback_data); + + bool is_event_filter_desc_init = false; + EventFilterDescriptor event_filter_desc; + uint8_t *buffer = NULL; + + if (filter_data) { + // The callback is expecting that filter data to be a concatenated list + // of pairs of null terminated strings. The first member of the pair is + // the key and the second is the value. + // To convert to this format we need to convert all '=' and ';' + // characters to '\0', except when in a quoted string. + const uint32_t filter_data_len = ep_rt_utf8_string_len (filter_data); + uint32_t buffer_size = filter_data_len + 1; + + buffer = ep_rt_byte_array_alloc (buffer_size); + ep_raise_error_if_nok (buffer != NULL); + + bool is_quoted_value = false; + uint32_t j = 0; + + for (uint32_t i = 0; i < buffer_size; ++i) { + // if a value is a quoted string, leave the quotes out from the destination + // and don't replace `=` or `;` characters until leaving the quoted section + // e.g., key="a;value=";foo=bar --> { key\0a;value=\0foo\0bar\0 } + if (filter_data [i] == '"') { + is_quoted_value = !is_quoted_value; + continue; + } + buffer [j++] = ((filter_data [i] == '=' || filter_data [i] == ';') && !is_quoted_value) ? '\0' : filter_data [i]; + } + + // In case we skipped over quotes in the filter string, shrink the buffer size accordingly + if (j < filter_data_len) + buffer_size = j + 1; + + ep_event_filter_desc_init (&event_filter_desc, (uint64_t)buffer, buffer_size, 0); + is_event_filter_desc_init = true; + } + + if (callback_function && !ep_rt_process_detach ()) { + (*callback_function)( + NULL, /* provider_id */ + enabled ? 1 : 0, + (uint8_t)provider_level, + (uint64_t)keywords, + 0, /* match_all_keywords */ + is_event_filter_desc_init ? &event_filter_desc : NULL, + callback_data /* CallbackContext */); + } + +ep_on_exit: + if (is_event_filter_desc_init) + ep_event_filter_desc_fini (&event_filter_desc); + + ep_rt_byte_array_free (buffer); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_provider; +const char quiet_linker_empty_file_warning_eventpipe_provider = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-provider.h b/src/mono/mono/eventpipe/ep-provider.h new file mode 100644 index 0000000000000..3d95ec8122382 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-provider.h @@ -0,0 +1,123 @@ +#ifndef __EVENTPIPE_PROVIDER_H__ +#define __EVENTPIPE_PROVIDER_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeProvider. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProvider { +#else +struct _EventPipeProvider_Internal { +#endif + ep_char8_t *provider_name; + ep_char16_t *provider_name_utf16; + int64_t keywords; + EventPipeEventLevel provider_level; + ep_rt_event_list_t event_list; + EventPipeCallback callback_func; + void *callback_data; + EventPipeConfiguration *config; + bool delete_deferred; + uint64_t sessions; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProvider { + uint8_t _internal [sizeof (struct _EventPipeProvider_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeProvider *, provider, const ep_char8_t *, provider_name) +EP_DEFINE_GETTER(EventPipeProvider *, provider, const ep_char16_t *, provider_name_utf16) +EP_DEFINE_GETTER(EventPipeProvider *, provider, uint64_t, keywords) +EP_DEFINE_SETTER(EventPipeProvider *, provider, uint64_t, keywords) +EP_DEFINE_GETTER(EventPipeProvider *, provider, EventPipeEventLevel, provider_level) +EP_DEFINE_SETTER(EventPipeProvider *, provider, EventPipeEventLevel, provider_level) +EP_DEFINE_GETTER_REF(EventPipeProvider *, provider, ep_rt_event_list_t *, event_list) +EP_DEFINE_GETTER(EventPipeProvider *, provider, EventPipeCallback, callback_func) +EP_DEFINE_GETTER(EventPipeProvider *, provider, void *, callback_data) +EP_DEFINE_GETTER(EventPipeProvider *, provider, EventPipeConfiguration *, config) +EP_DEFINE_GETTER(EventPipeProvider *, provider, bool, delete_deferred) +EP_DEFINE_SETTER(EventPipeProvider *, provider, bool, delete_deferred) +EP_DEFINE_GETTER(EventPipeProvider *, provider, uint64_t, sessions) +EP_DEFINE_SETTER(EventPipeProvider *, provider, uint64_t, sessions) + +static +inline +bool +ep_provider_get_enabled (const EventPipeProvider *provider) +{ + return ep_provider_get_sessions (provider) != 0; +} + +static +inline +const ep_char8_t * +ep_provider_get_wildcard_name_utf8 (void) +{ + return "*"; +} + +static +inline +const ep_char8_t * +ep_provider_get_default_name_utf8 (void) +{ + return "Microsoft-DotNETCore-EventPipe"; +} + +EventPipeProvider * +ep_provider_alloc ( + EventPipeConfiguration *config, + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data); + +void +ep_provider_free (EventPipeProvider * provider); + +EventPipeEvent * +ep_provider_add_event ( + EventPipeProvider *provider, + uint32_t event_id, + uint64_t keywords, + uint32_t event_version, + EventPipeEventLevel level, + bool need_stack, + const uint8_t *metadata, + uint32_t metadata_len); + +const EventPipeProviderCallbackData * +ep_provider_set_config_lock_held ( + EventPipeProvider *provider, + int64_t keywords_for_all_sessions, + EventPipeEventLevel level_for_all_sessions, + uint64_t session_mask, + int64_t keywords, + EventPipeEventLevel level, + const ep_char8_t *filter_data, + EventPipeProviderCallbackData *callback_data); + +const EventPipeProviderCallbackData * +ep_provider_unset_config_lock_held ( + EventPipeProvider *provider, + int64_t keywords_for_all_sessions, + EventPipeEventLevel level_for_all_sessions, + uint64_t session_mask, + int64_t keywords, + EventPipeEventLevel level, + const ep_char8_t *filter_data, + EventPipeProviderCallbackData *callback_data); + +void +ep_provider_invoke_callback (EventPipeProviderCallbackData *provider_callback_data); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_PROVIDER_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-rt-config-mono.h b/src/mono/mono/eventpipe/ep-rt-config-mono.h new file mode 100644 index 0000000000000..0e5eb527c2f78 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt-config-mono.h @@ -0,0 +1,7 @@ +#ifndef __EVENTPIPE_RT_CONFIG_MONO_H__ +#define __EVENTPIPE_RT_CONFIG_MONO_H__ + +#include +#define EP_RT_MONO_USE_STATIC_RUNTIME + +#endif /* __EVENTPIPE_RT_CONFIG_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt-config.h b/src/mono/mono/eventpipe/ep-rt-config.h new file mode 100644 index 0000000000000..5c1499ca72c89 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt-config.h @@ -0,0 +1,9 @@ +#ifndef __EVENTPIPE_RT_CONFIG_H__ +#define __EVENTPIPE_RT_CONFIG_H__ + +#include "ep-rt-config-mono.h" + +#define EP_INLINE_GETTER_SETTER +#define EP_INCLUDE_SOURCE_FILES + +#endif /* __EVENTPIPE_RT_CONFIG_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c new file mode 100644 index 0000000000000..26d3df4a2fda6 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -0,0 +1,14 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" + +#include "ep.h" + +ep_rt_spin_lock_handle_t _ep_rt_mono_config_lock = {0}; +EventPipeMonoFuncTable _ep_rt_mono_func_table = {0}; + +#endif /* ENABLE_PERFTRACING */ + +extern const char quiet_linker_empty_file_warning_eventpipe_rt_mono; +const char quiet_linker_empty_file_warning_eventpipe_rt_mono = 0; diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h new file mode 100644 index 0000000000000..8bcb8a1b39505 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt-mono.h @@ -0,0 +1,1108 @@ +// Implementation of ep-rt.h targeting Mono runtime. +#ifndef __EVENTPIPE_RT_MONO_H__ +#define __EVENTPIPE_RT_MONO_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "ep.h" + +#undef EP_ARRAY_SIZE +#define EP_ARRAY_SIZE(expr) G_N_ELEMENTS(expr) + +#undef EP_INFINITE_WAIT +#define EP_INFINITE_WAIT MONO_INFINITE_WAIT + +//TODO: Should make sure block is executed in safe mode. +#undef EP_GCX_PREEMP_ENTER +#define EP_GCX_PREEMP_ENTER { + +//TODO: Should make sure block is returned back to previous mode. +#undef EP_GCX_PREEMP_EXIT +#define EP_GCX_PREEMP_EXIT } + +#define EP_RT_DEFINE_LIST(list_name, list_type, item_type) \ + static inline void ep_rt_ ## list_name ## _free (list_type *list, void (*callback)(void *)) { \ + for (GSList *l = list->list; l; l = l->next) { \ + if (callback != NULL) \ + callback (l->data); \ + } \ + g_slist_free (list->list); \ + list->list = NULL; \ + } \ + static inline void ep_rt_ ## list_name ## _clear (list_type *list, void (*callback)(void *)) { ep_rt_ ## list_name ## _free (list, callback); } \ + static inline void ep_rt_ ## list_name ## _append (list_type *list, item_type item) { list->list = g_slist_append (list->list, ((gpointer)(gsize)item)); } \ + static inline void ep_rt_ ## list_name ## _remove (list_type *list, const item_type item) { list->list = g_slist_remove (list->list, ((gconstpointer)(const gsize)item)); } \ + static inline bool ep_rt_ ## list_name ## _find (const list_type *list, const item_type item_to_find, item_type *found_item) { \ + GSList *found_glist_item = g_slist_find (list->list, ((gconstpointer)(const gsize)item_to_find)); \ + *found_item = (found_glist_item != NULL) ? ((item_type)(gsize)(found_glist_item->data)) : ((item_type)(gsize)NULL); \ + return *found_item != NULL; \ + } \ + static inline bool ep_rt_ ## list_name ## _is_empty (const list_type *list) { return list->list == NULL; } + +#define EP_RT_DEFINE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \ + static inline void ep_rt_ ## list_name ## _iterator_begin (const list_type *list, iterator_type *iterator) { iterator->iterator = list->list; } \ + static inline bool ep_rt_ ## list_name ## _iterator_end (const list_type *list, const iterator_type *iterator) { return iterator->iterator == NULL; } \ + static inline void ep_rt_ ## list_name ## _iterator_next (const list_type *list, iterator_type *iterator) { iterator->iterator = iterator->iterator->next; } \ + static inline item_type ep_rt_ ## list_name ## _iterator_value (const iterator_type *iterator) { return ((item_type)(gsize)(iterator->iterator->data)); } + +#define EP_RT_DEFINE_QUEUE(queue_name, queue_type, item_type) \ + static inline void ep_rt_ ## queue_name ## _alloc (queue_type *queue) { \ + queue->queue = g_queue_new ();\ + } \ + static inline void ep_rt_ ## queue_name ## _free (queue_type *queue) { \ + g_queue_free (queue->queue); \ + queue->queue = NULL; \ + } \ + static inline void ep_rt_ ## queue_name ## _pop_head (queue_type *queue, item_type *item) { \ + *item = ((item_type)(gsize)g_queue_pop_head (queue->queue)); \ + } \ + static inline void ep_rt_ ## queue_name ## _push_head (queue_type *queue, item_type item) { \ + g_queue_push_head (queue->queue, ((gpointer)(gsize)item)); \ + } \ + static inline void ep_rt_ ## queue_name ## _push_tail (queue_type *queue, item_type item) { \ + g_queue_push_tail (queue->queue, ((gpointer)(gsize)item)); \ + } \ + static inline bool ep_rt_ ## queue_name ## _is_empty (const queue_type *queue) { \ + return g_queue_is_empty (queue->queue); \ + } + +#define EP_RT_DEFINE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \ + static inline void ep_rt_ ## hash_map_name ## _alloc (hash_map_type *hash_map, uint32_t (*hash_callback)(const void *), bool (*eq_callback)(const void *, const void *), void (*key_free_callback)(void *), void (*value_free_callback)(void *)) { \ + hash_map->table = g_hash_table_new_full ((GHashFunc)hash_callback, (GEqualFunc)eq_callback, (GDestroyNotify)key_free_callback, (GDestroyNotify)value_free_callback); \ + hash_map->count = 0;\ + } \ + static inline void ep_rt_ ## hash_map_name ## _free (hash_map_type *hash_map) { \ + g_hash_table_destroy (hash_map->table); \ + hash_map->table = NULL; \ + hash_map->count = 0; \ + } \ + static inline void ep_rt_ ## hash_map_name ## _add (hash_map_type *hash_map, key_type key, value_type value) { \ + g_hash_table_replace (hash_map->table, (gpointer)key, ((gpointer)(gsize)value)); \ + hash_map->count++; \ + } \ + static inline void ep_rt_ ## hash_map_name ## _remove (hash_map_type *hash_map, const key_type key) { \ + if (g_hash_table_remove (hash_map->table, (gconstpointer)key)) \ + hash_map->count--; \ + } \ + static inline void ep_rt_ ## hash_map_name ## _remove_all (hash_map_type *hash_map) { \ + g_hash_table_remove_all (hash_map->table); \ + hash_map->count = 0; \ + } \ + static inline bool ep_rt_ ## hash_map_name ## _lookup (const hash_map_type *hash_map, const key_type key, value_type *value) { \ + gpointer _value = NULL; \ + bool result = g_hash_table_lookup_extended (hash_map->table, (gconstpointer)key, NULL, &_value); \ + *value = ((value_type)(gsize)_value); \ + return result; \ + } \ + static inline uint32_t ep_rt_ ## hash_map_name ## _count (const hash_map_type *hash_map) { \ + return hash_map->count; \ + } + +#define EP_RT_DEFINE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ + static inline void ep_rt_ ## hash_map_name ## _iterator_begin (const hash_map_type *hash_map, iterator_type *iterator) { \ + g_hash_table_iter_init (&iterator->iterator, hash_map->table); \ + if (hash_map->table) \ + iterator->end = g_hash_table_iter_next (&iterator->iterator, &iterator->key, &iterator->value); \ + else \ + iterator->end = true; \ + } \ + static inline bool ep_rt_ ## hash_map_name ## _iterator_end (const hash_map_type *hash_map, const iterator_type *iterator) { \ + return iterator->end; \ + } \ + static inline void ep_rt_ ## hash_map_name ## _iterator_next (const hash_map_type *hash_map, iterator_type *iterator) { \ + iterator->end = g_hash_table_iter_next (&iterator->iterator, &iterator->key, &iterator->value); \ + } \ + static inline key_type ep_rt_ ## hash_map_name ## _iterator_key (const iterator_type *iterator) { \ + return ((key_type)(gsize)iterator->key); \ + } \ + static inline value_type ep_rt_ ## hash_map_name ## _iterator_value (const iterator_type *iterator) { \ + return ((value_type)(gsize)iterator->value); \ + } + +typedef gint64 (*ep_rt_mono_100ns_ticks_func)(void); +typedef gint64 (*ep_rt_mono_100ns_datetime_func)(void); +typedef int (*ep_rt_mono_cpu_count_func)(void); +typedef int (*ep_rt_mono_process_current_pid_func)(void); +typedef MonoNativeThreadId (*ep_rt_mono_native_thread_id_get_func)(void); +typedef gboolean (*ep_rt_mono_native_thread_id_equals_func)(MonoNativeThreadId, MonoNativeThreadId); +typedef mono_bool (*ep_rt_mono_runtime_is_shutting_down_func)(void); +typedef gboolean (*ep_rt_mono_rand_try_get_bytes_func)(guchar *buffer, gssize buffer_size, MonoError *error); +typedef EventPipeThread * (*ep_rt_mono_thread_get_func)(void); +typedef EventPipeThread * (*ep_rt_mono_thread_get_or_create_func)(void); +typedef void (*ep_rt_mono_thread_exited_func)(void); +typedef gpointer (*ep_rt_mono_w32file_create_func)(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs); +typedef gboolean (*ep_rt_mono_w32file_write_func)(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, gint32 *win32error); +typedef gboolean (*ep_rt_mono_w32file_close_func)(gpointer handle); + +typedef struct _EventPipeMonoFuncTable { + ep_rt_mono_100ns_ticks_func ep_rt_mono_100ns_ticks; + ep_rt_mono_100ns_datetime_func ep_rt_mono_100ns_datetime; + ep_rt_mono_process_current_pid_func ep_rt_mono_process_current_pid; + ep_rt_mono_cpu_count_func ep_rt_mono_cpu_count; + ep_rt_mono_native_thread_id_get_func ep_rt_mono_native_thread_id_get; + ep_rt_mono_native_thread_id_equals_func ep_rt_mono_native_thread_id_equals; + ep_rt_mono_runtime_is_shutting_down_func ep_rt_mono_runtime_is_shutting_down; + ep_rt_mono_rand_try_get_bytes_func ep_rt_mono_rand_try_get_bytes; + ep_rt_mono_thread_get_func ep_rt_mono_thread_get; + ep_rt_mono_thread_get_or_create_func ep_rt_mono_thread_get_or_create; + ep_rt_mono_thread_exited_func ep_rt_mono_thread_exited; + ep_rt_mono_w32file_create_func ep_rt_mono_w32file_create; + ep_rt_mono_w32file_write_func ep_rt_mono_w32file_write; + ep_rt_mono_w32file_close_func ep_rt_mono_w32file_close; +} EventPipeMonoFuncTable; + +typedef EventPipeThreadHolder * (*ep_rt_thread_holder_alloc_func)(void); +typedef void (*ep_rt_thread_holder_free_func)(EventPipeThreadHolder *thread_holder); + +static +inline +ep_rt_spin_lock_handle_t * +ep_rt_mono_config_lock_get (void) +{ + extern ep_rt_spin_lock_handle_t _ep_rt_mono_config_lock; + return &_ep_rt_mono_config_lock; +} + +static +inline +EventPipeMonoFuncTable * +ep_rt_mono_func_table_get (void) +{ + extern EventPipeMonoFuncTable _ep_rt_mono_func_table; + return &_ep_rt_mono_func_table; +} + +MONO_PROFILER_API +void +mono_eventpipe_init ( + EventPipeMonoFuncTable *table, + ep_rt_thread_holder_alloc_func thread_holder_alloc_func, + ep_rt_thread_holder_free_func thread_holder_free_func); + +MONO_PROFILER_API +void +mono_eventpipe_fini (void); + +/* +* Helpers +*/ + +static +inline +MonoNativeThreadId +ep_rt_mono_native_thread_id_get (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return mono_native_thread_id_get (); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_native_thread_id_get (); +#endif +} + +static +inline +gboolean +ep_rt_mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return mono_native_thread_id_equals (id1, id2); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_native_thread_id_equals (id1, id2); +#endif +} + +static +inline +gboolean +ep_rt_mono_rand_try_get_bytes (guchar *buffer, gssize buffer_size, MonoError *error) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + extern gpointer ep_rt_mono_rand_provider; + g_assert (ep_rt_mono_rand_provider != NULL); + return mono_rand_try_get_bytes (&ep_rt_mono_rand_provider, buffer, buffer_size, error); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_rand_try_get_bytes (buffer, buffer_size, error); +#endif +} + +static +inline +void +ep_rt_mono_thread_exited (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + extern gboolean ep_rt_mono_initialized; + extern MonoNativeTlsKey ep_rt_mono_thread_holder_tls_id; + if (ep_rt_mono_initialized) { + EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id); + if (thread_holder) + ep_thread_holder_free (thread_holder); + mono_native_tls_set_value (ep_rt_mono_thread_holder_tls_id, NULL); + } +#else + ep_rt_mono_func_table_get ()->ep_rt_mono_thread_exited (); +#endif +} + +static +inline +gpointer +ep_rt_mono_w32file_create (const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return mono_w32file_create (name, fileaccess, sharemode, createmode, attrs); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_w32file_create (name, fileaccess, sharemode, createmode, attrs); +#endif +} + +static +inline +gboolean +ep_rt_mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, gint32 *win32error) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return mono_w32file_write (handle, buffer, numbytes, byteswritten, win32error); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_w32file_write (handle, buffer, numbytes, byteswritten, win32error); +#endif +} + +static +inline +gboolean +ep_rt_mono_w32file_close (gpointer handle) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return mono_w32file_close (handle); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_w32file_close (handle); +#endif +} + +/* +* Atomics. +*/ + +static +inline +uint32_t +ep_rt_atomic_inc_uint32_t (volatile uint32_t *value) +{ + return (uint32_t)mono_atomic_inc_i32 ((volatile gint32 *)value); +} + +static +inline +uint32_t +ep_rt_atomic_dec_uint32_t (volatile uint32_t *value) +{ + return (uint32_t)mono_atomic_dec_i32 ((volatile gint32 *)value); +} + +static +inline +int32_t +ep_rt_atomic_inc_int32_t (volatile int32_t *value) +{ + return (int32_t)mono_atomic_inc_i32 ((volatile gint32 *)value); +} + +static +inline +int32_t +ep_rt_atomic_dec_int32_t (volatile int32_t *value) +{ + return (int32_t)mono_atomic_dec_i32 ((volatile gint32 *)value); +} + +/* + * EventPipe. + */ + +static +EventPipeThreadHolder * +thread_holder_alloc_func (void) +{ + return ep_thread_holder_alloc (ep_thread_alloc()); +} + +static +void +thread_holder_free_func (EventPipeThreadHolder * thread_holder) +{ + ep_thread_holder_free (thread_holder); +} + +static +inline +void +ep_rt_init (void) +{ + mono_eventpipe_init (ep_rt_mono_func_table_get (), thread_holder_alloc_func, thread_holder_free_func); + ep_rt_spin_lock_alloc (ep_rt_mono_config_lock_get ()); +} + +static +inline +void +ep_rt_shutdown (void) +{ + ep_rt_spin_lock_free (ep_rt_mono_config_lock_get ()); + mono_eventpipe_fini (); +} + +static +inline +bool +ep_rt_config_aquire (void) +{ + ep_rt_spin_lock_aquire (ep_rt_mono_config_lock_get ()); + return true; +} + +static +inline +void +ep_rt_config_release (void) +{ + ep_rt_spin_lock_release (ep_rt_mono_config_lock_get ()); +} + +#ifdef EP_CHECKED_BUILD +static +inline +void +ep_rt_config_requires_lock_held (void) +{ + ep_rt_spin_lock_requires_lock_held (ep_rt_mono_config_lock_get ()); +} + +static +inline +void +ep_rt_config_requires_lock_not_held (void) +{ + ep_rt_spin_lock_requires_lock_not_held (ep_rt_mono_config_lock_get ()); +} +#endif + +/* + * EventPipeEvent. + */ + +EP_RT_DEFINE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *) +EP_RT_DEFINE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *) + +/* + * EventPipeFile. + */ + +EP_RT_DEFINE_HASH_MAP(metadata_labels, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t) +EP_RT_DEFINE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *) +EP_RT_DEFINE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *) + +/* + * EventPipeProvider. + */ + +EP_RT_DEFINE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *) +EP_RT_DEFINE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *) + +EP_RT_DEFINE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *) + +static +inline +int +compare_provider_name ( + gconstpointer a, + gconstpointer b) +{ + return (a) ? ep_rt_utf8_string_compare (ep_provider_get_provider_name ((EventPipeProvider *)a), (const ep_char8_t *)b) : 1; +} + +static +inline +EventPipeProvider * +ep_rt_provider_list_find_by_name ( + const ep_rt_provider_list_t *list, + const ep_char8_t *name) +{ + GSList *item = g_slist_find_custom (list->list, name, compare_provider_name); + return (item != NULL) ? (EventPipeProvider *)item->data : NULL; +} + +/* + * EventPipeSampleProfiler. + */ + +static +inline +void +ep_rt_sample_profiler_init (EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + //TODO: Not supported. +} + +static +inline +void +ep_rt_sample_profiler_enable (void) +{ + //TODO: Not supported. +} + +static +inline +void +ep_rt_sample_profiler_disable (void) +{ + //TODO: Not supported. +} + +static +uint32_t +ep_rt_sample_profiler_get_sampling_rate (void) +{ + //TODO: Not supported. + return 0; +} + +/* + * EvetPipeSessionProvider. + */ + +EP_RT_DEFINE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *) +EP_RT_DEFINE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *) + +static +inline +int +compare_session_provider_name ( + gconstpointer a, + gconstpointer b) +{ + return (a) ? ep_rt_utf8_string_compare (ep_session_provider_get_provider_name ((EventPipeSessionProvider *)a), (const ep_char8_t *)b) : 1; +} + +static +inline +EventPipeSessionProvider * +ep_rt_session_provider_list_find_by_name ( + const ep_rt_session_provider_list_t *list, + const ep_char8_t *name) +{ + GSList *item = g_slist_find_custom (list->list, name, compare_provider_name); + return (item != NULL) ? (EventPipeSessionProvider *)item->data : NULL; +} + +/* + * Arrays. + */ + +static +inline +uint8_t * +ep_rt_byte_array_alloc (size_t len) +{ + return g_new(uint8_t, len); +} + +static +inline +void +ep_rt_byte_array_free (uint8_t *ptr) +{ + g_free (ptr); +} + +/* + * Event. + */ + +static +inline +void +ep_rt_wait_event_alloc (ep_rt_wait_event_handle_t *wait_event) +{ + EP_ASSERT (wait_event != NULL); + wait_event->event = g_new0 (MonoOSEvent, 1); + if (wait_event->event) + mono_os_event_init (wait_event->event, false); +} + +static +inline +void +ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event) +{ + if (wait_event != NULL && wait_event->event != NULL) { + mono_os_event_destroy (wait_event->event); + g_free (wait_event->event); + wait_event->event = NULL; + } +} + +static +inline +bool +ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event) +{ + EP_ASSERT (wait_event != NULL && wait_event->event != NULL); + mono_os_event_set (wait_event->event); + return true; +} + +static +inline +int32_t +ep_rt_wait_event_wait ( + ep_rt_wait_event_handle_t *wait_event, + uint32_t timeout, + bool alertable) +{ + EP_ASSERT (wait_event != NULL && wait_event->event != NULL); + return mono_os_event_wait_one (wait_event->event, timeout, alertable); +} + +static +inline +EventPipeWaitHandle +ep_rt_wait_event_get_wait_handle (ep_rt_wait_event_handle_t *wait_event) +{ + EP_ASSERT (wait_event != NULL); + return (EventPipeWaitHandle)wait_event; +} + +/* + * Misc. + */ + +static +inline +bool +ep_rt_process_detach (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return (bool)mono_runtime_is_shutting_down (); +#else + return (bool)ep_rt_mono_func_table_get ()->ep_rt_mono_runtime_is_shutting_down (); +#endif +} + +static +inline +void +ep_rt_create_activity_id ( + uint8_t *activity_id, + uint32_t activity_id_len) +{ + EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE); + + ERROR_DECL (error); + ep_rt_mono_rand_try_get_bytes ((guchar *)activity_id, EP_ACTIVITY_ID_SIZE, error); + + const uint16_t version_mask = 0xF000; + const uint16_t random_guid_version = 0x4000; + const uint8_t clock_seq_hi_and_reserved_mask = 0xC0; + const uint8_t clock_seq_hi_and_reserved_value = 0x80; + + // Modify bits indicating the type of the GUID + uint8_t *activity_id_c = activity_id + sizeof (uint32_t) + sizeof (uint16_t); + uint8_t *activity_id_d = activity_id + sizeof (uint32_t) + sizeof (uint16_t) + sizeof (uint16_t); + + uint16_t c; + memcpy (&c, activity_id_c, sizeof (c)); + + uint8_t d; + memcpy (&d, activity_id_d, sizeof (d)); + + // time_hi_and_version + c = ((c & ~version_mask) | random_guid_version); + // clock_seq_hi_and_reserved + d = ((d & ~clock_seq_hi_and_reserved_mask) | clock_seq_hi_and_reserved_value); + + memcpy (activity_id_c, &c, sizeof (c)); + memcpy (activity_id_d, &d, sizeof (d)); +} + +/* + * Objects. + */ + +#undef ep_rt_object_alloc +#define ep_rt_object_alloc(obj_type) (g_new0 (obj_type, 1)) + +static +inline +void +ep_rt_object_free (void *ptr) +{ + g_free (ptr); +} + +/* + * PAL. + */ + +static +inline +uint32_t +ep_rt_current_process_get_id (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return (uint32_t)mono_process_current_pid (); +#else + return (uint32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_process_current_pid (); +#endif +} + +static +inline +uint32_t +ep_rt_current_processor_get_number (void) +{ + return 0xFFFFFFFF; +} + +static +inline +uint32_t +ep_rt_processors_get_count (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return (uint32_t)mono_cpu_count (); +#else + return (uint32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_cpu_count (); +#endif +} + +static +inline +size_t +ep_rt_current_thread_get_id (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()); +#else + return MONO_NATIVE_THREAD_ID_TO_UINT (ep_rt_mono_func_table_get ()->ep_rt_mono_native_thread_id_get ()); +#endif +} + +static +inline +uint64_t +ep_rt_perf_counter_query (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return (uint64_t)mono_100ns_ticks (); +#else + return (uint64_t)ep_rt_mono_func_table_get ()->ep_rt_mono_100ns_ticks (); +#endif +} + +static +inline +uint64_t +ep_rt_perf_frequency_query (void) +{ + //Counter uses resolution of 100ns ticks. + return 100 * 1000 * 1000; +} + +static +inline +uint64_t +ep_rt_system_time_get (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + return (uint64_t)mono_100ns_datetime (); +#else + return (uint64_t)ep_rt_mono_func_table_get ()->ep_rt_mono_100ns_datetime (); +#endif +} + +static +inline +const ep_char8_t * +ep_rt_command_line_get (void) +{ + //TODO: Implement. + return ""; +} + +static +inline +ep_rt_file_handle_t +ep_rt_file_open_write (const ep_char8_t *path) +{ + ep_char16_t *path_utf16 = ep_rt_utf8_to_utf16_string (path, -1); + ep_return_null_if_nok (path_utf16 != NULL); + + gpointer file_handle = ep_rt_mono_w32file_create (path_utf16, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, FileAttributes_Normal); + ep_rt_utf16_string_free (path_utf16); + + return file_handle; +} + +static +bool +ep_rt_file_close (ep_rt_file_handle_t file_handle) +{ + ep_return_false_if_nok (file_handle != NULL); + return ep_rt_mono_w32file_close (file_handle); +} + +static +bool +ep_rt_file_write ( + ep_rt_file_handle_t file_handle, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + ep_return_false_if_nok (file_handle != NULL); + EP_ASSERT (buffer != NULL); + + gint32 win32_error; + bool result = ep_rt_mono_w32file_write (file_handle, buffer, bytes_to_write, bytes_written, &win32_error); + if (result) + *bytes_written = bytes_to_write; + + return result; +} + +/* +* SpinLock. +*/ + +static +inline +void +ep_rt_spin_lock_alloc (ep_rt_spin_lock_handle_t *spin_lock) +{ +#ifdef EP_CHECKED_BUILD + spin_lock->lock_is_held = false; +#endif + spin_lock->lock = g_new0 (MonoCoopMutex, 1); + if (spin_lock->lock) + mono_coop_mutex_init (spin_lock->lock); +} + +static +inline +void +ep_rt_spin_lock_free (ep_rt_spin_lock_handle_t *spin_lock) +{ + if (spin_lock && spin_lock->lock) { + mono_coop_mutex_destroy (spin_lock->lock); + g_free (spin_lock->lock); + spin_lock->lock = NULL; + } +} + +static +inline +void +ep_rt_spin_lock_aquire (ep_rt_spin_lock_handle_t *spin_lock) +{ + if (spin_lock && spin_lock->lock) { + mono_coop_mutex_lock (spin_lock->lock); +#ifdef EP_CHECKED_BUILD + spin_lock->owning_thread_id = ep_rt_mono_native_thread_id_get (); + spin_lock->lock_is_held = true; +#endif + } +} + +static +inline +void +ep_rt_spin_lock_release (ep_rt_spin_lock_handle_t *spin_lock) +{ + if (spin_lock && spin_lock->lock) { +#ifdef EP_CHECKED_BUILD + spin_lock->lock_is_held = false; +#endif + mono_coop_mutex_unlock (spin_lock->lock); + } +} + +#ifdef EP_CHECKED_BUILD +static +inline +void +ep_rt_spin_lock_requires_lock_held (const ep_rt_spin_lock_handle_t *spin_lock) +{ + g_assert (spin_lock->lock_is_held && ep_rt_mono_native_thread_id_equals (spin_lock->owning_thread_id, ep_rt_mono_native_thread_id_get ())); +} + +static +inline +void +ep_rt_spin_lock_requires_lock_not_held (const ep_rt_spin_lock_handle_t *spin_lock) +{ + g_assert (!spin_lock->lock_is_held || (spin_lock->lock_is_held && !ep_rt_mono_native_thread_id_equals (spin_lock->owning_thread_id, ep_rt_mono_native_thread_id_get ()))); +} +#endif + +/* + * String. + */ + +static +inline +size_t +ep_rt_utf8_string_len (const ep_char8_t *str) +{ + return g_utf8_strlen ((const gchar *)str, -1); +} + +static +inline +int +ep_rt_utf8_string_compare ( + const ep_char8_t *str1, + const ep_char8_t *str2) +{ + return strcmp ((const char *)str1, (const char *)str2); +} + +static +inline +ep_char16_t * +ep_rt_utf8_to_utf16_string ( + const ep_char8_t *str, + size_t len) +{ + return (ep_char16_t *)(g_utf8_to_utf16 ((const gchar *)str, len, NULL, NULL, NULL)); +} + +static +inline +ep_char8_t * +ep_rt_utf8_string_dup (const ep_char8_t *str) +{ + return g_strdup (str); +} + +static +inline +void +ep_rt_utf8_string_free (ep_char8_t *str) +{ + g_free (str); +} + +static +inline +size_t +ep_rt_utf16_string_len (const ep_char16_t *str) +{ + return g_utf16_len ((const gunichar2 *)str); +} + +static +inline +ep_char8_t * +ep_rt_utf16_to_utf8_string ( + const ep_char16_t *str, + size_t len) +{ + return g_utf16_to_utf8 ((const gunichar2 *)str, len, NULL, NULL, NULL); +} + +static +inline +void +ep_rt_utf16_string_free (ep_char16_t *str) +{ + g_free (str); +} + +static +inline +const ep_char8_t * +ep_rt_managed_command_line_get (void) +{ + //TODO: Implement. + return ""; +} + +/* + * Thread. + */ +static +inline +void +ep_rt_thread_setup (void) +{ + //TODO: Is this needed on Mono runtime? Looks like a thread attach, making sure thread is attached to runtime. +} + +static +inline +EventPipeThread * +ep_rt_thread_get (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + extern MonoNativeTlsKey ep_rt_mono_thread_holder_tls_id; + EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id); + return thread_holder ? ep_thread_holder_get_thread (thread_holder) : NULL; +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_thread_get (); +#endif +} + +static +inline +EventPipeThread * +ep_rt_thread_get_or_create (void) +{ +#ifdef EP_RT_MONO_USE_STATIC_RUNTIME + extern MonoNativeTlsKey ep_rt_mono_thread_holder_tls_id; + EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id); + if (!thread_holder) { + thread_holder = thread_holder_alloc_func (); + mono_native_tls_set_value (ep_rt_mono_thread_holder_tls_id, thread_holder); + } + return ep_thread_holder_get_thread (thread_holder); +#else + return ep_rt_mono_func_table_get ()->ep_rt_mono_thread_get_or_create (); +#endif +} + +/* + * ThreadSequenceNumberMap. + */ + +EP_RT_DEFINE_HASH_MAP(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t) +EP_RT_DEFINE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t) + +/* + * Volatile. + */ + +static +inline +uint32_t +ep_rt_volatile_load_uint32_t (const volatile uint32_t *ptr) +{ + return mono_atomic_load_i32 ((volatile gint32 *)ptr); +} + +static +inline +uint32_t +ep_rt_volatile_load_uint32_t_without_barrier (const volatile uint32_t *ptr) +{ + uint32_t value = *ptr; + return value; +} + +static +inline +void +ep_rt_volatile_store_uint32_t ( + volatile uint32_t *ptr, + uint32_t value) +{ + mono_atomic_store_i32 ((volatile gint32 *)ptr, (gint32)value); +} + +static +inline +void +ep_rt_volatile_store_uint32_t_without_barrier ( + volatile uint32_t *ptr, + uint32_t value) +{ + *ptr = value; +} + +static +inline +uint64_t +ep_rt_volatile_load_uint64_t (const volatile uint64_t *ptr) +{ + return mono_atomic_load_i64 ((volatile gint64 *)ptr); +} + +static +inline +uint64_t +ep_rt_volatile_load_uint64_t_without_barrier (const volatile uint64_t *ptr) +{ + uint64_t value = *ptr; + return value; +} + +static +inline +void +ep_rt_volatile_store_uint64_t ( + volatile uint64_t *ptr, + uint64_t value) +{ + mono_atomic_store_i64 ((volatile gint64 *)ptr, (gint64)value); +} + +static +inline +void +ep_rt_volatile_store_uint64_t_without_barrier ( + volatile uint64_t *ptr, + uint64_t value) +{ + *ptr = value; +} + +static +inline +void * +ep_rt_volatile_load_ptr (volatile void **ptr) +{ + return mono_atomic_load_ptr ((volatile gpointer *)ptr); +} + +static +inline +void * +ep_rt_volatile_load_ptr_without_barrier (volatile void **ptr) +{ + void *value = (void *)(*ptr); + return value; +} + +static +inline +void +ep_rt_volatile_store_ptr ( + volatile void **ptr, + void *value) +{ + mono_atomic_store_ptr ((volatile gpointer *)ptr, (gpointer)value); +} + +static +inline +void +ep_rt_volatile_store_ptr_without_barrier ( + volatile void **ptr, + void *value) +{ + *ptr = value; +} + +#endif /* ENABLE_PERFTRACING */ +#endif /* __EVENTPIPE_RT_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt-types-mono.h b/src/mono/mono/eventpipe/ep-rt-types-mono.h new file mode 100644 index 0000000000000..266f1ee25cd1f --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt-types-mono.h @@ -0,0 +1,96 @@ +// Implementation of ep-rt-types.h targeting Mono runtime. +#ifndef __EVENTPIPE_RT_TYPES_MONO_H__ +#define __EVENTPIPE_RT_TYPES_MONO_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include +#include +#include +#include + +//#ifdef ENABLE_CHECKED_BUILD +#define EP_CHECKED_BUILD +//#endif + +#undef EP_ASSERT +//#define EP_ASSERT(expr) g_assert_checked(expr) +#define EP_ASSERT(expr) g_assert(expr) + +#undef EP_LIKELY +#define EP_LIKELY(expr) G_LIKELY(expr) + +#undef EP_UNLIKELY +#define EP_UNLIKELY(expr) G_UNLIKELY(expr) + +struct _rt_mono_list_internal_t { + GSList *list; +}; + +struct _rt_mono_list_iterator_internal_t { + GSList *iterator; +}; + +typedef struct _rt_mono_list_internal_t ep_rt_provider_list_t; +typedef struct _rt_mono_list_iterator_internal_t ep_rt_provider_list_iterator_t; + +typedef struct _rt_mono_list_internal_t ep_rt_event_list_t; +typedef struct _rt_mono_list_iterator_internal_t ep_rt_event_list_iterator_t; + +typedef struct _rt_mono_list_internal_t ep_rt_session_provider_list_t; +typedef struct _rt_mono_list_iterator_internal_t ep_rt_session_provider_list_iterator_t; + +struct _rt_mono_queue_internal_t { + GQueue *queue; +}; + +typedef struct _rt_mono_queue_internal_t ep_rt_provider_callback_data_queue_t; +typedef struct _rt_mono_queue_iterator_internal_t ep_rt_provider_callback_data_queue_iterator_t; + +struct _rt_mono_table_internal_t { + GHashTable *table; + uint32_t count; +}; + +struct _rt_mono_table_iterator_internal_t { + GHashTableIter iterator; + gpointer key; + gpointer value; + bool end; +}; + +typedef struct _rt_mono_table_internal_t ep_rt_metadata_labels_hash_map_t; +typedef struct _rt_mono_iterator_table_internal_t ep_rt_metadata_labels_hash_map_iterator_t; + +typedef struct _rt_mono_table_internal_t ep_rt_stack_hash_map_t; +typedef struct _rt_mono_table_iterator_internal_t ep_rt_stack_hash_map_iterator_t; + +typedef struct _rt_mono_table_internal_t ep_rt_thread_sequence_number_hash_map_t; +typedef struct _rt_mono_table_iterator_internal_t ep_rt_thread_sequence_number_hash_map_iterator_t; + +typedef MonoThreadHandle ep_rt_thread_handle_t; +typedef gpointer ep_rt_file_handle_t; +typedef gpointer ep_rt_ipc_handle_t; +typedef MonoMethod ep_rt_method_desc_t; + +struct _rt_mono_event_internal_t { + MonoOSEvent *event; +}; + +typedef struct _rt_mono_event_internal_t ep_rt_wait_event_handle_t; + +struct _rt_mono_lock_internal_t { + MonoCoopMutex *lock; +#ifdef EP_CHECKED_BUILD + MonoNativeThreadId owning_thread_id; + bool lock_is_held; +#endif +}; + +typedef struct _rt_mono_lock_internal_t ep_rt_lock_handle_t; +typedef ep_rt_lock_handle_t ep_rt_spin_lock_handle_t; + +#endif /* ENABLE_PERFTRACING */ +#endif /* __EVENTPIPE_RT_TYPES_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt-types.h b/src/mono/mono/eventpipe/ep-rt-types.h new file mode 100644 index 0000000000000..cb0a9af82fa6d --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt-types.h @@ -0,0 +1,22 @@ +#ifndef __EVENTPIPE_RT_TYPES_H__ +#define __EVENTPIPE_RT_TYPES_H__ + +#define EP_ASSERT(expr) ep_rt_redefine +#define EP_LIKELY(expr) ep_rt_redefine +#define EP_UNLIKELY(expr) ep_rt_redefine + +/* + * ErrorHandling. + */ + +#define ep_raise_error_if_nok(expr) do { if (EP_UNLIKELY(!(expr))) goto ep_on_error; } while (0) +#define ep_raise_error() do { goto ep_on_error; } while (0) +#define ep_exit_error_handler() do { goto ep_on_exit; } while (0) +#define ep_return_null_if_nok(expr) do { if (EP_UNLIKELY(!(expr))) return NULL; } while (0) +#define ep_return_void_if_nok(expr) do { if (EP_UNLIKELY(!(expr))) return; } while (0) +#define ep_return_false_if_nok(expr) do { if (EP_UNLIKELY(!(expr))) return false; } while (0) +#define ep_return_zero_if_nok(expr) do { if (EP_UNLIKELY(!(expr))) return 0; } while (0) + +#include "ep-rt-types-mono.h" + +#endif /* __EVENTPIPE_RT_TYPES_H__ */ diff --git a/src/mono/mono/eventpipe/ep-rt.h b/src/mono/mono/eventpipe/ep-rt.h new file mode 100644 index 0000000000000..0bcdbc8cd3624 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-rt.h @@ -0,0 +1,482 @@ +#ifndef __EVENTPIPE_RT_H__ +#define __EVENTPIPE_RT_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +#define EP_ARRAY_SIZE(expr) ep_rt_redefine +#define EP_INFINITE_WAIT ep_rt_redefine + +#define EP_GCX_PREEMP_ENTER ep_rt_redefine +#define EP_GCX_PREEMP_EXIT ep_rt_redefine + +#define EP_RT_DECLARE_LIST(list_name, list_type, item_type) \ + static void ep_rt_ ## list_name ## _free (list_type *list, void (*callback)(void *)); \ + static void ep_rt_ ## list_name ## _clear (list_type *list, void (*callback)(void *)); \ + static void ep_rt_ ## list_name ## _append (list_type *list, item_type item); \ + static void ep_rt_ ## list_name ## _remove (list_type *list, const item_type item); \ + static bool ep_rt_ ## list_name ## _find (const list_type *list, const item_type item_to_find, item_type *found_item); \ + static bool ep_rt_ ## list_name ## _is_empty (const list_type *list); + +#define EP_RT_DECLARE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \ + static void ep_rt_ ## list_name ## _iterator_begin (const list_type *list, iterator_type *iterator); \ + static bool ep_rt_ ## list_name ## _iterator_end (const list_type *list, const iterator_type *iterator); \ + static void ep_rt_ ## list_name ## _iterator_next (const list_type *list, iterator_type *iterator); \ + static item_type ep_rt_ ## list_name ## _iterator_value (const iterator_type *iterator); + +#define EP_RT_DECLARE_QUEUE(queue_name, queue_type, item_type) \ + static void ep_rt_ ## queue_name ## _alloc (queue_type *queue); \ + static void ep_rt_ ## queue_name ## _free (queue_type *queue); \ + static void ep_rt_ ## queue_name ## _pop_head (queue_type *queue, item_type *item); \ + static void ep_rt_ ## queue_name ## _push_head (queue_type *queue, item_type item); \ + static void ep_rt_ ## queue_name ## _push_tail (queue_type *queue, item_type item); \ + static bool ep_rt_ ## queue_name ## _is_empty (const queue_type *queue); + +#define EP_RT_DECLARE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \ + static void ep_rt_ ## hash_map_name ## _alloc (hash_map_type *hash_map, uint32_t (*hash_callback)(const void *), bool (*eq_callback)(const void *, const void *), void (*key_free_callback)(void *), void (*value_free_callback)(void *)); \ + static void ep_rt_ ## hash_map_name ## _free (hash_map_type *hash_map); \ + static void ep_rt_ ## hash_map_name ## _add (hash_map_type *hash_map, key_type key, value_type value); \ + static void ep_rt_ ## hash_map_name ## _remove (hash_map_type *hash_map, const key_type key); \ + static void ep_rt_ ## hash_map_name ## _remove_all (hash_map_type *hash_map); \ + static bool ep_rt_ ## hash_map_name ## _lookup (const hash_map_type *hash_map, const key_type key, value_type *value); \ + static uint32_t ep_rt_ ## hash_map_name ## _count (const hash_map_type *hash_map); + +#define EP_RT_DECLARE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \ + static void ep_rt_ ## hash_map_name ## _iterator_begin (const hash_map_type *hash_map, iterator_type *iterator); \ + static bool ep_rt_ ## hash_map_name ## _iterator_end (const hash_map_type *hash_map, const iterator_type *iterator); \ + static void ep_rt_ ## hash_map_name ## _iterator_next (const hash_map_type *hash_map, iterator_type *iterator); \ + static key_type ep_rt_ ## hash_map_name ## _iterator_key (const iterator_type *iterator); \ + static value_type ep_rt_ ## hash_map_name ## _iterator_value (const iterator_type *iterator); + +/* +* Atomics. +*/ + +static +uint32_t +ep_rt_atomic_inc_uint32_t (volatile uint32_t *value); + +static +uint32_t +ep_rt_atomic_dec_uint32_t (volatile uint32_t *value); + +static +int32_t +ep_rt_atomic_inc_int32_t (volatile int32_t *value); + +static +int32_t +ep_rt_atomic_dec_int32_t (volatile int32_t *value); + +/* + * EventPipe. + */ + +static +void +ep_rt_init (void); + +static +void +ep_rt_shutdown (void); + +static +bool +ep_rt_config_aquire (void); + +static +void +ep_rt_config_release (void); + +#ifdef EP_CHECKED_BUILD +static +void +ep_rt_config_requires_lock_held (void); + +static +void +ep_rt_config_requires_lock_not_held (void); +#else +#define ep_rt_config_requires_lock_held() +#define ep_rt_config_requires_lock_not_held() +#endif + +/* + * EventPipeEvent. + */ + +EP_RT_DECLARE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *) +EP_RT_DECLARE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *) + +/* + * EventPipeFile. + */ + +EP_RT_DECLARE_HASH_MAP(metadata_labels, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t) +EP_RT_DECLARE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *) +EP_RT_DECLARE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *) + +/* + * EventPipeProvider. + */ + +EP_RT_DECLARE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *) +EP_RT_DECLARE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *) + +EP_RT_DECLARE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *) + +static +EventPipeProvider * +ep_rt_provider_list_find_by_name ( + const ep_rt_provider_list_t *list, + const ep_char8_t *name); + +/* + * EventPipeSampleProfiler. + */ + +static +void +ep_rt_sample_profiler_init (EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +static +void +ep_rt_sample_profiler_enable (void); + +static +void +ep_rt_sample_profiler_disable (void); + +static +uint32_t +ep_rt_sample_profiler_get_sampling_rate (void); + +/* + * EventPipeSessionProvider. + */ + +EP_RT_DECLARE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *) +EP_RT_DECLARE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *) + +static +EventPipeSessionProvider * +ep_rt_session_provider_list_find_by_name ( + const ep_rt_session_provider_list_t *list, + const ep_char8_t *name); + +/* + * Arrays. + */ + +static +uint8_t * +ep_rt_byte_array_alloc (size_t len); + +static +void +ep_rt_byte_array_free (uint8_t *ptr); + +/* + * Event. + */ + +static +void +ep_rt_wait_event_alloc (ep_rt_wait_event_handle_t *wait_event); + +static +void +ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event); + +static +bool +ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event); + +static +int32_t +ep_rt_wait_event_wait ( + ep_rt_wait_event_handle_t *wait_event, + uint32_t timeout, + bool alertable); + +static +EventPipeWaitHandle +ep_rt_wait_event_get_handle (ep_rt_wait_event_handle_t *wait_event); + +/* + * Misc. + */ + +static +bool +ep_rt_process_detach (void); + +static +void +ep_rt_create_activity_id ( + uint8_t *activity_id, + uint32_t activity_id_len); + +/* + * Objects. + */ + +#define ep_rt_object_alloc(obj_type) ep_rt_redefine + +static +void +ep_rt_object_free (void *ptr); + +/* + * PAL. + */ + +static +uint32_t +ep_rt_current_process_get_id (void); + +static +uint32_t +ep_rt_current_processor_get_number (void); + +static +uint32_t +ep_rt_processors_get_count (void); + +static +size_t +ep_rt_current_thread_get_id (void); + +static +uint64_t +ep_rt_perf_counter_query (void); + +static +uint64_t +ep_rt_perf_frequency_query (void); + +static +uint64_t +ep_rt_system_time_get (void); + +static +const ep_char8_t * +ep_rt_command_line_get (void); + +static +ep_rt_file_handle_t +ep_rt_file_open_write (const ep_char8_t *path); + +static +bool +ep_rt_file_close (ep_rt_file_handle_t file_handle); + +static +bool +ep_rt_file_write ( + ep_rt_file_handle_t file_handle, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +/* +* SpinLock. +*/ + +static +void +ep_rt_spin_lock_alloc (ep_rt_spin_lock_handle_t *spin_lock); + +static +void +ep_rt_spin_lock_free (ep_rt_spin_lock_handle_t *spin_lock); + +static +void +ep_rt_spin_lock_aquire (ep_rt_spin_lock_handle_t *spin_lock); + +static +void +ep_rt_spin_lock_release (ep_rt_spin_lock_handle_t *spin_lock); + +#ifdef EP_CHECKED_BUILD +static +void +ep_rt_spin_lock_requires_lock_held (const ep_rt_spin_lock_handle_t *spin_lock); + +static +void +ep_rt_spin_lock_requires_lock_not_held (const ep_rt_spin_lock_handle_t *spin_lock); +#else +#define ep_rt_spin_lock_requires_lock_held(spin_lock) +#define ep_rt_spin_lock_requires_lock_not_held(spin_lock) +#endif + +/* + * String. + */ + +static +size_t +ep_rt_utf8_string_len (const ep_char8_t *str); + +static +int +ep_rt_utf8_string_compare ( + const ep_char8_t *str1, + const ep_char8_t *str2); + +static +ep_char8_t * +ep_rt_utf8_string_dup (const ep_char8_t *str); + +static +ep_char16_t * +ep_rt_utf8_to_utf16_string ( + const ep_char8_t *str, + size_t len); + +static +void +ep_rt_utf8_string_free (ep_char8_t *str); + +static +size_t +ep_rt_utf16_string_len (const ep_char16_t *str); + +static +ep_char8_t * +ep_rt_utf16_to_utf8_string ( + const ep_char16_t *str, + size_t len); + +static +void +ep_rt_utf16_string_free (ep_char16_t *str); + +static +const ep_char8_t * +ep_rt_managed_command_line_get (void); + +/* + * Thread. + */ +static +void +ep_rt_thread_setup (void); + +static +EventPipeThread * +ep_rt_thread_get (void); + +static +EventPipeThread * +ep_rt_thread_get_or_create (void); + + +/* + * ThreadSequenceNumberMap. + */ + +EP_RT_DECLARE_HASH_MAP(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t) +EP_RT_DECLARE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t) + + +/* + * Volatile. + */ + +static +uint32_t +ep_rt_volatile_load_uint32_t (const volatile uint32_t *ptr); + +static +uint32_t +ep_rt_volatile_load_uint32_t_without_barrier (const volatile uint32_t *ptr); + +static +void +ep_rt_volatile_store_uint32_t ( + volatile uint32_t *ptr, + uint32_t value); + +static +void +ep_rt_volatile_store_uint32_t_without_barrier ( + volatile uint32_t *ptr, + uint32_t value); + +static +uint64_t +ep_rt_volatile_load_uint64_t (const volatile uint64_t *ptr); + +static +uint64_t +ep_rt_volatile_load_uint64_t_without_barrier (const volatile uint64_t *ptr); + +static +void +ep_rt_volatile_store_uint64_t ( + volatile uint64_t *ptr, + uint64_t value); + +static +void +ep_rt_volatile_store_uint64_t_without_barrier ( + volatile uint64_t *ptr, + uint64_t value); + +static +void * +ep_rt_volatile_load_ptr (volatile void **ptr); + +static +void * +ep_rt_volatile_load_ptr_without_barrier (volatile void **ptr); + +static +void +ep_rt_volatile_store_ptr ( + volatile void **ptr, + void *value); + +static +void +ep_rt_volatile_store_ptr_without_barrier ( + volatile void **ptr, + void *value); + +/* + * Enter/Exit config lock helper used with error handling macros. + */ + +#define EP_CONFIG_LOCK_ENTER \ +{ \ + ep_rt_config_requires_lock_not_held (); \ + bool _owns_lock = ep_rt_config_aquire (); \ + bool _no_error = false; \ + if (EP_UNLIKELY((!_owns_lock))) \ + goto _ep_on_lock_exit; + +#define EP_CONFIG_LOCK_EXIT \ + _no_error = true; \ +_ep_on_lock_exit: \ + if (EP_UNLIKELY((!_owns_lock))) \ + goto ep_on_error; \ + ep_rt_config_requires_lock_held (); \ + ep_rt_config_release (); \ + if (EP_UNLIKELY((!_no_error))) \ + goto ep_on_error; \ + ep_rt_config_requires_lock_not_held (); \ +} + +#define ep_raise_error_if_nok_holding_lock(expr) do { if (EP_UNLIKELY(!(expr))) goto _ep_on_lock_exit; } while (0) +#define ep_raise_error_holding_lock() do { goto _ep_on_lock_exit; } while (0) + +#include "ep-rt-mono.h" + +#endif /* ENABLE_PERFTRACING */ +#endif /* __EVENTPIPE_RT_H__ */ diff --git a/src/mono/mono/eventpipe/ep-session-internals.c b/src/mono/mono/eventpipe/ep-session-internals.c new file mode 100644 index 0000000000000..3ed2a1101cc22 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-session-internals.c @@ -0,0 +1,123 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventPipeSession. + */ + +EventPipeSession * +ep_session_alloc ( + uint32_t index, + const ep_char8_t *output_path, + IpcStream *stream, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + bool rundown_enabled) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (index < EP_MAX_NUMBER_OF_SESSIONS && format < EP_SERIALIZATION_FORMAT_COUNT && circular_buffer_size_in_mb > 0 && providers_len > 0 && providers != NULL); + + FileStreamWriter *file_stream_writer = NULL; + IpcStreamWriter *ipc_stream_writer = NULL; + + EventPipeSession *instance = ep_rt_object_alloc (EventPipeSession); + ep_raise_error_if_nok (instance != NULL); + + instance->providers = ep_session_provider_list_alloc (providers, providers_len); + ep_raise_error_if_nok (instance->providers != NULL); + + instance->index = index; + instance->rundown_enabled = rundown_enabled ? 1 : 0; + instance->session_type = session_type; + instance->format = format; + instance->rundown_requested = rundown_requested; + + size_t sequence_point_alloc_budget = 0; + + // Hard coded 10MB for now, we'll probably want to make + // this configurable later. + if (instance->session_type != EP_SESSION_TYPE_LISTENER && instance->format >= EP_SERIALIZATION_FORMAT_NETTRACE_V4) { + sequence_point_alloc_budget = 10 * 1024 * 1024; + } + + instance->buffer_manager = ep_buffer_manager_alloc (instance, ((size_t)circular_buffer_size_in_mb) << 20, sequence_point_alloc_budget); + ep_raise_error_if_nok (instance->buffer_manager != NULL); + + // Create the event pipe file. + // A NULL output path means that we should not write the results to a file. + // This is used in the EventListener case. + switch (session_type) { + case EP_SESSION_TYPE_FILE : + if (output_path) { + file_stream_writer = ep_file_stream_writer_alloc (output_path); + instance->file = ep_file_alloc (ep_file_stream_writer_get_stream_writer_ref (file_stream_writer), format); + ep_raise_error_if_nok (instance->file != NULL); + file_stream_writer = NULL; + } + break; + + case EP_SESSION_TYPE_IPCSTREAM: + ipc_stream_writer = ep_ipc_stream_writer_alloc ((uint64_t)instance, stream); + ep_raise_error_if_nok (ipc_stream_writer != NULL); + instance->file = ep_file_alloc (ep_ipc_stream_writer_get_stream_writer_ref (ipc_stream_writer), format); + ep_raise_error_if_nok (instance->file != NULL); + ipc_stream_writer = NULL; + break; + + default: + break; + } + + instance->session_start_time = ep_rt_system_time_get (); + instance->session_start_timestamp = ep_perf_counter_query (); + + ep_rt_wait_event_alloc (&instance->rt_thread_shutdown_event); + +ep_on_exit: + ep_rt_config_requires_lock_held (); + return instance; + +ep_on_error: + ep_file_stream_writer_free (file_stream_writer); + ep_ipc_stream_writer_free (ipc_stream_writer); + ep_session_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_session_free (EventPipeSession *session) +{ + ep_return_void_if_nok (session != NULL); + + EP_ASSERT (ep_session_get_ipc_streaming_enabled (session) == false); + + ep_rt_wait_event_free (&session->rt_thread_shutdown_event); + + ep_session_provider_list_free (session->providers); + + ep_buffer_manager_free (session->buffer_manager); + ep_file_free (session->file); + + ep_rt_object_free (session); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_session_internals; +const char quiet_linker_empty_file_warning_eventpipe_session_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-session-provider-internals.c b/src/mono/mono/eventpipe/ep-session-provider-internals.c new file mode 100644 index 0000000000000..5c71bb7ef7af3 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-session-provider-internals.c @@ -0,0 +1,135 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +session_provider_free_func (void *session_provider); + +/* + * EventPipeSessionProvider. + */ + +static +void +session_provider_free_func (void *session_provider) +{ + ep_session_provider_free ((EventPipeSessionProvider *)session_provider); +} + +EventPipeSessionProvider * +ep_session_provider_alloc ( + const ep_char8_t *provider_name, + uint64_t keywords, + EventPipeEventLevel logging_level, + const ep_char8_t *filter_data) +{ + EventPipeSessionProvider *instance = ep_rt_object_alloc (EventPipeSessionProvider); + ep_raise_error_if_nok (instance != NULL); + + if (provider_name) { + instance->provider_name = ep_rt_utf8_string_dup (provider_name); + ep_raise_error_if_nok (instance->provider_name != NULL); + } + + if (filter_data) { + instance->filter_data = ep_rt_utf8_string_dup (filter_data); + ep_raise_error_if_nok (instance->filter_data != NULL); + } + + instance->keywords = keywords; + instance->logging_level = logging_level; + +ep_on_exit: + return instance; + +ep_on_error: + ep_session_provider_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_session_provider_free (EventPipeSessionProvider * session_provider) +{ + ep_return_void_if_nok (session_provider != NULL); + + ep_rt_utf8_string_free (session_provider->filter_data); + ep_rt_utf8_string_free (session_provider->provider_name); + ep_rt_object_free (session_provider); +} + +/* + * EventPipeSessionProviderList. + */ + +EventPipeSessionProviderList * +ep_session_provider_list_alloc ( + const EventPipeProviderConfiguration *configs, + uint32_t configs_len) +{ + ep_return_null_if_nok ((configs_len == 0) || (configs_len > 0 && configs != NULL)); + + EventPipeSessionProviderList *instance = ep_rt_object_alloc (EventPipeSessionProviderList); + ep_raise_error_if_nok (instance != NULL); + + instance->catch_all_provider = NULL; + + for (uint32_t i = 0; i < configs_len; ++i) { + const EventPipeProviderConfiguration *config = &configs [i]; + EP_ASSERT (config != NULL); + + // Enable all events if the provider name == '*', all keywords are on and the requested level == verbose. + if ((ep_rt_utf8_string_compare(ep_provider_get_wildcard_name_utf8 (), config->provider_name) == 0) && + (config->keywords == 0xFFFFFFFFFFFFFFFF) && + ((config->logging_level == EP_EVENT_LEVEL_VERBOSE) && (instance->catch_all_provider == NULL))) { + instance->catch_all_provider = ep_session_provider_alloc (NULL, 0xFFFFFFFFFFFFFFFF, EP_EVENT_LEVEL_VERBOSE, NULL ); + ep_raise_error_if_nok (instance->catch_all_provider != NULL); + } + else { + EventPipeSessionProvider * session_provider = ep_session_provider_alloc ( + config->provider_name, + config->keywords, + config->logging_level, + config->filter_data); + ep_rt_session_provider_list_append (&instance->providers, session_provider); + } + } + +ep_on_exit: + return instance; + +ep_on_error: + ep_session_provider_list_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_session_provider_list_free (EventPipeSessionProviderList *session_provider_list) +{ + ep_return_void_if_nok (session_provider_list != NULL); + + ep_rt_session_provider_list_free (&session_provider_list->providers, session_provider_free_func); + ep_session_provider_free (session_provider_list->catch_all_provider); + ep_rt_object_free (session_provider_list); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_session_provider_internals; +const char quiet_linker_empty_file_warning_eventpipe_session_provider_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-session-provider.c b/src/mono/mono/eventpipe/ep-session-provider.c new file mode 100644 index 0000000000000..08b6db7f5a0c3 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-session-provider.c @@ -0,0 +1,60 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +session_provider_free_func (void *session_provider); + +/* + * EventPipeSessionProvider. + */ + +static +void +session_provider_free_func (void *session_provider) +{ + ep_session_provider_free ((EventPipeSessionProvider *)session_provider); +} + +/* + * EventPipeSessionProviderList. + */ + +void +ep_session_provider_list_clear (EventPipeSessionProviderList *session_provider_list) +{ + ep_return_void_if_nok (session_provider_list != NULL); + ep_rt_session_provider_list_clear (ep_session_provider_list_get_providers_ref (session_provider_list), session_provider_free_func); +} + +bool +ep_session_provider_list_is_empty (const EventPipeSessionProviderList *session_provider_list) +{ + return (ep_rt_provider_list_is_empty (ep_session_provider_list_get_providers_cref (session_provider_list)) && ep_session_provider_list_get_catch_all_provider (session_provider_list) == NULL); +} + +void +ep_session_provider_list_add_session_provider ( + EventPipeSessionProviderList *session_provider_list, + EventPipeSessionProvider *session_provider) +{ + ep_return_void_if_nok (session_provider != NULL); + ep_rt_session_provider_list_append (ep_session_provider_list_get_providers_ref (session_provider_list), session_provider); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_session_provider; +const char quiet_linker_empty_file_warning_eventpipe_session_provider = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-session-provider.h b/src/mono/mono/eventpipe/ep-session-provider.h new file mode 100644 index 0000000000000..7a2812f09f2e5 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-session-provider.h @@ -0,0 +1,86 @@ +#ifndef __EVENTPIPE_SESSION_PROVIDER_H__ +#define __EVENTPIPE_SESSION_PROVIDER_H__ + +#include "ep-rt-config.h" + +#ifdef ENABLE_PERFTRACING +#include "ep-types.h" + +/* + * EventPipeSessionProvider. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSessionProvider { +#else +struct _EventPipeSessionProvider_Internal { +#endif + ep_char8_t *provider_name; + uint64_t keywords; + EventPipeEventLevel logging_level; + ep_char8_t *filter_data; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSessionProvider { + uint8_t _internal [sizeof (struct _EventPipeSessionProvider_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t *, provider_name) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, uint64_t, keywords) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeEventLevel, logging_level) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t *, filter_data) + +EventPipeSessionProvider * +ep_session_provider_alloc ( + const ep_char8_t *provider_name, + uint64_t keywords, + EventPipeEventLevel logging_level, + const ep_char8_t *filter_data); + +void +ep_session_provider_free (EventPipeSessionProvider * session_provider); + +/* +* EventPipeSessionProviderList. + */ +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSessionProviderList { +#else +struct _EventPipeSessionProviderList_Internal { +#endif + ep_rt_session_provider_list_t providers; + EventPipeSessionProvider *catch_all_provider; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSessionProviderList { + uint8_t _internal [sizeof (struct _EventPipeSessionProviderList_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeSessionProviderList *, session_provider_list, ep_rt_session_provider_list_t *, providers) +EP_DEFINE_GETTER(EventPipeSessionProviderList *, session_provider_list, EventPipeSessionProvider *, catch_all_provider) + +EventPipeSessionProviderList * +ep_session_provider_list_alloc ( + const EventPipeProviderConfiguration *configs, + uint32_t configs_len); + +void +ep_session_provider_list_free (EventPipeSessionProviderList *session_provider_list); + +void +ep_session_provider_list_clear (EventPipeSessionProviderList *session_provider_list); + +bool +ep_session_provider_list_is_empty (const EventPipeSessionProviderList *session_provider_list); + +void +ep_session_provider_list_add_session_provider ( + EventPipeSessionProviderList *session_provider_list, + EventPipeSessionProvider *session_provider); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_SESSION_PROVIDER_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-session.c b/src/mono/mono/eventpipe/ep-session.c new file mode 100644 index 0000000000000..f4e4caa67e869 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-session.c @@ -0,0 +1,255 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +session_disable_ipc_streaming_thread (EventPipeSession *session); + +static +void +session_create_ipc_streaming_thread_lock_held (EventPipeSession *session); + +/* + * EventPipeSession. + */ + +static +void +session_create_ipc_streaming_thread_lock_held (EventPipeSession *session) +{ + //TODO: Implement. +} + +static +void +session_disable_ipc_streaming_thread (EventPipeSession *session) +{ + EP_ASSERT (ep_session_get_session_type (session) == EP_SESSION_TYPE_IPCSTREAM); + EP_ASSERT (ep_session_get_ipc_streaming_enabled (session)); + + EP_ASSERT (!ep_rt_process_detach ()); + + // The IPC streaming thread will watch this value and exit + // when profiling is disabled. + ep_session_set_ipc_streaming_enabled (session, false); + + // Thread could be waiting on the event that there is new data to read. + ep_rt_wait_event_set (ep_buffer_manager_get_rt_wait_event_ref (ep_session_get_buffer_manager (session))); + + // Wait for the sampling thread to clean itself up. + ep_rt_wait_event_handle_t *rt_thread_shutdown_event = ep_session_get_rt_thread_shutdown_event_ref (session); + ep_rt_wait_event_wait (rt_thread_shutdown_event, EP_INFINITE_WAIT, false /* bAlertable */); + ep_rt_wait_event_free (rt_thread_shutdown_event); +} + +EventPipeSessionProvider * +ep_session_get_session_provider_lock_held ( + const EventPipeSession *session, + const EventPipeProvider *provider) +{ + ep_rt_config_requires_lock_held (); + + ep_return_null_if_nok (session != NULL && provider != NULL); + + EventPipeSessionProviderList *providers = ep_session_get_providers (session); + ep_return_null_if_nok (providers != NULL); + + EventPipeSessionProvider *catch_all = ep_session_provider_list_get_catch_all_provider (providers); + if (catch_all) + return catch_all; + + EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_ref (providers), ep_provider_get_provider_name (provider)); + + ep_rt_config_requires_lock_held (); + return session_provider; +} + +void +ep_session_enable_rundown_lock_held (EventPipeSession *session) +{ + ep_rt_config_requires_lock_held (); + + ep_return_void_if_nok (session != NULL); + + //TODO: This is CoreCLR specific keywords for native ETW events (ending up in event pipe). + //! The keywords below seems to correspond to: + //! LoaderKeyword (0x00000008) + //! JitKeyword (0x00000010) + //! NgenKeyword (0x00000020) + //! unused_keyword (0x00000100) + //! JittedMethodILToNativeMapKeyword (0x00020000) + //! ThreadTransferKeyword (0x80000000) + const uint64_t keywords = 0x80020138; + const uint32_t verbose_logging_level = (uint32_t)EP_EVENT_LEVEL_VERBOSE; + + EventPipeProviderConfiguration rundown_providers [2]; + uint32_t rundown_providers_len = EP_ARRAY_SIZE (rundown_providers); + + ep_provider_config_init (&rundown_providers [0], ep_config_get_public_provider_name_utf8 (), keywords, verbose_logging_level, NULL); // Public provider. + ep_provider_config_init (&rundown_providers [1], ep_config_get_rundown_provider_name_utf8 (), keywords, verbose_logging_level, NULL); // Rundown provider. + + //TODO: This is CoreCLR specific provider. + // update the provider context here since the callback doesn't happen till we actually try to do rundown. + //MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.Level = VerboseLoggingLevel; + //MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.EnabledKeywordsBitmask = Keywords; + //MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled = true; + + // Update provider list with rundown configuration. + for (uint32_t i = 0; i < rundown_providers_len; ++i) { + const EventPipeProviderConfiguration *config = &rundown_providers [i]; + + EventPipeSessionProvider *session_provider = ep_session_provider_alloc ( + ep_provider_config_get_provider_name (config), + ep_provider_config_get_keywords (config), + ep_provider_config_get_logging_level (config), + ep_provider_config_get_filter_data (config)); + + ep_session_add_session_provider (session, session_provider); + } + + ep_session_set_rundown_enabled (session, true); + + ep_rt_config_requires_lock_held (); + return; +} + +void +ep_session_execute_rundown_lock_held (EventPipeSession *session) +{ + //TODO: Implement. This is mainly runtime specific implementation + //since it will emit native trace events into the pipe (using CoreCLR's ETW support). +} + +void +ep_session_suspend_write_event_lock_held (EventPipeSession *session) +{ + //TODO: Implement. +} + +void +ep_session_write_sequence_point_unbuffered_lock_held (EventPipeSession *session) +{ + //TODO: Implement. +} + +void +ep_session_start_streaming_lock_held (EventPipeSession *session) +{ + ep_rt_config_requires_lock_held (); + + ep_return_void_if_nok (session != NULL); + + if (ep_session_get_file (session) != NULL) + ep_file_initialize_file (ep_session_get_file (session)); + + if (ep_session_get_session_type (session) == EP_SESSION_TYPE_IPCSTREAM) + session_create_ipc_streaming_thread_lock_held (session); + + ep_rt_config_requires_lock_held (); + return; +} + +bool +ep_session_is_valid (const EventPipeSession *session) +{ + return !ep_session_provider_list_is_empty (ep_session_get_providers (session)); +} + +void +ep_session_add_session_provider (EventPipeSession *session, EventPipeSessionProvider *session_provider) +{ + ep_return_void_if_nok (session != NULL); + ep_session_provider_list_add_session_provider (ep_session_get_providers (session), session_provider); +} + +void +ep_session_disable (EventPipeSession *session) +{ + ep_return_void_if_nok (session != NULL); + if (ep_session_get_session_type (session) == EP_SESSION_TYPE_IPCSTREAM && ep_session_get_ipc_streaming_enabled (session)) + session_disable_ipc_streaming_thread (session); + + bool ignored; + ep_session_write_all_buffers_to_file (session, &ignored); + ep_session_provider_list_clear (ep_session_get_providers (session)); +} + +bool +ep_session_write_all_buffers_to_file (EventPipeSession *session, bool *events_written) +{ + //TODO: Implement. + *events_written = false; + return true; +} + +EventPipeEventInstance * +ep_session_get_next_event (EventPipeSession *session) +{ + //TODO: Implement. + return NULL; +} + +EventPipeWaitHandle +ep_session_get_wait_event (EventPipeSession *session) +{ + ep_raise_error_if_nok (session != NULL); + + EventPipeBufferManager *buffer_manager = ep_session_get_buffer_manager (session); + ep_raise_error_if_nok (buffer_manager != NULL); + + return ep_rt_wait_event_get_wait_handle (ep_buffer_manager_get_rt_wait_event_ref (buffer_manager)); + +ep_on_error: + return 0; +} + +uint64_t +ep_session_get_mask (const EventPipeSession *session) +{ + return ((uint64_t)1 << ep_session_get_index (session)); +} + +bool +ep_session_get_rundown_enabled (const EventPipeSession *session) +{ + return (ep_rt_volatile_load_uint32_t(ep_session_get_rundown_enabled_cref (session)) ? true : false); +} + +void +ep_session_set_rundown_enabled ( + EventPipeSession *session, + bool enabled) +{ + ep_rt_volatile_store_uint32_t (ep_session_get_rundown_enabled_ref (session), (enabled) ? 1 : 0); +} + +bool +ep_session_get_ipc_streaming_enabled (const EventPipeSession *session) +{ + return (ep_rt_volatile_load_uint32_t(ep_session_get_ipc_streaming_enabled_cref (session)) ? true : false); +} + +void +ep_session_set_ipc_streaming_enabled ( + EventPipeSession *session, + bool enabled) +{ + ep_rt_volatile_store_uint32_t (ep_session_get_ipc_streaming_enabled_ref (session), (enabled) ? 1 : 0); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_session; +const char quiet_linker_empty_file_warning_eventpipe_session = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-session.h b/src/mono/mono/eventpipe/ep-session.h new file mode 100644 index 0000000000000..cfcf1476938be --- /dev/null +++ b/src/mono/mono/eventpipe/ep-session.h @@ -0,0 +1,130 @@ +#ifndef __EVENTPIPE_SESSION_H__ +#define __EVENTPIPE_SESSION_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeSession. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSession { +#else +struct _EventPipeSession_Internal { +#endif + uint32_t index; + EventPipeSessionProviderList *providers; + EventPipeBufferManager *buffer_manager; + volatile uint32_t rundown_enabled; + EventPipeSessionType session_type; + EventPipeSerializationFormat format; + bool rundown_requested; + uint64_t session_start_time; + uint64_t session_start_timestamp; + EventPipeFile *file; + volatile uint32_t ipc_streaming_enabled; + EventPipeThread ipc_streaming_thread; + ep_rt_wait_event_handle_t rt_thread_shutdown_event; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeSession { + uint8_t _internal [sizeof (struct _EventPipeSession_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeSession *, session, uint32_t, index) +EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeSessionProviderList *, providers) +EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeBufferManager *, buffer_manager) +EP_DEFINE_GETTER_REF(EventPipeSession *, session, volatile uint32_t *, rundown_enabled) +EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeSessionType, session_type) +EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeSerializationFormat, format) +EP_DEFINE_GETTER(EventPipeSession *, session, bool, rundown_requested) +EP_DEFINE_GETTER(EventPipeSession *, session, uint64_t, session_start_time) +EP_DEFINE_GETTER(EventPipeSession *, session, uint64_t, session_start_timestamp) +EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeFile *, file) +EP_DEFINE_GETTER_REF(EventPipeSession *, session, volatile uint32_t *, ipc_streaming_enabled) +EP_DEFINE_GETTER_REF(EventPipeSession *, session, EventPipeThread *, ipc_streaming_thread) +EP_DEFINE_GETTER_REF(EventPipeSession *, session, ep_rt_wait_event_handle_t *, rt_thread_shutdown_event) + +EventPipeSession * +ep_session_alloc ( + uint32_t index, + const ep_char8_t *output_path, + IpcStream *stream, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + bool rundown_enabled); + +void +ep_session_free (EventPipeSession *session); + +EventPipeSessionProvider * +ep_session_get_session_provider_lock_held ( + const EventPipeSession *session, + const EventPipeProvider *provider); + +void +ep_session_enable_rundown_lock_held (EventPipeSession *session); + +void +ep_session_execute_rundown_lock_held (EventPipeSession *session); + +void +ep_session_suspend_write_event_lock_held (EventPipeSession *session); + +void +ep_session_write_sequence_point_unbuffered_lock_held (EventPipeSession *session); + +void +ep_session_start_streaming_lock_held (EventPipeSession *session); + +bool +ep_session_is_valid (const EventPipeSession *session); + +void +ep_session_add_session_provider ( + EventPipeSession *session, + EventPipeSessionProvider *session_provider); + +void +ep_session_disable (EventPipeSession *session); + +bool +ep_session_write_all_buffers_to_file (EventPipeSession *session, bool *events_written); + +EventPipeEventInstance * +ep_session_get_next_event (EventPipeSession *session); + +EventPipeWaitHandle +ep_session_get_wait_event (EventPipeSession *session); + +uint64_t +ep_session_get_mask (const EventPipeSession *session); + +bool +ep_session_get_rundown_enabled (const EventPipeSession *session); + +void +ep_session_set_rundown_enabled ( + EventPipeSession *session, + bool enabled); + +bool +ep_session_get_ipc_streaming_enabled (const EventPipeSession *session); + +void +ep_session_set_ipc_streaming_enabled ( + EventPipeSession *session, + bool enabled); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_SESSION_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-stack-contents.h b/src/mono/mono/eventpipe/ep-stack-contents.h new file mode 100644 index 0000000000000..6ffe98d657004 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-stack-contents.h @@ -0,0 +1,172 @@ +#ifndef __EVENTPIPE_STACKCONTENTS_H__ +#define __EVENTPIPE_STACKCONTENTS_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeStackContents. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeStackContents { +#else +struct _EventPipeStackContents_Internal { +#endif + // Array of IP values from a stack crawl. + // Top of stack is at index 0. + uintptr_t stack_frames [EP_MAX_STACK_DEPTH]; +#ifdef EP_CHECKED_BUILD + // Parallel array of MethodDesc pointers. + // Used for debug-only stack printing. + ep_rt_method_desc_t *methods [EP_MAX_STACK_DEPTH]; +#endif + + // The next available slot in stack_frames. + uint32_t next_available_frame; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeStackContents { + uint8_t _internal [sizeof (struct _EventPipeStackContents_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_ARRAY_REF(EventPipeStackContents *, stack_contents, uintptr_t *, const uintptr_t *, stack_frames, stack_frames[0]) +#ifdef EP_CHECKED_BUILD +EP_DEFINE_GETTER_ARRAY_REF(EventPipeStackContents *, stack_contents, ep_rt_method_desc_t **, ep_rt_method_desc_t *const*, methods, methods[0]) +#endif +EP_DEFINE_GETTER(EventPipeStackContents *, stack_contents, uint32_t, next_available_frame) +EP_DEFINE_SETTER(EventPipeStackContents *, stack_contents, uint32_t, next_available_frame) + +EventPipeStackContents * +ep_stack_contents_alloc (void); + +EventPipeStackContents * +ep_stack_contents_init (EventPipeStackContents *stack_contents); + +void +ep_stack_contents_fini (EventPipeStackContents *stack_contents); + +void +ep_stack_contents_free (EventPipeStackContents *stack_contents); + +static +inline +void +ep_stack_contents_copyto ( + EventPipeStackContents *stack_contents, + EventPipeStackContents *dest) +{ + memcpy ( + ep_stack_contents_get_stack_frames_ref (dest), + ep_stack_contents_get_stack_frames_ref (stack_contents), + ep_stack_contents_get_next_available_frame (stack_contents) * sizeof (uintptr_t)); + +#ifdef EP_CHECKED_BUILD + memcpy ( + ep_stack_contents_get_methods_ref (dest), + ep_stack_contents_get_methods_ref (stack_contents), + ep_stack_contents_get_next_available_frame (stack_contents) * sizeof (ep_rt_method_desc_t *)); +#endif + + ep_stack_contents_set_next_available_frame (dest, ep_stack_contents_get_next_available_frame (stack_contents)); +} + +static +inline +void +ep_stack_contents_reset (EventPipeStackContents *stack_contents) +{ + ep_stack_contents_set_next_available_frame (stack_contents, 0); +} + +static +inline +bool +ep_stack_contents_is_empty (EventPipeStackContents *stack_contents) +{ + return (ep_stack_contents_get_next_available_frame (stack_contents) == 0); +} + +static +inline +uint32_t +ep_stack_contents_get_length (EventPipeStackContents *stack_contents) +{ + return ep_stack_contents_get_next_available_frame (stack_contents); +} + +static +inline +uintptr_t +ep_stack_contents_get_ip ( + EventPipeStackContents *stack_contents, + uint32_t frame_index) +{ + EP_ASSERT (frame_index < EP_MAX_STACK_DEPTH); + if (frame_index >= EP_MAX_STACK_DEPTH) + return 0; + + return ep_stack_contents_get_stack_frames_cref (stack_contents)[frame_index]; +} + +#ifdef EP_CHECKED_BUILD +static +inline +ep_rt_method_desc_t * +ep_stack_contents_get_method ( + EventPipeStackContents *stack_contents, + uint32_t frame_index) +{ + EP_ASSERT (frame_index < EP_MAX_STACK_DEPTH); + if (frame_index >= EP_MAX_STACK_DEPTH) + return NULL; + + return ep_stack_contents_get_methods_cref (stack_contents)[frame_index]; +} +#endif + +static +inline +void +ep_stack_contents_append ( + EventPipeStackContents *stack_contents, + uintptr_t control_pc, + ep_rt_method_desc_t *method) +{ + EP_ASSERT (stack_contents != NULL); + uint32_t next_frame = ep_stack_contents_get_next_available_frame (stack_contents); + if (next_frame < EP_MAX_STACK_DEPTH) { + ep_stack_contents_get_stack_frames_ref (stack_contents)[next_frame] = control_pc; +#ifdef EP_CHECKED_BUILD + ep_stack_contents_get_methods_ref (stack_contents)[next_frame] = method; +#endif + next_frame++; + ep_stack_contents_set_next_available_frame (stack_contents, next_frame); + } +} + +static +inline +uint8_t * +ep_stack_contents_get_pointer (const EventPipeStackContents *stack_contents) +{ + EP_ASSERT (stack_contents != NULL); + return (uint8_t *)ep_stack_contents_get_stack_frames_cref (stack_contents); +} + +static +inline +uint32_t +ep_stack_contents_get_size (const EventPipeStackContents *stack_contents) +{ + EP_ASSERT (stack_contents != NULL); + return (ep_stack_contents_get_next_available_frame (stack_contents) * sizeof (uintptr_t)); +} + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_STACKCONTENTS_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-stream-internals.c b/src/mono/mono/eventpipe/ep-stream-internals.c new file mode 100644 index 0000000000000..c62c857552aec --- /dev/null +++ b/src/mono/mono/eventpipe/ep-stream-internals.c @@ -0,0 +1,392 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +file_stream_writer_free_func (void *stream); + +static +bool +file_stream_writer_write_func ( + void *stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +static +void +file_write_end (EventPipeFile *file); + +static +void +ipc_stream_writer_free_func (void *stream); + +static +bool +ipc_stream_writer_write_func ( + void *stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +/* + * FastSerializableObject. + */ + +FastSerializableObject * +ep_fast_serializable_object_init ( + FastSerializableObject *fast_serializable_object, + FastSerializableObjectVtable *vtable, + int32_t object_version, + int32_t min_reader_version, + bool is_private) +{ + EP_ASSERT (fast_serializable_object != NULL && vtable != NULL); + + fast_serializable_object->vtable = vtable; + fast_serializable_object->object_version = object_version; + fast_serializable_object->min_reader_version = min_reader_version; + fast_serializable_object->is_private = is_private; + + return fast_serializable_object; +} + +void +ep_fast_serializable_object_fini (FastSerializableObject *fast_serializable_ojbect) +{ + ; +} + +void +ep_fast_serializable_object_free_vcall (FastSerializableObject *fast_serializable_ojbect) +{ + ep_return_void_if_nok (fast_serializable_ojbect != NULL); + + EP_ASSERT (fast_serializable_ojbect->vtable != NULL); + FastSerializableObjectVtable *vtable = fast_serializable_ojbect->vtable; + + EP_ASSERT (vtable->free_func != NULL); + vtable->free_func (fast_serializable_ojbect); +} + +void +ep_fast_serializable_object_fast_serialize_vcall ( + FastSerializableObject *fast_serializable_ojbect, + FastSerializer *fast_serializer) +{ + EP_ASSERT (fast_serializable_ojbect != NULL && fast_serializable_ojbect->vtable != NULL); + FastSerializableObjectVtable *vtable = fast_serializable_ojbect->vtable; + + EP_ASSERT (vtable->fast_serialize_func != NULL); + vtable->fast_serialize_func (fast_serializable_ojbect, fast_serializer); +} + +const ep_char8_t * +ep_fast_serializable_object_get_type_name_vcall (FastSerializableObject *fast_serializable_ojbect) +{ + EP_ASSERT (fast_serializable_ojbect != NULL && fast_serializable_ojbect->vtable != NULL); + FastSerializableObjectVtable *vtable = fast_serializable_ojbect->vtable; + + EP_ASSERT (vtable->get_type_name_func != NULL); + return vtable->get_type_name_func (fast_serializable_ojbect); +} + +/* + * FastSerializer. + */ +FastSerializer * +ep_fast_serializer_alloc (StreamWriter *stream_writer) +{ + ep_return_null_if_nok (stream_writer != NULL); + + FastSerializer *instance = ep_rt_object_alloc (FastSerializer); + ep_raise_error_if_nok (instance != NULL); + + // Ownership transfered. + instance->stream_writer = stream_writer; + instance->required_padding = 0; + instance->write_error_encountered = false; + + const ep_char8_t signature[] = "!FastSerialization.1"; // the consumer lib expects exactly the same string, it must not be changed + uint32_t signature_len = EP_ARRAY_SIZE (signature) - 1; + ep_fast_serializer_write_string (instance, signature, signature_len); + +ep_on_exit: + return instance; + +ep_on_error: + ep_fast_serializer_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_fast_serializer_free (FastSerializer *fast_serializer) +{ + ep_return_void_if_nok (fast_serializer != NULL); + + EP_ASSERT (fast_serializer->stream_writer != NULL); + ep_stream_writer_free_vcall (fast_serializer->stream_writer); + + ep_rt_object_free (fast_serializer); +} + +/* + * FileStream. + */ + +FileStream * +ep_file_stream_alloc (void) +{ + return ep_rt_object_alloc (FileStream); +} + +void +ep_file_stream_free (FileStream *file_stream) +{ + ep_return_void_if_nok (file_stream != NULL); + + ep_file_stream_close (file_stream); + ep_rt_object_free (file_stream); +} + +/* + * FileStreamWriter. + */ + +static +void +file_stream_writer_free_func (void *stream) +{ + ep_file_stream_writer_free ((FileStreamWriter *)stream); +} + +static +bool +file_stream_writer_write_func ( + void *stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + EP_ASSERT (stream != NULL); + + return ep_file_stream_writer_write ( + (FileStreamWriter *)stream, + buffer, + bytes_to_write, + bytes_written); +} + +static StreamWriterVtable file_stream_writer_vtable = { + file_stream_writer_free_func, + file_stream_writer_write_func }; + +FileStreamWriter * +ep_file_stream_writer_alloc (const ep_char8_t *output_file_path) +{ + ep_return_null_if_nok (output_file_path != NULL); + + FileStreamWriter *instance = ep_rt_object_alloc (FileStreamWriter); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_stream_writer_init ( + &instance->stream_writer, + &file_stream_writer_vtable) != NULL); + + instance->file_stream = ep_file_stream_alloc (); + ep_raise_error_if_nok (instance->file_stream != NULL); + + if (!ep_file_stream_open_write (instance->file_stream, output_file_path)) { + EP_ASSERT (!"Unable to open file for write."); + ep_raise_error (); + } + +ep_on_exit: + return instance; + +ep_on_error: + ep_file_stream_writer_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_file_stream_writer_free (FileStreamWriter *file_stream_writer) +{ + ep_return_void_if_nok (file_stream_writer != NULL); + + ep_file_stream_free (file_stream_writer->file_stream); + ep_stream_writer_fini (&file_stream_writer->stream_writer); + ep_rt_object_free (file_stream_writer); +} + +/* + * IpcStream. + */ + +IpcStream * +ep_ipc_stream_alloc (ep_rt_ipc_handle_t rt_ipc) +{ + IpcStream *instance = ep_rt_object_alloc (IpcStream); + ep_raise_error_if_nok (instance != NULL); + + //Transfer ownership. + instance->rt_ipc = rt_ipc; + +ep_on_exit: + return instance; + +ep_on_error: + ep_ipc_stream_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_ipc_stream_free (IpcStream *ipc_stream) +{ + ep_return_void_if_nok (ipc_stream != NULL); + + ep_ipc_stream_flush (ipc_stream); + ep_ipc_stream_disconnect (ipc_stream); + ep_ipc_stream_close (ipc_stream); + + ep_rt_object_free (ipc_stream); +} + +/* + * IpcStreamWriter. + */ + +static +void +ipc_stream_writer_free_func (void *stream) +{ + ep_ipc_stream_writer_free ((IpcStreamWriter *)stream); +} + +static +bool +ipc_stream_writer_write_func ( + void *stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + EP_ASSERT (stream != NULL); + + return ep_ipc_stream_writer_write ( + (IpcStreamWriter *)stream, + buffer, + bytes_to_write, + bytes_written); +} + +static StreamWriterVtable ipc_stream_writer_vtable = { + ipc_stream_writer_free_func, + ipc_stream_writer_write_func }; + +IpcStreamWriter * +ep_ipc_stream_writer_alloc ( + uint64_t id, + IpcStream *stream) +{ + IpcStreamWriter *instance = ep_rt_object_alloc (IpcStreamWriter); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_stream_writer_init ( + &instance->stream_writer, + &ipc_stream_writer_vtable) != NULL); + + //Ownership transfered. + instance->ipc_stream = stream; + +ep_on_exit: + return instance; + +ep_on_error: + ep_ipc_stream_writer_free (instance); + + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_ipc_stream_writer_free (IpcStreamWriter *ipc_stream_writer) +{ + ep_return_void_if_nok (ipc_stream_writer != NULL); + + ep_ipc_stream_free (ipc_stream_writer->ipc_stream); + ep_stream_writer_fini (&ipc_stream_writer->stream_writer); + ep_rt_object_free (ipc_stream_writer); +} + +/* + * StreamWriter. + */ + +StreamWriter * +ep_stream_writer_init ( + StreamWriter *stream_writer, + StreamWriterVtable *vtable) +{ + EP_ASSERT (stream_writer != NULL && vtable != NULL); + + stream_writer->vtable = vtable; + + return stream_writer; +} + +void +ep_stream_writer_fini (StreamWriter *stream_writer) +{ + ; +} + +void +ep_stream_writer_free_vcall (StreamWriter *stream_writer) +{ + ep_return_void_if_nok (stream_writer != NULL); + + EP_ASSERT (stream_writer->vtable != NULL); + StreamWriterVtable *vtable = stream_writer->vtable; + + EP_ASSERT (vtable->free_func != NULL); + vtable->free_func (stream_writer); +} + +bool +ep_stream_writer_write_vcall ( + StreamWriter *stream_writer, + const uint8_t *buffer, + const uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + EP_ASSERT (stream_writer != NULL && stream_writer->vtable != NULL); + StreamWriterVtable *vtable = stream_writer->vtable; + + EP_ASSERT (vtable->write_func != NULL); + return vtable->write_func (stream_writer, buffer, bytes_to_write, bytes_written); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_stream_internals; +const char quiet_linker_empty_file_warning_eventpipe_stream_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-stream.c b/src/mono/mono/eventpipe/ep-stream.c new file mode 100644 index 0000000000000..5d9ee0060aa38 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-stream.c @@ -0,0 +1,280 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * Forward declares of all static functions. + */ + +static +void +fast_serializer_write_serialization_type ( + FastSerializer *fast_serializer, + FastSerializableObject *fast_serializable_ojbect); + +/* + * FastSerializableObject. + */ + +void +ep_fast_serializable_object_fast_serialize ( + FastSerializableObject *fast_serializable_ojbect, + FastSerializer *fast_serializer) +{ + ep_fast_serializable_object_fast_serialize_vcall (fast_serializable_ojbect, fast_serializer); +} + +const ep_char8_t * +ep_fast_serializable_object_get_type_name (FastSerializableObject *fast_serializable_ojbect) +{ + return ep_fast_serializable_object_get_type_name_vcall (fast_serializable_ojbect); +} + +/* + * FastSerializer. + */ + +static +void +fast_serializer_write_serialization_type ( + FastSerializer *fast_serializer, + FastSerializableObject *fast_serializable_ojbect) +{ + ep_return_void_if_nok (fast_serializable_ojbect != NULL); + + // Write the BeginObject tag. + ep_fast_serializer_write_tag (fast_serializer, ep_fast_serializable_object_get_is_private (fast_serializable_ojbect) ? FAST_SERIALIZER_TAGS_BEGIN_PRIVATE_OBJECT : FAST_SERIALIZER_TAGS_BEGIN_OBJECT, NULL, 0); + + // Write a NullReferenceTag, which implies that the following fields belong to SerializationType. + ep_fast_serializer_write_tag (fast_serializer, FAST_SERIALIZER_TAGS_NULL_REFERENCE, NULL, 0); + + // Write the SerializationType version fields. + int32_t serialization_type [2]; + serialization_type [0] = ep_fast_serializable_object_get_object_version (fast_serializable_ojbect); + serialization_type [1] = ep_fast_serializable_object_get_min_reader_version (fast_serializable_ojbect); + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)serialization_type, sizeof (serialization_type)); + + // Write the SerializationType TypeName field. + const ep_char8_t *type_name = ep_fast_serializable_object_get_type_name_vcall (fast_serializable_ojbect); + if (type_name) + ep_fast_serializer_write_string (fast_serializer, type_name, (uint32_t)ep_rt_utf8_string_len (type_name)); + + // Write the EndObject tag. + ep_fast_serializer_write_tag (fast_serializer, FAST_SERIALIZER_TAGS_END_OBJECT, NULL, 0); +} + +void +ep_fast_serializer_write_buffer ( + FastSerializer *fast_serializer, + const uint8_t *buffer, + uint32_t buffer_len) +{ + ep_return_void_if_nok (fast_serializer != NULL && buffer != NULL && buffer_len > 0); + ep_return_void_if_nok (ep_fast_serializer_get_write_error_encountered (fast_serializer) != true && ep_fast_serializer_get_stream_writer (fast_serializer) != NULL); + + uint32_t bytes_written = 0; + bool result = ep_stream_writer_write (ep_fast_serializer_get_stream_writer (fast_serializer), buffer, buffer_len, &bytes_written); + + uint32_t required_padding = ep_fast_serializer_get_required_padding (fast_serializer); + required_padding = (FAST_SERIALIZER_ALIGNMENT_SIZE + required_padding - (bytes_written & FAST_SERIALIZER_ALIGNMENT_SIZE)) % FAST_SERIALIZER_ALIGNMENT_SIZE; + ep_fast_serializer_set_required_padding (fast_serializer, required_padding); + + // This will cause us to stop writing to the file. + // The file will still remain open until shutdown so that we don't + // have to take a lock at this level when we touch the file stream. + ep_fast_serializer_set_write_error_encountered (fast_serializer, ((buffer_len != bytes_written) || !result)); +} + +void +ep_fast_serializer_write_object ( + FastSerializer *fast_serializer, + FastSerializableObject *fast_serializable_ojbect) +{ + ep_return_void_if_nok (fast_serializer != NULL && fast_serializable_ojbect != NULL); + + ep_fast_serializer_write_tag (fast_serializer, ep_fast_serializable_object_get_is_private (fast_serializable_ojbect) ? FAST_SERIALIZER_TAGS_BEGIN_PRIVATE_OBJECT : FAST_SERIALIZER_TAGS_BEGIN_OBJECT, NULL, 0); + + fast_serializer_write_serialization_type (fast_serializer, fast_serializable_ojbect); + + // Ask the object to serialize itself using the current serializer. + ep_fast_serializable_object_fast_serialize_vcall (fast_serializable_ojbect, fast_serializer); + + ep_fast_serializer_write_tag (fast_serializer, FAST_SERIALIZER_TAGS_END_OBJECT, NULL, 0); +} + +void +ep_fast_serializer_write_string ( + FastSerializer *fast_serializer, + const ep_char8_t *contents, + uint32_t contents_len) +{ + // Write teh string length. + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)&contents_len, sizeof (contents_len)); + + //Wirte the string contents. + ep_fast_serializer_write_buffer (fast_serializer, (const uint8_t *)contents, contents_len); +} + +void +ep_fast_serializer_write_tag ( + FastSerializer *fast_serializer, + FastSerializerTags tag, + const uint8_t *payload, + uint32_t payload_len) +{ + uint8_t tag_as_byte = tag; + ep_fast_serializer_write_buffer (fast_serializer, &tag_as_byte, sizeof (tag_as_byte)); + if (payload != NULL) { + EP_ASSERT (payload_len > 0); + ep_fast_serializer_write_buffer (fast_serializer, payload, payload_len); + } +} + +/* +* FileStream. +*/ + +bool +ep_file_stream_open_write ( + FileStream *file_stream, + const ep_char8_t *path) +{ + ep_return_false_if_nok (file_stream != NULL); + + ep_rt_file_handle_t rt_file = ep_rt_file_open_write (path); + ep_raise_error_if_nok (rt_file != NULL); + + ep_file_stream_set_rt_file (file_stream, rt_file); + return true; + +ep_on_error: + return false; +} + +bool +ep_file_stream_close (FileStream *file_stream) +{ + ep_return_false_if_nok (file_stream != NULL); + return ep_rt_file_close (ep_file_stream_get_rt_file (file_stream)); +} + +bool +ep_file_stream_write ( + FileStream *file_stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + ep_return_false_if_nok (file_stream != NULL && buffer != NULL && bytes_to_write > 0 && bytes_written != NULL); + return ep_rt_file_write (ep_file_stream_get_rt_file (file_stream), buffer, bytes_to_write, bytes_written); +} + +/* + * FileStreamWriter. + */ + +bool +ep_file_stream_writer_write ( + FileStreamWriter *file_stream_writer, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + ep_return_false_if_nok (file_stream_writer != NULL && buffer != NULL && bytes_to_write > 0 && bytes_written != NULL); + + ep_raise_error_if_nok (ep_file_stream_writer_get_file_stream (file_stream_writer) != NULL); + + return ep_file_stream_write (ep_file_stream_writer_get_file_stream (file_stream_writer), buffer, bytes_to_write, bytes_written); + +ep_on_error: + *bytes_written = 0; + return false; +} + +/* +* IpcStream. +*/ + +bool +ep_ipc_stream_flush (IpcStream *ipc_stream) +{ + //TODO: Implement. + return false; +} + +bool +ep_ipc_stream_disconnect (IpcStream *ipc_stream) +{ + //TODO: Implement. + return false; +} + +bool +ep_ipc_stream_close (IpcStream *ipc_stream) +{ + //TODO: Implement. + return false; +} + +bool +ep_ipc_stream_write ( + IpcStream *ipc_stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + //TODO: Implement. + return false; +} + +/* + * IpcStreamWriter. + */ + +bool +ep_ipc_stream_writer_write ( + IpcStreamWriter *ipc_stream_writer, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + ep_return_false_if_nok (ipc_stream_writer != NULL && buffer != NULL && bytes_to_write > 0 && bytes_written != NULL); + + ep_raise_error_if_nok (ep_ipc_stream_writer_get_ipc_stream (ipc_stream_writer) != NULL); + + return ep_ipc_stream_write (ep_ipc_stream_writer_get_ipc_stream (ipc_stream_writer), buffer, bytes_to_write, bytes_written); + +ep_on_error: + *bytes_written = 0; + return false; +} + +/* + * StreamWriter. + */ + +bool +ep_stream_writer_write ( + StreamWriter *stream_writer, + const uint8_t *buffer, + const uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + return ep_stream_writer_write_vcall ( + stream_writer, + buffer, + bytes_to_write, + bytes_written); +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_stream; +const char quiet_linker_empty_file_warning_eventpipe_stream = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-stream.h b/src/mono/mono/eventpipe/ep-stream.h new file mode 100644 index 0000000000000..16d9c9e49b8e3 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-stream.h @@ -0,0 +1,364 @@ +#ifndef __EVENTPIPE_STREAM_H__ +#define __EVENTPIPE_STREAM_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +// the enumeration has a specific set of values to keep it compatible with consumer library +// it's sibling is defined in https://github.com/Microsoft/perfview/blob/10d1f92b242c98073b3817ac5ee6d98cd595d39b/src/FastSerialization/FastSerialization.cs#L2295 +typedef enum +{ + FAST_SERIALIZER_TAGS_ERROR = 0, // To improve debugabilty, 0 is an illegal tag. + FAST_SERIALIZER_TAGS_NULL_REFERENCE = 1, // Tag for a null object forwardReference. + FAST_SERIALIZER_TAGS_OBJECT_REFERENCE = 2, // Followed by StreamLabel + // 3 used to belong to ForwardReference, which got removed in V3 + FAST_SERIALIZER_TAGS_BEGIN_OBJECT = 4, // Followed by Type object, object data, tagged EndObject + FAST_SERIALIZER_TAGS_BEGIN_PRIVATE_OBJECT = 5, // Like beginObject, but not placed in interning table on deserialiation + FAST_SERIALIZER_TAGS_END_OBJECT = 6, // Placed after an object to mark its end. + // 7 used to belong to ForwardDefinition, which got removed in V3 + FAST_SERIALIZER_TAGS_BYTE = 8, + FAST_SERIALIZER_TAGS_INT16, + FAST_SERIALIZER_TAGS_INT32, + FAST_SERIALIZER_TAGS_INT64, + FAST_SERIALIZER_TAGS_SKIP_REGION, + FAST_SERIALIZER_TAGS_STRING, + FAST_SERIALIZER_TAGS_BLOB, + FAST_SERIALIZER_TAGS_LIMIT // Just past the last valid tag, used for asserts. +} FastSerializerTags; + +/* + * StreamWriter. + */ + +typedef void (*StreamWriterFreeFunc)(void *stream); +typedef bool (*StreamWriterWriteFunc)(void *stream, const uint8_t *buffer, const uint32_t bytes_to_write, uint32_t *bytes_written); + +struct _StreamWriterVtable { + StreamWriterFreeFunc free_func; + StreamWriterWriteFunc write_func; +}; + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _StreamWriter { +#else +struct _StreamWriter_Internal { +#endif + StreamWriterVtable *vtable; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _StreamWriter { + uint8_t _internal [sizeof (struct _StreamWriter_Internal)]; +}; +#endif + +StreamWriter * +ep_stream_writer_init ( + StreamWriter *stream_writer, + StreamWriterVtable *vtable); + +void +ep_stream_writer_fini (StreamWriter *stream_writer); + +bool +ep_stream_writer_write ( + StreamWriter *stream_writer, + const uint8_t *buffer, + const uint32_t bytes_to_write, + uint32_t *bytes_written); + +void +ep_stream_writer_free_vcall (StreamWriter *stream_writer); + +bool +ep_stream_writer_write_vcall ( + StreamWriter *stream_writer, + const uint8_t *buffer, + const uint32_t bytes_to_write, + uint32_t *bytes_written); + +/* + * FastSerializableObject. + */ + +typedef void (*FastSerializableObjectFreeFunc)(void *object); +typedef void (*FastSerializableObjectFastSerializeFunc)(void *object, FastSerializer *fast_serializer); +typedef const ep_char8_t * (*FastSerializableObjectGetTypeNameFunc)(void *object); + +struct _FastSerializableObjectVtable { + FastSerializableObjectFreeFunc free_func; + FastSerializableObjectFastSerializeFunc fast_serialize_func; + FastSerializableObjectGetTypeNameFunc get_type_name_func; +}; + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _FastSerializableObject { +#else +struct _FastSerializableObject_Internal { +#endif + FastSerializableObjectVtable *vtable; + int32_t object_version; + int32_t min_reader_version; + bool is_private; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _FastSerializableObject { + uint8_t _internal [sizeof (struct _FastSerializableObject_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(FastSerializableObject *, fast_serializable_object, int32_t, object_version) +EP_DEFINE_GETTER(FastSerializableObject *, fast_serializable_object, int32_t, min_reader_version) +EP_DEFINE_GETTER(FastSerializableObject *, fast_serializable_object, bool, is_private) + +FastSerializableObject * +ep_fast_serializable_object_init ( + FastSerializableObject *fast_serializable_object, + FastSerializableObjectVtable *vtable, + int32_t object_version, + int32_t min_reader_version, + bool is_private); + +void +ep_fast_serializable_object_fini (FastSerializableObject *fast_serializable_object); + +void +ep_fast_serializable_object_fast_serialize ( + FastSerializableObject *fast_serializable_ojbect, + FastSerializer *fast_serializer); + +const ep_char8_t * +ep_fast_serializable_object_get_type_name (FastSerializableObject *fast_serializable_ojbect); + +void +ep_fast_serializable_object_free_vcall (FastSerializableObject *fast_serializable_ojbect); + +const ep_char8_t * +ep_fast_serializable_object_get_type_name_vcall (FastSerializableObject *fast_serializable_ojbect); + +void +ep_fast_serializable_object_fast_serialize_vcall ( + FastSerializableObject *fast_serializable_ojbect, + FastSerializer *fast_serializer); + +/* + * FastSerializer. + */ + +#define FAST_SERIALIZER_ALIGNMENT_SIZE 4 + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _FastSerializer { +#else +struct _FastSerializer_Internal { +#endif + StreamWriter *stream_writer; + uint32_t required_padding; + bool write_error_encountered; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _FastSerializer { + uint8_t _internal [sizeof (struct _FastSerializer_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(FastSerializer *, fast_serializer, StreamWriter *, stream_writer) +EP_DEFINE_GETTER(FastSerializer *, fast_serializer, uint32_t, required_padding) +EP_DEFINE_SETTER(FastSerializer *, fast_serializer, uint32_t, required_padding) +EP_DEFINE_GETTER(FastSerializer *, fast_serializer, bool, write_error_encountered) +EP_DEFINE_SETTER(FastSerializer *, fast_serializer, bool, write_error_encountered) + +FastSerializer * +ep_fast_serializer_alloc (StreamWriter *stream_writer); + +void +ep_fast_serializer_free (FastSerializer *fast_serializer); + +void +ep_fast_serializer_write_buffer ( + FastSerializer *fast_serializer, + const uint8_t *buffer, + uint32_t buffer_len); + +void +ep_fast_serializer_write_object ( + FastSerializer *fast_serializer, + FastSerializableObject *fast_serializable_ojbect); + +void +ep_fast_serializer_write_string ( + FastSerializer *fast_serializer, + const ep_char8_t *contents, + uint32_t contents_len); + +void +ep_fast_serializer_write_tag ( + FastSerializer *fast_serializer, + FastSerializerTags tag, + const uint8_t *payload, + uint32_t payload_len); + +/* +* FileStream. +*/ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _FileStream { +#else +struct _FileStream_Internal { +#endif + ep_rt_file_handle_t rt_file; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _FileStream { + uint8_t _internal [sizeof (struct _FileStream_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(FileStream *, file_stream, ep_rt_file_handle_t, rt_file) +EP_DEFINE_SETTER(FileStream *, file_stream, ep_rt_file_handle_t, rt_file) + +FileStream * +ep_file_stream_alloc (void); + +void +ep_file_stream_free (FileStream *file_stream); + +bool +ep_file_stream_open_write ( + FileStream *file_stream, + const ep_char8_t *path); + +bool +ep_file_stream_close (FileStream *file_stream); + +bool +ep_file_stream_write ( + FileStream *file_stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +/* + * FileStreamWriter. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _FileStreamWriter { +#else +struct _FileStreamWriter_Internal { +#endif + StreamWriter stream_writer; + FileStream *file_stream; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _FileStreamWriter { + uint8_t _internal [sizeof (struct _FileStreamWriter_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(FileStreamWriter *, file_stream_writer, StreamWriter *, stream_writer) +EP_DEFINE_GETTER(FileStreamWriter *, file_stream_writer, FileStream *, file_stream) + +FileStreamWriter * +ep_file_stream_writer_alloc (const ep_char8_t *output_file_path); + +void +ep_file_stream_writer_free (FileStreamWriter *file_stream_writer); + +bool +ep_file_stream_writer_write ( + FileStreamWriter *file_stream_writer, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +/* + * IpcStream. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +//TODO: Implement. +struct _IpcStream { +#else +struct _IpcStream_Internal { +#endif + ep_rt_ipc_handle_t rt_ipc; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _IpcStream { + uint8_t _internal [sizeof (struct _IpcStream_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(IpcStream *, ipc_stream, ep_rt_ipc_handle_t, rt_ipc) + +IpcStream * +ep_ipc_stream_alloc (ep_rt_ipc_handle_t rt_ipc); + +void +ep_ipc_stream_free (IpcStream *ipc_stream); + +bool +ep_ipc_stream_flush (IpcStream *stream); + +bool +ep_ipc_stream_disconnect (IpcStream *stream); + +bool +ep_ipc_stream_close (IpcStream *stream); + +bool +ep_ipc_stream_write ( + IpcStream *stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +/* + * IpcStreamWriter. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _IpcStreamWriter { +#else +struct _IpcStreamWriter_Internal { +#endif + StreamWriter stream_writer; + IpcStream *ipc_stream; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _IpcStreamWriter { + uint8_t _internal [sizeof (struct _IpcStreamWriter_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(IpcStreamWriter *, ipc_stream_writer, StreamWriter *, stream_writer) +EP_DEFINE_GETTER(IpcStreamWriter *, ipc_stream_writer, IpcStream *, ipc_stream) + +IpcStreamWriter * +ep_ipc_stream_writer_alloc ( + uint64_t id, + IpcStream *stream); + +void +ep_ipc_stream_writer_free (IpcStreamWriter *ipc_stream_writer); + +bool +ep_ipc_stream_writer_write ( + IpcStreamWriter *ipc_stream_writer, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_STREAM_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-thread-internals.c b/src/mono/mono/eventpipe/ep-thread-internals.c new file mode 100644 index 0000000000000..da2d7ad2b624f --- /dev/null +++ b/src/mono/mono/eventpipe/ep-thread-internals.c @@ -0,0 +1,219 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#define EP_IMPL_GETTER_SETTER +#include "ep.h" + +/* + * EventPipeThread. + */ + +EventPipeThread * +ep_thread_alloc (void) +{ + EventPipeThread *instance = ep_rt_object_alloc (EventPipeThread); + ep_raise_error_if_nok (instance != NULL); + + ep_rt_spin_lock_alloc (&instance->rt_lock); + ep_raise_error_if_nok (instance->rt_lock.lock != NULL); + + instance->os_thread_id = ep_rt_current_thread_get_id (); + memset (instance->session_state, 0, sizeof (instance->session_state)); + +ep_on_exit: + return instance; + +ep_on_error: + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_thread_free (EventPipeThread *thread) +{ + ep_return_void_if_nok (thread != NULL); + + EP_ASSERT (ep_rt_volatile_load_uint32_t ((const volatile uint32_t *)&thread->ref_count) == 0); + +#ifdef EP_CHECKED_BUILD + for (uint32_t i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; ++i) { + EP_ASSERT (thread->session_state [i] == NULL); + } +#endif + + ep_rt_spin_lock_free (&thread->rt_lock); + ep_rt_object_free (thread); +} + +/* + * EventPipeThreadHolder. + */ + +EventPipeThreadHolder * +ep_thread_holder_alloc (EventPipeThread *thread) +{ + ep_return_null_if_nok (thread != NULL); + + EventPipeThreadHolder *instance = ep_rt_object_alloc (EventPipeThreadHolder); + ep_raise_error_if_nok (instance != NULL); + ep_raise_error_if_nok (ep_thread_holder_init (instance, thread) != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + instance = NULL; + ep_exit_error_handler (); +} + +EventPipeThreadHolder * +ep_thread_holder_init ( + EventPipeThreadHolder *thread_holder, + EventPipeThread *thread) +{ + ep_return_null_if_nok (thread_holder != NULL && thread != NULL); + + thread_holder->thread = thread; + ep_thread_addref (thread_holder->thread); + + return thread_holder; +} + +void +ep_thread_holder_fini (EventPipeThreadHolder *thread_holder) +{ + ep_return_void_if_nok (thread_holder != NULL && thread_holder->thread); + ep_thread_release (thread_holder->thread); +} + +void +ep_thread_holder_free (EventPipeThreadHolder *thread_holder) +{ + ep_return_void_if_nok (thread_holder != NULL); + ep_thread_holder_fini (thread_holder); + ep_rt_object_free (thread_holder); +} + +/* + * EventPipeThreadSessionState. + */ + +EventPipeThreadSessionState * +ep_thread_session_state_alloc ( + EventPipeThread *thread, + EventPipeSession *session, + EventPipeBufferManager *buffer_manager) +{ + EventPipeThreadSessionState *instance = ep_rt_object_alloc (EventPipeThreadSessionState); + ep_raise_error_if_nok (instance != NULL); + + ep_raise_error_if_nok (ep_thread_holder_init (&instance->thread_holder, thread) != NULL); + + instance->session = session; + instance->sequence_number = 1; + +#ifdef EP_CHECKED_BUILD + instance->buffer_manager = buffer_manager; +#endif + +ep_on_exit: + return instance; + +ep_on_error: + instance = NULL; + ep_exit_error_handler (); +} + +void +ep_thread_session_state_free (EventPipeThreadSessionState *thread_session_state) +{ + ep_return_void_if_nok (thread_session_state != NULL); + ep_thread_holder_fini (&thread_session_state->thread_holder); + ep_rt_object_free (thread_session_state); +} + +EventPipeThread * +ep_thread_session_state_get_thread (const EventPipeThreadSessionState *thread_session_state) +{ + EP_ASSERT (thread_session_state != NULL); + return thread_session_state->thread_holder.thread; +} + +EventPipeBuffer * +ep_thread_session_state_get_write_buffer (const EventPipeThreadSessionState *thread_session_state) +{ + EP_ASSERT (thread_session_state != NULL); + ep_thread_requires_lock_held (thread_session_state->thread_holder.thread); + + EP_ASSERT ((thread_session_state->write_buffer == NULL) || (ep_rt_volatile_load_uint32_t (&thread_session_state->write_buffer->state) == EP_BUFFER_STATE_WRITABLE)); + return thread_session_state->write_buffer; +} + +void +ep_thread_session_state_set_write_buffer ( + EventPipeThreadSessionState *thread_session_state, + EventPipeBuffer *new_buffer) +{ + EP_ASSERT (thread_session_state != NULL); + ep_thread_requires_lock_held (thread_session_state->thread_holder.thread); + + EP_ASSERT ((new_buffer == NULL) || (ep_rt_volatile_load_uint32_t (&thread_session_state->write_buffer->state) == EP_BUFFER_STATE_WRITABLE)); + EP_ASSERT ((thread_session_state->write_buffer == NULL) || (ep_rt_volatile_load_uint32_t (&thread_session_state->write_buffer->state) == EP_BUFFER_STATE_WRITABLE)); + + if (thread_session_state->write_buffer) + ep_buffer_convert_to_read_only (thread_session_state->write_buffer); + + thread_session_state->write_buffer = new_buffer; +} + +EventPipeBufferList * +ep_thread_session_state_get_buffer_list (const EventPipeThreadSessionState *thread_session_state) +{ + EP_ASSERT (thread_session_state != NULL); + ep_buffer_manager_requires_lock_held (thread_session_state->buffer_manager); + return thread_session_state->buffer_list; +} + +void +ep_thread_session_state_set_buffer_list ( + EventPipeThreadSessionState *thread_session_state, + EventPipeBufferList *new_buffer_list) +{ + EP_ASSERT (thread_session_state != NULL); + ep_buffer_manager_requires_lock_held (thread_session_state->buffer_manager); + thread_session_state->buffer_list = new_buffer_list; +} + +uint32_t +ep_thread_session_state_get_volatile_sequence_number (const EventPipeThreadSessionState *thread_session_state) +{ + EP_ASSERT (thread_session_state != NULL); + return ep_rt_volatile_load_uint32_t_without_barrier (&thread_session_state->sequence_number); +} + +uint32_t +ep_thread_session_state_get_sequence_number (const EventPipeThreadSessionState *thread_session_state) +{ + EP_ASSERT (thread_session_state != NULL); + ep_thread_requires_lock_held (thread_session_state->thread_holder.thread); + return ep_rt_volatile_load_uint32_t_without_barrier (&thread_session_state->sequence_number); +} + +void +ep_thread_session_state_increment_sequence_number (EventPipeThreadSessionState *thread_session_state) +{ + EP_ASSERT (thread_session_state != NULL); + ep_thread_requires_lock_held (thread_session_state->thread_holder.thread); + thread_session_state->sequence_number++; +} + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_thread_internals; +const char quiet_linker_empty_file_warning_eventpipe_thread_internals = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-thread.c b/src/mono/mono/eventpipe/ep-thread.c new file mode 100644 index 0000000000000..68632bea401b0 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-thread.c @@ -0,0 +1,157 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#if !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) + +#include "ep.h" + +/* + * EventPipeThread. + */ + +void +ep_thread_addref (EventPipeThread *thread) +{ + EP_ASSERT (thread != NULL); + ep_rt_atomic_inc_int32_t (ep_thread_get_ref_count_ref (thread)); +} + +void +ep_thread_release (EventPipeThread *thread) +{ + EP_ASSERT (thread != NULL); + if (ep_rt_atomic_dec_int32_t (ep_thread_get_ref_count_ref (thread)) == 0) + ep_thread_free (thread); +} + +EventPipeThread * +ep_thread_get (void) +{ + return ep_rt_thread_get (); +} + +EventPipeThread * +ep_thread_get_or_create (void) +{ + return ep_rt_thread_get_or_create (); +} + +void +ep_thread_create_activity_id ( + uint8_t *activity_id, + uint32_t activity_id_len) +{ + ep_return_void_if_nok (activity_id != NULL); + ep_rt_create_activity_id (activity_id, activity_id_len); +} + +void +ep_thread_get_activity_id ( + EventPipeThread *thread, + uint8_t *activity_id, + uint32_t activity_id_len) +{ + ep_return_void_if_nok (thread != NULL && activity_id != NULL); + EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE); + memcpy (activity_id, ep_thread_get_activity_id_cref (thread), EP_ACTIVITY_ID_SIZE); +} + +void +ep_thread_set_activity_id ( + EventPipeThread *thread, + const uint8_t *activity_id, + uint32_t activity_id_len) +{ + ep_return_void_if_nok (thread != NULL && activity_id != NULL); + EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE); + memcpy (ep_thread_get_activity_id_ref (thread), activity_id, EP_ACTIVITY_ID_SIZE); +} + +void +ep_thread_set_session_write_in_progress ( + EventPipeThread *thread, + uint32_t session_index) +{ + ep_return_void_if_nok (thread != NULL); + ep_rt_volatile_store_uint32_t (ep_thread_get_writing_event_in_progress_ref (thread), session_index); +} + +uint32_t +ep_thread_get_session_write_in_progress (const EventPipeThread *thread) +{ + ep_return_zero_if_nok (thread != NULL); + return ep_rt_volatile_load_uint32_t (ep_thread_get_writing_event_in_progress_cref (thread)); +} + +EventPipeThreadSessionState * +ep_thread_get_or_create_session_state ( + EventPipeThread *thread, + EventPipeSession *session) +{ + ep_return_null_if_nok (thread != NULL && session != NULL); + EP_ASSERT (ep_session_get_index (session) < EP_MAX_NUMBER_OF_SESSIONS); + ep_thread_requires_lock_held (thread); + + EventPipeThreadSessionState *state = ep_thread_get_session_state_ref (thread)[ep_session_get_index (session)]; + if (!state) { + state = ep_thread_session_state_alloc (thread, session, ep_session_get_buffer_manager (session)); + ep_thread_get_session_state_ref (thread)[ep_session_get_index (session)] = state; + } + + return state; +} + +EventPipeThreadSessionState * +ep_thread_get_session_state ( + const EventPipeThread *thread, + EventPipeSession *session) +{ + ep_return_null_if_nok (thread != NULL && session != NULL); + EP_ASSERT (ep_session_get_index (session) < EP_MAX_NUMBER_OF_SESSIONS); + ep_thread_requires_lock_held (thread); + + EventPipeThreadSessionState *const state = ep_thread_get_session_state_cref (thread)[ep_session_get_index (session)]; + EP_ASSERT (state != NULL); + return state; +} + +void +ep_thread_delete_session_state ( + EventPipeThread *thread, + EventPipeSession *session) +{ + ep_return_void_if_nok (thread != NULL && session != NULL); + ep_thread_requires_lock_held (thread); + + uint32_t index = ep_session_get_index (session); + EP_ASSERT (index < EP_MAX_NUMBER_OF_SESSIONS); + EventPipeThreadSessionState *state = ep_thread_get_session_state_ref (thread)[index]; + EP_ASSERT (state != NULL); + ep_thread_session_state_free (state); + ep_thread_get_session_state_ref (thread)[index] = NULL; +} + +#ifdef EP_CHECKED_BUILD +void +ep_thread_requires_lock_held (const EventPipeThread *thread) +{ + EP_ASSERT (thread != NULL); + ep_rt_spin_lock_requires_lock_held (ep_thread_get_rt_lock_cref (thread)); +} + +void +ep_thread_requires_lock_not_held (const EventPipeThread *thread) +{ + EP_ASSERT (thread != NULL); + ep_rt_spin_lock_requires_lock_not_held (ep_thread_get_rt_lock_cref (thread)); +} +#endif + +#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ +#endif /* ENABLE_PERFTRACING */ + +#ifndef EP_INCLUDE_SOURCE_FILES +extern const char quiet_linker_empty_file_warning_eventpipe_thread; +const char quiet_linker_empty_file_warning_eventpipe_thread = 0; +#endif diff --git a/src/mono/mono/eventpipe/ep-thread.h b/src/mono/mono/eventpipe/ep-thread.h new file mode 100644 index 0000000000000..23d0e5093f237 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-thread.h @@ -0,0 +1,233 @@ +#ifndef __EVENTPIPE_THREAD_H__ +#define __EVENTPIPE_THREAD_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" + +/* + * EventPipeThread. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeThread { +#else +struct _EventPipeThread_Internal { +#endif + EventPipeThreadSessionState *session_state [EP_MAX_NUMBER_OF_SESSIONS]; + uint8_t activity_id [EP_ACTIVITY_ID_SIZE]; + EventPipeSession *rundown_session; + size_t os_thread_id; + ep_rt_thread_handle_t rt_thread; + ep_rt_spin_lock_handle_t rt_lock; + int32_t ref_count; + volatile uint32_t writing_event_in_progress; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeThread { + uint8_t _internal [sizeof (struct _EventPipeThread_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_ARRAY_REF(EventPipeThread *, thread, EventPipeThreadSessionState **, EventPipeThreadSessionState *const*, session_state, session_state[0]); +EP_DEFINE_GETTER_ARRAY_REF(EventPipeThread *, thread, uint8_t *, const uint8_t *, activity_id, activity_id[0]); +EP_DEFINE_GETTER(EventPipeThread *, thread, EventPipeSession *, rundown_session); +EP_DEFINE_SETTER(EventPipeThread *, thread, EventPipeSession *, rundown_session); +EP_DEFINE_GETTER(EventPipeThread *, thread, size_t, os_thread_id); +EP_DEFINE_GETTER_REF(EventPipeThread *, thread, ep_rt_spin_lock_handle_t *, rt_lock); +EP_DEFINE_GETTER_REF(EventPipeThread *, thread, int32_t *, ref_count); +EP_DEFINE_GETTER_REF(EventPipeThread *, thread, volatile uint32_t *, writing_event_in_progress); + +EventPipeThread * +ep_thread_alloc (void); + +void +ep_thread_free (EventPipeThread *thread); + +void +ep_thread_addref (EventPipeThread *thread); + +void +ep_thread_release (EventPipeThread *thread); + +EventPipeThread * +ep_thread_get (void); + +EventPipeThread * +ep_thread_get_or_create (void); + +void +ep_thread_create_activity_id ( + uint8_t *activity_id, + uint32_t activity_id_len); + +void +ep_thread_get_activity_id ( + EventPipeThread *thread, + uint8_t *activity_id, + uint32_t activity_id_len); + +void +ep_thread_set_activity_id ( + EventPipeThread *thread, + const uint8_t *activity_id, + uint32_t activity_id_len); + +static +inline +void +ep_thread_set_as_rundown_thread ( + EventPipeThread *thread, + EventPipeSession *session) +{ + EP_ASSERT (thread != NULL); + ep_thread_set_rundown_session (thread, session); +} + +static +inline +bool +ep_thread_is_rundown_thread (const EventPipeThread *thread) +{ + EP_ASSERT (thread != NULL); + return (ep_thread_get_rundown_session (thread) != NULL); +} + +#ifdef EP_CHECKED_BUILD +void +ep_thread_requires_lock_held (const EventPipeThread *thread); + +void +ep_thread_requires_lock_not_held (const EventPipeThread *thread); +#else +#define ep_thread_requires_lock_held(x) +#define ep_thread_requires_lock_not_held(x) +#endif + +void +ep_thread_set_session_write_in_progress ( + EventPipeThread *thread, + uint32_t session_index); + +uint32_t +ep_thread_get_session_write_in_progress (const EventPipeThread *thread); + +EventPipeThreadSessionState * +ep_thread_get_or_create_session_state ( + EventPipeThread *thread, + EventPipeSession *session); + +EventPipeThreadSessionState * +ep_thread_get_session_state ( + const EventPipeThread *thread, + EventPipeSession *session); + +void +ep_thread_delete_session_state ( + EventPipeThread *thread, + EventPipeSession *session); + +/* + * EventPipeThreadHolder. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeThreadHolder { +#else +struct _EventPipeThreadHolder_Internal { +#endif + EventPipeThread *thread; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeThreadHolder { + uint8_t _internal [sizeof (struct _EventPipeThreadHolder_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeThreadHolder *, thread_holder, EventPipeThread *, thread) + +EventPipeThreadHolder * +ep_thread_holder_alloc (EventPipeThread *thread); + +EventPipeThreadHolder * +ep_thread_holder_init ( + EventPipeThreadHolder *thread_holder, + EventPipeThread *thread); + +void +ep_thread_holder_fini (EventPipeThreadHolder *thread_holder); + +void +ep_thread_holder_free (EventPipeThreadHolder *thread_holder); + +/* + * EventPipeThreadSessionState. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeThreadSessionState { +#else +struct _EventPipeThreadSessionState_Internal { +#endif + EventPipeThreadHolder thread_holder; + EventPipeSession *session; + EventPipeBuffer *write_buffer; + EventPipeBufferList *buffer_list; +#ifdef EP_CHECKED_BUILD + EventPipeBufferManager *buffer_manager; +#endif + volatile uint32_t sequence_number; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeThreadSessionState { + uint8_t _internal [sizeof (struct _EventPipeThreadSessionState_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeThreadSessionState *, thread_session_state, EventPipeThreadHolder *, thread_holder) +EP_DEFINE_GETTER(EventPipeThreadSessionState *, thread_session_state, EventPipeSession *, session) + +EventPipeThreadSessionState * +ep_thread_session_state_alloc ( + EventPipeThread *thread, + EventPipeSession *session, + EventPipeBufferManager *buffer_manager); + +void +ep_thread_session_state_free (EventPipeThreadSessionState *thread_session_state); + +EventPipeThread * +ep_thread_session_state_get_thread (const EventPipeThreadSessionState *thread_session_state); + +EventPipeBuffer * +ep_thread_session_state_get_write_buffer (const EventPipeThreadSessionState *thread_session_state); + +void +ep_thread_session_state_set_write_buffer ( + EventPipeThreadSessionState *thread_session_state, + EventPipeBuffer *new_buffer); + +EventPipeBufferList * +ep_thread_session_state_get_buffer_list (const EventPipeThreadSessionState *thread_session_state); + +void +ep_thread_session_state_set_buffer_list ( + EventPipeThreadSessionState *thread_session_state, + EventPipeBufferList *new_buffer_list); + +uint32_t +ep_thread_session_state_get_volatile_sequence_number (const EventPipeThreadSessionState *thread_session_state); + +uint32_t +ep_thread_session_state_get_sequence_number (const EventPipeThreadSessionState *thread_session_state); + +void +ep_thread_session_state_increment_sequence_number (EventPipeThreadSessionState *thread_session_state); + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_THREAD_H__ **/ diff --git a/src/mono/mono/eventpipe/ep-types.h b/src/mono/mono/eventpipe/ep-types.h new file mode 100644 index 0000000000000..7e25f32016c96 --- /dev/null +++ b/src/mono/mono/eventpipe/ep-types.h @@ -0,0 +1,388 @@ +#ifndef __EVENTPIPE_TYPES_H__ +#define __EVENTPIPE_TYPES_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include +#include +#include "ep-rt-types.h" + +/* + * EventPipe Structs. + */ + +typedef struct _EventData EventData; +typedef struct _EventFilterDescriptor EventFilterDescriptor; +typedef struct _EventPipeBuffer EventPipeBuffer; +typedef struct _EventPipeBufferList EventPipeBufferList; +typedef struct _EventPipeBufferManager EventPipeBufferManager; +typedef struct _EventPipeBlock EventPipeBlock; +typedef struct _EventPipeBlockVtable EventPipeBlockVtable; +typedef struct _EventPipeConfiguration EventPipeConfiguration; +typedef struct _EventPipeEvent EventPipeEvent; +typedef struct _EventPipeEventBlockBase EventPipeEventBlockBase; +typedef struct _EventPipeEventBlock EventPipeEventBlock; +typedef struct _EventPipeEventHeader EventPipeEventHeader; +typedef struct _EventPipeEventInstance EventPipeEventInstance; +typedef struct _EventPipeEventMetadataEvent EventPipeEventMetadataEvent; +typedef struct _EventPipeEventSource EventPipeEventSource; +typedef struct _EventPipeFile EventPipeFile; +typedef struct _EventPipeMetadataBlock EventPipeMetadataBlock; +typedef struct _EventPipeParameterDesc EventPipeParameterDesc; +typedef struct _EventPipeProvider EventPipeProvider; +typedef struct _EventPipeProviderCallbackData EventPipeProviderCallbackData; +typedef struct _EventPipeProviderCallbackDataQueue EventPipeProviderCallbackDataQueue; +typedef struct _EventPipeProviderConfiguration EventPipeProviderConfiguration; +typedef struct _EventPipeSession EventPipeSession; +typedef struct _EventPipeSessionProvider EventPipeSessionProvider; +typedef struct _EventPipeSessionProviderList EventPipeSessionProviderList; +typedef struct _EventPipeSequencePoint EventPipeSequencePoint; +typedef struct _EventPipeSequencePointBlock EventPipeSequencePointBlock; +typedef struct _EventPipeStackBlock EventPipeStackBlock; +typedef struct _EventPipeStackContents EventPipeStackContents; +typedef struct _EventPipeThread EventPipeThread; +typedef struct _EventPipeThreadHolder EventPipeThreadHolder; +typedef struct _EventPipeThreadSessionState EventPipeThreadSessionState; +typedef struct _FastSerializableObject FastSerializableObject; +typedef struct _FastSerializableObjectVtable FastSerializableObjectVtable; +typedef struct _FastSerializer FastSerializer; +typedef struct _FileStream FileStream; +typedef struct _FileStreamWriter FileStreamWriter; +typedef struct _IpcStream IpcStream; +typedef struct _IpcStreamWriter IpcStreamWriter; +typedef struct _StackHashEntry StackHashEntry; +typedef struct _StackHashKey StackHashKey; +typedef struct _StreamWriter StreamWriter; +typedef struct _StreamWriterVtable StreamWriterVtable; + +#ifdef EP_INLINE_GETTER_SETTER +#ifndef EP_DEFINE_GETTER +#define EP_DEFINE_GETTER(instance_type, instance_type_name, return_type, instance_field_name) \ + static inline return_type ep_ ## instance_type_name ## _get_ ## instance_field_name (const instance_type instance) { return instance-> instance_field_name; } \ + static inline size_t ep_ ## instance_type_name ## _sizeof_ ## instance_field_name (const instance_type instance) { return sizeof (instance-> instance_field_name); } +#endif + +#ifndef EP_DEFINE_GETTER_REF +#define EP_DEFINE_GETTER_REF(instance_type, instance_type_name, return_type, instance_field_name) \ + static inline return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _ref (instance_type instance) { return &(instance-> instance_field_name); } \ + static inline const return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _cref (const instance_type instance) { return &(instance-> instance_field_name); } +#endif + +#ifndef EP_DEFINE_GETTER_ARRAY_REF +#define EP_DEFINE_GETTER_ARRAY_REF(instance_type, instance_type_name, return_type, const_return_type, instance_field_name, instance_field) \ + static inline return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _ref (instance_type instance) { return &(instance-> instance_field); } \ + static inline const_return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _cref (const instance_type instance) { return &(instance-> instance_field); } +#endif + +#ifndef EP_DEFINE_SETTER +#define EP_DEFINE_SETTER(instance_type, instance_type_name, instance_field_type, instance_field_name) static inline void ep_ ## instance_type_name ## _set_ ## instance_field_name (instance_type instance, instance_field_type instance_field_name) { instance-> instance_field_name = instance_field_name; } +#endif +#else +#ifndef EP_DEFINE_GETTER +#define EP_DEFINE_GETTER(instance_type, instance_type_name, return_type, instance_field_name) \ + return_type ep_ ## instance_type_name ## _get_ ## instance_field_name (const instance_type instance); \ + size_t ep_ ## instance_type_name ## _sizeof_ ## instance_field_name (const instance_type instance); +#endif + +#ifndef EP_DEFINE_GETTER_REF +#define EP_DEFINE_GETTER_REF(instance_type, instance_type_name, return_type, instance_field_name) \ + return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _ref (instance_type instance); \ + const return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _cref (const instance_type instance); +#endif + +#ifndef EP_DEFINE_GETTER_ARRAY_REF +#define EP_DEFINE_GETTER_ARRAY_REF(instance_type, instance_type_name, return_type, const_return_type, instance_field_name, instance_field) \ + return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _ref (instance_type instance); \ + const_return_type ep_ ## instance_type_name ## _get_ ## instance_field_name ## _cref (const instance_type instance); +#endif + +#ifndef EP_DEFINE_SETTER +#define EP_DEFINE_SETTER(instance_type, instance_type_name, instance_field_type, instance_field_name) \ + void ep_ ## instance_type_name ## _set_ ## instance_field_name (instance_type instance, instance_field_type instance_field_name); +#endif +#endif + +#define EP_MAX_NUMBER_OF_SESSIONS 64 + +#define EP_ACTIVITY_ID_SIZE 16 + +#define EP_MAX_STACK_DEPTH 100 + +/* + * EventPipe Enums. + */ + +typedef enum { + EP_BUFFER_STATE_WRITABLE = 0, + EP_BUFFER_STATE_READ_ONLY = 1 +} EventPipeBufferState; + +typedef enum { + EP_EVENT_LEVEL_LOG_ALWAYS, + EP_EVENT_LEVEL_CRITICAL, + EP_EVENT_LEVEL_ERROR, + EP_EVENT_LEVEL_WARNING, + EP_EVENT_LEVEL_INFORMATIONAL, + EP_EVENT_LEVEL_VERBOSE +} EventPipeEventLevel; + +typedef enum { + EP_FILE_FLUSH_FLAGS_EVENT_BLOCK = 1, + EP_FILE_FLUSH_FLAGS_METADATA_BLOCK = 2, + EP_FILE_FLUSH_FLAGS_STACK_BLOCK = 4, + EP_FILE_FLUSH_FLAGS_ALL_BLOCKS = EP_FILE_FLUSH_FLAGS_EVENT_BLOCK | EP_FILE_FLUSH_FLAGS_METADATA_BLOCK | EP_FILE_FLUSH_FLAGS_STACK_BLOCK +} EventPipeFileFlushFlags; + +// Represents the type of an event parameter. +// This enum is derived from the managed TypeCode type, though +// not all of these values are available in TypeCode. +// For example, Guid does not exist in TypeCode. +// Keep this in sync with COR_PRF_EVENTPIPE_PARAM_TYPE defined in +// corprof.idl +typedef enum { + EP_PARAMETER_TYPE_EMPTY = 0, // Null reference + EP_PARAMETER_TYPE_OBJECT = 1, // Instance that isn't a value + EP_PARAMETER_TYPE_DB_NULL = 2, // Database null value + EP_PARAMETER_TYPE_BOOLEAN = 3, // Boolean + EP_PARAMETER_TYPE_CHAR = 4, // Unicode character + EP_PARAMETER_TYPE_SBYTE = 5, // Signed 8-bit integer + EP_PARAMETER_TYPE_BYTE = 6, // Unsigned 8-bit integer + EP_PARAMETER_TYPE_INT16 = 7, // Signed 16-bit integer + EP_PARAMETER_TYPE_UINT16 = 8, // Unsigned 16-bit integer + EP_PARAMETER_TYPE_INT32 = 9, // Signed 32-bit integer + EP_PARAMETER_TYPE_UINT32 = 10, // Unsigned 32-bit integer + EP_PARAMETER_TYPE_INT64 = 11, // Signed 64-bit integer + EP_PARAMETER_TYPE_UINT64 = 12, // Unsigned 64-bit integer + EP_PARAMETER_TYPE_SINGLE = 13, // IEEE 32-bit float + EP_PARAMETER_TYPE_DOUBLE = 14, // IEEE 64-bit double + EP_PARAMETER_TYPE_DECIMAL = 15, // Decimal + EP_PARAMETER_TYPE_DATE_TIME = 16, // DateTime + EP_PARAMETER_TYPE_GUID = 17, // Guid + EP_PARAMETER_TYPE_STRING = 18 // Unicode character string +} EventPipeParameterType; + +typedef enum { + EP_SERIALIZATION_FORMAT_NETPERF_V3, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + EP_SERIALIZATION_FORMAT_COUNT +} EventPipeSerializationFormat; + +typedef enum { + EP_SESSION_TYPE_FILE, + EP_SESSION_TYPE_LISTENER, + EP_SESSION_TYPE_IPCSTREAM +} EventPipeSessionType ; + +typedef enum { + EP_STATE_NOT_INITIALIZED, + EP_STATE_INITIALIZED, + EP_STATE_SHUTTING_DOWN +} EventPipeState; + +/* + * EventPipe Basic Types. + */ + +typedef intptr_t EventPipeWaitHandle; +typedef uint64_t EventPipeSessionID; +typedef char ep_char8_t; +typedef unsigned short ep_char16_t; + +/* + * EventPipe Callbacks. + */ + +// Define the event pipe callback to match the ETW callback signature. +typedef void (*EventPipeCallback)( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_context); + +/* + * EventFilterDescriptor. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventFilterDescriptor { +#else +struct _EventFilterDescriptor_Internal { +#endif + uint64_t ptr; + uint32_t size; + uint32_t type; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventFilterDescriptor { + uint8_t _internal [sizeof (struct _EventFilterDescriptor_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventFilterDescriptor *, event_filter_desc, uint64_t, ptr) +EP_DEFINE_GETTER(EventFilterDescriptor *, event_filter_desc, uint32_t, size) +EP_DEFINE_GETTER(EventFilterDescriptor *, event_filter_desc, uint32_t, type) + +EventFilterDescriptor * +ep_event_filter_desc_alloc ( + uint64_t ptr, + uint32_t size, + uint32_t type); + +EventFilterDescriptor * +ep_event_filter_desc_init ( + EventFilterDescriptor *event_filter_desc, + uint64_t ptr, + uint32_t size, + uint32_t type +); + +void +ep_event_filter_desc_fini (EventFilterDescriptor * filter_desc); + +void +ep_event_filter_desc_free (EventFilterDescriptor * filter_desc); + +/* + * EventPipeProviderCallbackData. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProviderCallbackData { +#else +struct _EventPipeProviderCallbackData_Internal { +#endif + const ep_char8_t *filter_data; + EventPipeCallback callback_function; + void *callback_data; + int64_t keywords; + EventPipeEventLevel provider_level; + bool enabled; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProviderCallbackData { + uint8_t _internal [sizeof (struct _EventPipeProviderCallbackData_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeProviderCallbackData *, provider_callback_data, const ep_char8_t *, filter_data) +EP_DEFINE_GETTER(EventPipeProviderCallbackData *, provider_callback_data, EventPipeCallback, callback_function) +EP_DEFINE_GETTER(EventPipeProviderCallbackData *, provider_callback_data, void *, callback_data) +EP_DEFINE_GETTER(EventPipeProviderCallbackData *, provider_callback_data, int64_t, keywords) +EP_DEFINE_GETTER(EventPipeProviderCallbackData *, provider_callback_data, EventPipeEventLevel, provider_level) +EP_DEFINE_GETTER(EventPipeProviderCallbackData *, provider_callback_data, bool, enabled) + +EventPipeProviderCallbackData * +ep_provider_callback_data_alloc ( + const ep_char8_t *filter_data, + EventPipeCallback callback_function, + void *callback_data, + int64_t keywords, + EventPipeEventLevel provider_level, + bool enabled); + +EventPipeProviderCallbackData * +ep_provider_callback_data_alloc_copy (EventPipeProviderCallbackData *provider_callback_data_src); + +EventPipeProviderCallbackData * +ep_provider_callback_data_init ( + EventPipeProviderCallbackData *provider_callback_data, + const ep_char8_t *filter_data, + EventPipeCallback callback_function, + void *callback_data, + int64_t keywords, + EventPipeEventLevel provider_level, + bool enabled); + +EventPipeProviderCallbackData * +ep_provider_callback_data_init_copy ( + EventPipeProviderCallbackData *provider_callback_data_dst, + EventPipeProviderCallbackData *provider_callback_data_src); + +void +ep_provider_callback_data_fini (EventPipeProviderCallbackData *provider_callback_data); + +void +ep_provider_callback_data_free (EventPipeProviderCallbackData *provider_callback_data); + +/* + * EventPipeProviderCallbackDataQueue. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProviderCallbackDataQueue { +#else +struct _EventPipeProviderCallbackDataQueue_Internal { +#endif + ep_rt_provider_callback_data_queue_t queue; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProviderCallbackDataQueue { + uint8_t _internal [sizeof (struct _EventPipeProviderCallbackDataQueue_Internal)]; +}; +#endif + +EP_DEFINE_GETTER_REF(EventPipeProviderCallbackDataQueue *, provider_callback_data_queue, ep_rt_provider_callback_data_queue_t *, queue) + +EventPipeProviderCallbackDataQueue * +ep_provider_callback_data_queue_init (EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +void +ep_provider_callback_data_queue_fini (EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +void +ep_provider_callback_data_queue_enqueue ( + EventPipeProviderCallbackDataQueue *provider_callback_data_queue, + EventPipeProviderCallbackData *provider_callback_data); + +bool +ep_provider_callback_data_queue_try_dequeue ( + EventPipeProviderCallbackDataQueue *provider_callback_data_queue, + EventPipeProviderCallbackData *provider_callback_data); + +/* + * EventPipeProviderConfiguration. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProviderConfiguration { +#else +struct _EventPipeProviderConfiguration_Internal { +#endif + const ep_char8_t *provider_name; + uint64_t keywords; + EventPipeEventLevel logging_level; + const ep_char8_t *filter_data; +}; + + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_GETTER_SETTER) +struct _EventPipeProviderConfiguration { + uint8_t _internal [sizeof (struct _EventPipeProviderConfiguration_Internal)]; +}; +#endif + +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const ep_char8_t *, provider_name) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, uint64_t, keywords) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeEventLevel, logging_level) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const ep_char8_t *, filter_data) + +EventPipeProviderConfiguration * +ep_provider_config_init ( + EventPipeProviderConfiguration *provider_config, + const ep_char8_t *provider_name, + uint64_t keywords, + uint32_t logging_level, + const ep_char8_t *filter_data); + +void +ep_provider_config_fini (EventPipeProviderConfiguration *provider_config); + +#endif /* ENABLE_PERFTRACING */ +#endif /* __EVENTPIPE_TYPES_H__ */ diff --git a/src/mono/mono/eventpipe/ep.c b/src/mono/mono/eventpipe/ep.c new file mode 100644 index 0000000000000..3725a8281eb8f --- /dev/null +++ b/src/mono/mono/eventpipe/ep.c @@ -0,0 +1,711 @@ +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep.h" + +// Option to include all internal source files into ep.c. +#ifdef EP_INCLUDE_SOURCE_FILES +#define EP_FORCE_INCLUDE_SOURCE_FILES +#include "ep-block.c" +#include "ep-buffer-manager.c" +#include "ep-config.c" +#include "ep-event-instance.c" +#include "ep-event-source.c" +#include "ep-file.c" +#include "ep-metadata-generator.c" +#include "ep-provider.c" +#include "ep-session.c" +#include "ep-session-provider.c" +#include "ep-stream.c" +#include "ep-thread.c" +#endif + +/* + * Forward declares of all static functions. + */ + +static +bool +enabled_lock_held (void); + +static +uint32_t +generate_session_index_lock_held (void); + +static +bool +is_session_id_in_collection_lock_held (EventPipeSessionID id); + +static +EventPipeSessionID +enable_lock_held ( + const ep_char8_t *output_path, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + IpcStream *stream, + bool enable_sample_profiler, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +static +void +log_process_info_event (EventPipeEventSource *event_source); + +static +void +disable_lock_held ( + EventPipeSessionID id, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +static +void +disable ( + EventPipeSessionID id, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); + +/* + * Global volatile varaibles, only to be accessed through inlined volatile access functions. + */ + +volatile EventPipeState _ep_state = EP_STATE_NOT_INITIALIZED; + +volatile uint32_t _ep_number_of_sessions = 0; + +volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS] = { 0 }; + +volatile uint64_t _ep_allow_write = 0; + +/* + * EventPipe. + */ + +static +bool +enabled_lock_held (void) +{ + ep_rt_config_requires_lock_held (); + return (ep_volatile_load_eventpipe_state_without_barrier () >= EP_STATE_INITIALIZED && + ep_volatile_load_number_of_sessions_without_barrier () > 0); +} + +static +uint32_t +generate_session_index_lock_held (void) +{ + ep_rt_config_requires_lock_held (); + + for (uint32_t i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; ++i) + if (ep_volatile_load_session_without_barrier (i) == NULL) + return i; + return EP_MAX_NUMBER_OF_SESSIONS; +} + +static +bool +is_session_id_in_collection_lock_held (EventPipeSessionID session_id) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (session_id != 0); + + const EventPipeSession *const session = (EventPipeSession *)session_id; + for (uint32_t i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; ++i) { + if (ep_volatile_load_session (i) == session) { + EP_ASSERT (i == ep_session_get_index (session)); + return true; + } + } + + return false; +} + +static +EventPipeSessionID +enable_lock_held ( + const ep_char8_t *output_path, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + IpcStream *stream, + bool enable_sample_profiler, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT); + EP_ASSERT (circular_buffer_size_in_mb > 0); + EP_ASSERT (providers_len > 0 && providers != NULL); + EP_ASSERT ((session_type == EP_SESSION_TYPE_FILE && output_path != NULL) ||(session_type == EP_SESSION_TYPE_IPCSTREAM && stream != NULL)); + + EventPipeSession *session = NULL; + EventPipeSessionID session_id = 0; + + ep_raise_error_if_nok (ep_volatile_load_eventpipe_state () == EP_STATE_INITIALIZED); + + const uint32_t session_index = generate_session_index_lock_held (); + ep_raise_error_if_nok (session_index < EP_MAX_NUMBER_OF_SESSIONS); + + session = ep_session_alloc ( + session_index, + output_path, + stream, + session_type, + format, + rundown_requested, + circular_buffer_size_in_mb, + providers, + providers_len, + FALSE); + + ep_raise_error_if_nok (session != NULL && ep_session_is_valid (session) == true); + + session_id = (EventPipeSessionID)session; + + // Return if the index is invalid. + if (ep_session_get_index (session) >= EP_MAX_NUMBER_OF_SESSIONS) { + EP_ASSERT (!"Session index was out of range."); + ep_raise_error (); + } + + if (ep_volatile_load_number_of_sessions () >= EP_MAX_NUMBER_OF_SESSIONS) { + EP_ASSERT (!"max number of sessions reached."); + ep_raise_error (); + } + + // Register the SampleProfiler the very first time (if supported). + ep_rt_sample_profiler_init (provider_callback_data_queue); + + // Enable the EventPipe EventSource. + ep_event_source_enable (ep_event_source_get (), session); + + // Save the session. + if (ep_volatile_load_session_without_barrier (ep_session_get_index (session)) != NULL) { + EP_ASSERT (!"Attempting to override an existing session."); + ep_raise_error (); + } + + ep_volatile_store_session (ep_session_get_index (session), session); + + ep_volatile_store_allow_write (ep_volatile_load_allow_write () | ep_session_get_mask (session)); + ep_volatile_store_number_of_sessions (ep_volatile_load_number_of_sessions () + 1); + + // Enable tracing. + ep_config_enable_disable_lock_held (ep_config_get (), session, provider_callback_data_queue, true); + + session = NULL; + + // Enable the sample profiler (if supported). + if (enable_sample_profiler) + ep_rt_sample_profiler_enable (); + +ep_on_exit: + ep_rt_config_requires_lock_held (); + return session_id; + +ep_on_error: + ep_session_free (session); + + session_id = 0; + ep_exit_error_handler (); +} + +static +void +log_process_info_event (EventPipeEventSource *event_source) +{ + // Get the managed command line. + const ep_char8_t *cmd_line = ep_rt_managed_command_line_get (); + + if (cmd_line == NULL) + cmd_line = ep_rt_command_line_get (); + + // Log the process information event. + ep_char16_t *cmd_line_utf16 = ep_rt_utf8_to_utf16_string (cmd_line, -1); + if (cmd_line_utf16 != NULL) { + ep_event_source_send_process_info (event_source, cmd_line_utf16); + ep_rt_utf16_string_free (cmd_line_utf16); + } +} + +static +void +disable_lock_held ( + EventPipeSessionID id, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_held (); + EP_ASSERT (id != 0); + EP_ASSERT (ep_volatile_load_number_of_sessions () > 0); + + if (is_session_id_in_collection_lock_held (id)) { + EventPipeSession *const session = (EventPipeSession *)id; + + // Disable the profiler. + ep_rt_sample_profiler_disable (); + + // Log the process information event. + log_process_info_event (ep_event_source_get ()); + + // Disable session tracing. + ep_config_enable_disable_lock_held (ep_config_get (), session, provider_callback_data_queue, false); + + ep_session_disable (session); // WriteAllBuffersToFile, and remove providers. + + // Do rundown before fully stopping the session unless rundown wasn't requested + if (ep_session_get_rundown_requested (session)) { + ep_session_enable_rundown_lock_held (session); // Set Rundown provider. + EventPipeThread *const thread = ep_thread_get (); + if (thread != NULL) { + ep_thread_set_as_rundown_thread (thread, session); + { + ep_config_enable_disable_lock_held (ep_config_get (), session, provider_callback_data_queue, true); + { + ep_session_execute_rundown_lock_held (session); + } + ep_config_enable_disable_lock_held (ep_config_get (), session, provider_callback_data_queue, false); + } + ep_thread_set_as_rundown_thread (thread, NULL); + } else { + EP_ASSERT (!"Failed to get or create the EventPipeThread for rundown events."); + } + } + + ep_volatile_store_allow_write (ep_volatile_load_allow_write () & ~(ep_session_get_mask (session))); + ep_session_suspend_write_event_lock_held (session); + + bool ignored; + ep_session_write_all_buffers_to_file (session, &ignored); // Flush the buffers to the stream/file + + ep_volatile_store_number_of_sessions (ep_volatile_load_number_of_sessions () - 1); + + // At this point, we should not be writing events to this session anymore + // This is a good time to remove the session from the array. + EP_ASSERT (ep_volatile_load_session (ep_session_get_index (session)) == session); + + // Remove the session from the array, and mask. + ep_volatile_store_session (ep_session_get_index (session), NULL); + + // Write a final sequence point to the file now that all events have + // been emitted. + ep_session_write_sequence_point_unbuffered_lock_held (session); + + ep_session_free (session); + + // Providers can't be deleted during tracing because they may be needed when serializing the file. + ep_config_delete_deferred_providers_lock_held (ep_config_get ()); + } + + ep_rt_config_requires_lock_held (); + return; +} + +static +void +disable ( + EventPipeSessionID id, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) +{ + ep_rt_config_requires_lock_not_held (); + + EP_CONFIG_LOCK_ENTER + disable_lock_held (id, provider_callback_data_queue); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +EventPipeSessionID +ep_enable ( + const ep_char8_t *output_path, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + IpcStream *stream, + bool enable_sample_profiler) +{ + ep_rt_config_requires_lock_not_held (); + EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT); + EP_ASSERT (circular_buffer_size_in_mb > 0); + EP_ASSERT (providers_len > 0 && providers != NULL); + + // If the state or arguments are invalid, bail here. + if (session_type == EP_SESSION_TYPE_FILE && output_path == NULL) + return 0; + if (session_type == EP_SESSION_TYPE_IPCSTREAM && stream == NULL) + return 0; + + EventPipeSessionID session_id = 0; + EventPipeProviderCallbackDataQueue callback_data_queue; + EventPipeProviderCallbackData provider_callback_data; + EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); + + EP_CONFIG_LOCK_ENTER + session_id = enable_lock_held ( + output_path, + circular_buffer_size_in_mb, + providers, + providers_len, + session_type, + format, + rundown_requested, + stream, + enable_sample_profiler, + provider_callback_data_queue); + EP_CONFIG_LOCK_EXIT + + while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) + ep_provider_invoke_callback (&provider_callback_data); + +ep_on_exit: + ep_provider_callback_data_queue_fini (provider_callback_data_queue); + ep_rt_config_requires_lock_not_held (); + return session_id; + +ep_on_error: + session_id = 0; + ep_exit_error_handler (); +} + +void +ep_disable (EventPipeSessionID id) +{ + ep_rt_config_requires_lock_not_held (); + + //TODO: Why is this needed? Just to make sure thread is attached to runtime for + //EP_GCX_PREEMP_ENTER/EP_GCX_PREEMP_EXIT to work? + ep_rt_thread_setup (); + + if (id == 0) + return; + + // Don't block GC during clean-up. + EP_GCX_PREEMP_ENTER + + EventPipeProviderCallbackDataQueue callback_data_queue; + EventPipeProviderCallbackData provider_callback_data; + EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); + + disable (id, provider_callback_data_queue); + + while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) + ep_provider_invoke_callback (&provider_callback_data); + + ep_provider_callback_data_queue_fini (provider_callback_data_queue); + + EP_GCX_PREEMP_EXIT + + ep_rt_config_requires_lock_not_held (); + return; +} + +EventPipeSession * +ep_get_session (EventPipeSessionID session_id) +{ + ep_rt_config_requires_lock_not_held (); + + EP_CONFIG_LOCK_ENTER + + if (ep_volatile_load_eventpipe_state () == EP_STATE_NOT_INITIALIZED) { + EP_ASSERT (!"EventPipe::GetSession invoked before EventPipe was initialized."); + ep_raise_error_holding_lock (); + } + + ep_raise_error_if_nok_holding_lock (is_session_id_in_collection_lock_held (session_id) == true); + + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return (EventPipeSession *)session_id; + +ep_on_error: + session_id = 0; + ep_exit_error_handler (); +} + +bool +ep_enabled (void) +{ + //TODO: Validate if ever called without holding lock, if so should check be atomic? + return (ep_volatile_load_eventpipe_state () >= EP_STATE_INITIALIZED && + ep_volatile_load_number_of_sessions () > 0); +} + +EventPipeProvider * +ep_create_provider ( + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_null_if_nok (provider_name != NULL); + + EventPipeProvider *provider = NULL; + EventPipeProviderCallbackDataQueue data_queue; + EventPipeProviderCallbackData provider_callback_data; + EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&data_queue); + + EP_CONFIG_LOCK_ENTER + provider = ep_config_create_provider_lock_held (ep_config_get (), provider_name, callback_func, callback_data, provider_callback_data_queue); + ep_raise_error_if_nok_holding_lock (provider != NULL); + EP_CONFIG_LOCK_EXIT + + while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) + ep_provider_invoke_callback (&provider_callback_data); + +ep_on_exit: + ep_provider_callback_data_queue_fini (provider_callback_data_queue); + ep_rt_config_requires_lock_not_held (); + return provider; + +ep_on_error: + ep_delete_provider (provider); + + provider = NULL; + ep_exit_error_handler (); +} + +void +ep_delete_provider (EventPipeProvider *provider) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_void_if_nok (provider != NULL); + + // Take the lock to make sure that we don't have a race + // between disabling tracing and deleting a provider + // where we hold a provider after tracing has been disabled. + EP_CONFIG_LOCK_ENTER + if (enabled_lock_held ()) { + // Save the provider until the end of the tracing session. + ep_provider_set_delete_deferred (provider, true); + } else { + ep_config_delete_provider_lock_held (ep_config_get (), provider); + } + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +EventPipeProvider * +ep_get_provider (const ep_char8_t *provider_name) +{ + ep_rt_config_requires_lock_not_held (); + + ep_return_null_if_nok (provider_name != NULL); + + EventPipeProvider *provider = NULL; + + EP_CONFIG_LOCK_ENTER + provider = ep_config_get_provider_lock_held (ep_config_get (), provider_name); + ep_raise_error_if_nok_holding_lock (provider != NULL); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return provider; + +ep_on_error: + provider = NULL; + ep_exit_error_handler (); +} + +void +ep_init (void) +{ + ep_rt_init (); + ep_rt_config_requires_lock_not_held (); + + //TODO: Implement. Locking pattern between init/shutdown is racy but same as CoreCLR. Needs to be revisited. + if (ep_volatile_load_eventpipe_state () != EP_STATE_NOT_INITIALIZED) { + EP_ASSERT (!"EventPipe already initialized."); + return; + } + + for (uint32_t i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; ++i) + ep_volatile_store_session (i, NULL); + + if (ep_config_init (ep_config_get ())) { + EP_CONFIG_LOCK_ENTER + ep_volatile_store_eventpipe_state_without_barrier (EP_STATE_INITIALIZED); + EP_CONFIG_LOCK_EXIT + } + + //TODO: Implement. + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +void +ep_finish_init (void) +{ + //TODO: Implement. +} + +void +ep_shutdown (void) +{ + ep_rt_config_requires_lock_not_held (); + + //TODO: Locking pattern between init/shutdown is racy but same as CoreCLR. Needs to be revisited. + ep_return_void_if_nok (ep_volatile_load_eventpipe_state () != EP_STATE_SHUTTING_DOWN); + ep_return_void_if_nok (!ep_rt_process_detach ()); + ep_return_void_if_nok (ep_volatile_load_eventpipe_state () == EP_STATE_INITIALIZED); + + EP_CONFIG_LOCK_ENTER + ep_volatile_store_eventpipe_state_without_barrier (EP_STATE_SHUTTING_DOWN); + EP_CONFIG_LOCK_EXIT + + for (uint32_t i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; ++i) { + EventPipeSession *session = ep_volatile_load_session (i); + if (session) + ep_disable ((EventPipeSessionID)session); + } + + // dotnet/coreclr: issue 24850: EventPipe shutdown race conditions + // Deallocating providers/events here might cause AV if a WriteEvent + // was to occur. Thus, we are not doing this cleanup. + + // // Remove EventPipeEventSource first since it tries to use the data structures that we remove below. + // // We need to do this after disabling sessions since those try to write to EventPipeEventSource. + // delete s_pEventSource; + // s_pEventSource = nullptr; + // s_config.Shutdown(); + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + ep_rt_shutdown (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +EventPipeEventMetadataEvent * +ep_build_event_metadata_event ( + EventPipeEventInstance *event_instance, + uint32_t metadata_id) +{ + return ep_config_build_event_metadata_event (ep_config_get (), event_instance, metadata_id); +} + +void +ep_write_event ( + EventPipeEvent *ep_event, + EventData *event_data, + uint32_t event_data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id) +{ + //TODO: Implement. +} + +EventPipeEventInstance * +ep_get_next_event (EventPipeSessionID session_id) +{ + ep_rt_config_requires_lock_not_held (); + + // Only fetch the next event if a tracing session exists. + // The buffer manager is not disposed until the process is shutdown. + EventPipeSession *const session = ep_get_session (session_id); + return session ? ep_session_get_next_event (session) : NULL; +} + +EventPipeWaitHandle +ep_get_wait_handle (EventPipeSessionID session_id) +{ + EventPipeSession *const session = ep_get_session (session_id); + return session ? ep_session_get_wait_event (session) : 0; +} + +void +ep_start_streaming (EventPipeSessionID session_id) +{ + ep_rt_config_requires_lock_not_held (); + + EP_CONFIG_LOCK_ENTER + ep_raise_error_if_nok_holding_lock (is_session_id_in_collection_lock_held (session_id) == true); + EventPipeSession *const session = (EventPipeSession *)session_id; + ep_session_start_streaming_lock_held (session); + EP_CONFIG_LOCK_EXIT + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +/* + * EventPipePerf. + */ + +uint64_t +ep_perf_counter_query (void) +{ + return ep_rt_perf_counter_query (); +} + +uint64_t +ep_perf_frequency_query (void) +{ + return ep_rt_perf_frequency_query (); +} + +/* + * EventPipeProviderCallbackDataQueue. + */ + +void +ep_provider_callback_data_queue_enqueue ( + EventPipeProviderCallbackDataQueue *provider_callback_data_queue, + EventPipeProviderCallbackData *provider_callback_data) +{ + ep_return_void_if_nok (provider_callback_data_queue != NULL); + ep_rt_provider_callback_data_queue_push_tail (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), ep_provider_callback_data_alloc_copy (provider_callback_data)); +} + +bool +ep_provider_callback_data_queue_try_dequeue ( + EventPipeProviderCallbackDataQueue *provider_callback_data_queue, + EventPipeProviderCallbackData *provider_callback_data) +{ + ep_return_false_if_nok (provider_callback_data_queue != NULL && ep_rt_provider_callback_data_queue_is_empty (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue)) != true); + + EventPipeProviderCallbackData *value = NULL; + ep_rt_provider_callback_data_queue_pop_head (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), &value); + ep_provider_callback_data_init_copy (provider_callback_data, value); + ep_provider_callback_data_free (value); + + return true; +} + +#endif /* ENABLE_PERFTRACING */ + +extern const char quiet_linker_empty_file_warning_eventpipe; +const char quiet_linker_empty_file_warning_eventpipe = 0; diff --git a/src/mono/mono/eventpipe/ep.h b/src/mono/mono/eventpipe/ep.h new file mode 100644 index 0000000000000..ca11989aa415b --- /dev/null +++ b/src/mono/mono/eventpipe/ep.h @@ -0,0 +1,272 @@ +#ifndef __EVENTPIPE_H__ +#define __EVENTPIPE_H__ + +#include + +#ifdef ENABLE_PERFTRACING +#include "ep-rt-config.h" +#include "ep-types.h" +#include "ep-stream.h" +#include "ep-thread.h" +#include "ep-block.h" +#include "ep-event-payload.h" +#include "ep-buffer.h" +#include "ep-buffer-manager.h" +#include "ep-stack-contents.h" +#include "ep-event.h" +#include "ep-event-instance.h" +#include "ep-config.h" +#include "ep-event-source.h" +#include "ep-file.h" +#include "ep-metadata-generator.h" +#include "ep-provider.h" +#include "ep-session.h" +#include "ep-session-provider.h" +#include "ep-rt.h" + +/* + * Globals and volatile access functions. + */ + +static +inline +EventPipeState +ep_volatile_load_eventpipe_state (void) +{ + extern volatile EventPipeState _ep_state; + return (EventPipeState)ep_rt_volatile_load_uint32_t ((const volatile uint32_t *)&_ep_state); +} + +static +inline +EventPipeState +ep_volatile_load_eventpipe_state_without_barrier (void) +{ + extern volatile EventPipeState _ep_state; + return (EventPipeState)ep_rt_volatile_load_uint32_t_without_barrier ((const volatile uint32_t *)&_ep_state); +} + +static +inline +void +ep_volatile_store_eventpipe_state (EventPipeState state) +{ + extern volatile EventPipeState _ep_state; + ep_rt_volatile_store_uint32_t ((volatile uint32_t *)&_ep_state, state); +} + +static +inline +void +ep_volatile_store_eventpipe_state_without_barrier (EventPipeState state) +{ + extern volatile EventPipeState _ep_state; + ep_rt_volatile_store_uint32_t_without_barrier ((volatile uint32_t *)&_ep_state, state); +} + +static +inline +EventPipeSession * +ep_volatile_load_session (size_t index) +{ + extern volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS]; + return (EventPipeSession *)ep_rt_volatile_load_ptr ((volatile void **)(&_ep_sessions [index])); +} + +static +inline +EventPipeSession * +ep_volatile_load_session_without_barrier (size_t index) +{ + extern volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS]; + return (EventPipeSession *)ep_rt_volatile_load_ptr_without_barrier ((volatile void **)(&_ep_sessions [index])); +} + +static +inline +void +ep_volatile_store_session (size_t index, EventPipeSession *session) +{ + extern volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS]; + ep_rt_volatile_store_ptr ((volatile void **)(&_ep_sessions [index]), session); +} + +static +inline +void +ep_volatile_store_session_without_barrier (size_t index, EventPipeSession *session) +{ + extern volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS]; + ep_rt_volatile_store_ptr_without_barrier ((volatile void **)(&_ep_sessions [index]), session); +} + +static +inline +uint32_t +ep_volatile_load_number_of_sessions (void) +{ + extern volatile uint32_t _ep_number_of_sessions; + return ep_rt_volatile_load_uint32_t (&_ep_number_of_sessions); +} + +static +inline +uint32_t +ep_volatile_load_number_of_sessions_without_barrier (void) +{ + extern volatile uint32_t _ep_number_of_sessions; + return ep_rt_volatile_load_uint32_t_without_barrier (&_ep_number_of_sessions); +} + +static +inline +void +ep_volatile_store_number_of_sessions (uint32_t number_of_sessions) +{ + extern volatile uint32_t _ep_number_of_sessions; + ep_rt_volatile_store_uint32_t (&_ep_number_of_sessions, number_of_sessions); +} + +static +inline +void +ep_volatile_store_number_of_sessions_without_barrier (uint32_t number_of_sessions) +{ + extern volatile uint32_t _ep_number_of_sessions; + ep_rt_volatile_store_uint32_t_without_barrier (&_ep_number_of_sessions, number_of_sessions); +} + +static +inline +uint64_t +ep_volatile_load_allow_write (void) +{ + extern volatile uint64_t _ep_allow_write; + return ep_rt_volatile_load_uint64_t (&_ep_allow_write); +} + +static +inline +uint64_t +ep_volatile_load_allow_write_without_barrier (void) +{ + extern volatile uint64_t _ep_allow_write; + return ep_rt_volatile_load_uint64_t_without_barrier (&_ep_allow_write); +} + +static +inline +void +ep_volatile_store_allow_write (uint64_t allow_write) +{ + extern volatile uint64_t _ep_allow_write; + ep_rt_volatile_store_uint64_t (&_ep_allow_write, allow_write); +} + +static +inline +void +ep_volatile_store_allow_write_without_barrier (uint64_t allow_write) +{ + extern volatile uint64_t _ep_allow_write; + ep_rt_volatile_store_uint64_t_without_barrier (&_ep_allow_write, allow_write); +} + +/* + * EventPipe. + */ + +EventPipeSessionID +ep_enable ( + const ep_char8_t *output_path, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + IpcStream *stream, + bool enable_sample_profiler); + +void +ep_disable (EventPipeSessionID id); + +EventPipeSession * +ep_get_session (EventPipeSessionID session_id); + +bool +ep_enabled (void); + +EventPipeProvider * +ep_create_provider ( + const ep_char8_t *provider_name, + EventPipeCallback callback_func, + void *callback_data); + +void +ep_delete_provider (EventPipeProvider *provider); + +EventPipeProvider * +ep_get_provider (const ep_char8_t *provider_name); + +void +ep_init (void); + +void +ep_finish_init (void); + +void +ep_shutdown (void); + +EventPipeEventMetadataEvent * +ep_build_event_metadata_event ( + EventPipeEventInstance *event_instance, + uint32_t metadata_id); + +void +ep_write_event ( + EventPipeEvent *ep_event, + EventData *event_data, + uint32_t event_data_len, + const uint8_t *activity_id, + const uint8_t *related_activity_id); + +EventPipeEventInstance * +ep_get_next_event (EventPipeSessionID session_id); + +EventPipeWaitHandle +ep_get_wait_handle (EventPipeSessionID session_id); + +void +ep_start_streaming (EventPipeSessionID session_id); + +/* + * EventPipePerf. + */ + +uint64_t +ep_perf_counter_query (void); + +uint64_t +ep_perf_frequency_query (void); + +#else /* ENABLE_PERFTRACING */ + +static +inline +void +ep_init (void) +{ + ; +} + +static +inline +void +ep_shutdown (void) +{ + ; +} + +#endif /* ENABLE_PERFTRACING */ +#endif /** __EVENTPIPE_H__ **/ diff --git a/src/mono/mono/eventpipe/test/Directory.Build.props b/src/mono/mono/eventpipe/test/Directory.Build.props new file mode 100644 index 0000000000000..4de865b5f1e15 --- /dev/null +++ b/src/mono/mono/eventpipe/test/Directory.Build.props @@ -0,0 +1,3 @@ + + + diff --git a/src/mono/mono/eventpipe/test/Directory.Build.targets b/src/mono/mono/eventpipe/test/Directory.Build.targets new file mode 100644 index 0000000000000..c43cec29bd65d --- /dev/null +++ b/src/mono/mono/eventpipe/test/Directory.Build.targets @@ -0,0 +1,3 @@ + + + diff --git a/src/mono/mono/eventpipe/test/Makefile.am b/src/mono/mono/eventpipe/test/Makefile.am new file mode 100644 index 0000000000000..4513e50da6326 --- /dev/null +++ b/src/mono/mono/eventpipe/test/Makefile.am @@ -0,0 +1,56 @@ +MAKEFLAGS := $(MAKEFLAGS) --no-builtin-rules + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(GLIB_CFLAGS) + +if HOST_DARWIN +test_ldflags = -framework CoreFoundation -framework Foundation +endif + +sgen_libs = \ + $(top_builddir)/mono/metadata/libmonoruntimesgen.la \ + $(top_builddir)/mono/sgen/libmonosgen.la \ + $(top_builddir)/mono/utils/libmonoutils.la \ + $(top_builddir)/mono/eglib/libeglib.la + +mini_libs = \ + $(top_builddir)/mono/mini/libmini.la + +if !DISABLE_INTERPRETER +mini_libs += $(top_builddir)/mono/mini/libmono-ee-interp.la +endif + +if !DISABLE_DEBUGGER_AGENT +mini_libs += $(top_builddir)/mono/mini/libmono-dbg.la +endif + +eventpipe_libs = \ + $(top_builddir)/mono/eventpipe/libeventpipe.la + +CFLAGS = $(filter-out @CXX_REMOVE_CFLAGS@, @CFLAGS@) + +if !HOST_WIN32 +if ENABLE_PERFTRACING + +test_eventpipe_SOURCES = \ +ep-test-runner.c \ +ep-test-driver.c \ +ep-fake-tests.c \ +ep-fastserializer-tests.c \ +ep-provider-callback-dataqueue-tests.c \ +ep-setup-tests.c \ +ep-tests.c \ +ep-file-tests.c \ +ep-session-tests.c \ +ep-teardown-tests.c \ +ep-thread-tests.c \ +ep-tests-debug.h \ +ep-tests.h + +test_eventpipe_CFLAGS = $(AM_CFLAGS) $(SGEN_DEFINES) +test_eventpipe_LDADD = $(mini_libs) $(sgen_libs) $(eventpipe_libs) +test_eventpipe_LDFLAGS = $(test_ldflags) + +noinst_PROGRAMS = test-eventpipe + +endif ENABLE_PERFTRACING +endif !HOST_WIN32 diff --git a/src/mono/mono/eventpipe/test/ep-fake-tests.c b/src/mono/mono/eventpipe/test/ep-fake-tests.c new file mode 100644 index 0000000000000..86bc252101893 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-fake-tests.c @@ -0,0 +1 @@ +#include "mono/eglib/test/fake.c" diff --git a/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c b/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c new file mode 100644 index 0000000000000..0d39f7e6f294a --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-fastserializer-tests.c @@ -0,0 +1,346 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" + +#define TEST_PROVIDER_NAME "MyTestProvider" + +typedef struct _MemoryStreamWriter { + StreamWriter stream_writer; + uint8_t buffer [1024]; + uint8_t *current_ptr; +} MemoryStreamWriter; + +static +void +memory_stream_writer_free_func (void *stream) +{ + g_free ((MemoryStreamWriter *)stream); +} + +static +bool +memory_stream_writer_write_func ( + void *stream, + const uint8_t *buffer, + uint32_t bytes_to_write, + uint32_t *bytes_written) +{ + *bytes_written = 0; + + MemoryStreamWriter *memory_stream = (MemoryStreamWriter *)stream; + if (!stream) + return false; + + if ((memory_stream->current_ptr + bytes_to_write) > (memory_stream->buffer + sizeof (memory_stream->buffer))) + return false; + + memcpy (memory_stream->current_ptr, buffer, bytes_to_write); + memory_stream->current_ptr += bytes_to_write; + *bytes_written = bytes_to_write; + + return true; +} + +static StreamWriterVtable memory_stream_writer_vtable = { + memory_stream_writer_free_func, + memory_stream_writer_write_func }; + +static RESULT +test_fast_serializer_object_fast_serialize (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + MemoryStreamWriter *stream_writer = NULL; + FastSerializer *fast_serializer = NULL; + EventPipeProvider *provider = NULL; + EventPipeEvent *ep_event = NULL; + EventPipeEventInstance *ep_event_instance = NULL; + EventPipeEventBlock *event_block = NULL; + + // Use memory stream for testing. + stream_writer = g_new0 (MemoryStreamWriter, 1); + ep_raise_error_if_nok (stream_writer != NULL); + + test_location = 1; + + stream_writer->current_ptr = stream_writer->buffer; + ep_stream_writer_init (&stream_writer->stream_writer, &memory_stream_writer_vtable); + + fast_serializer = ep_fast_serializer_alloc ((StreamWriter *)stream_writer); + ep_raise_error_if_nok (fast_serializer != NULL); + stream_writer = NULL; + + test_location = 2; + + provider = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + ep_raise_error_if_nok (provider != NULL); + + test_location = 3; + + ep_event = ep_event_alloc (provider, 1, 1, 1, EP_EVENT_LEVEL_VERBOSE, false, NULL, 0); + ep_raise_error_if_nok (ep_event != NULL); + + test_location = 4; + + ep_event_instance = ep_event_instance_alloc (ep_event, 0, 0, NULL, 0, NULL, NULL); + event_block = ep_event_block_alloc (1024, EP_SERIALIZATION_FORMAT_NETTRACE_V4); + ep_raise_error_if_nok (ep_event_instance != NULL && event_block != NULL); + + test_location = 5; + + ep_raise_error_if_nok (ep_event_block_base_write_event ((EventPipeEventBlockBase *)event_block, ep_event_instance, 0, 1, 0, false) == true); + + test_location = 6; + + ep_fast_serializable_object_fast_serialize ((FastSerializableObject *)event_block, fast_serializer); + + //Check memory stream results. + stream_writer = (MemoryStreamWriter *)ep_fast_serializer_get_stream_writer (fast_serializer); + if (stream_writer->buffer == stream_writer->current_ptr) { + result = FAILED ("fast_serialize for EventPipeEventBlock didn't write any data into MemoryStreamWriter"); + ep_raise_error (); + } + +ep_on_exit: + ep_event_instance_free (ep_event_instance); + ep_event_block_free (event_block); + ep_event_free (ep_event); + ep_delete_provider (provider); + ep_fast_serializer_free (fast_serializer); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_event_block_free_vcall (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeEventBlock *event_block = ep_event_block_alloc (1024, EP_SERIALIZATION_FORMAT_NETTRACE_V4); + ep_raise_error_if_nok (event_block != NULL); + + test_location = 1; + + ep_fast_serializable_object_free_vcall ((FastSerializableObject *)event_block); + +ep_on_exit: + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_metadata_block_free_vcall (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeMetadataBlock *metadata_block = ep_metadata_block_alloc (1024); + ep_raise_error_if_nok (metadata_block != NULL); + + test_location = 1; + + ep_fast_serializable_object_free_vcall ((FastSerializableObject *)metadata_block); + +ep_on_exit: + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_sequence_point_block_free_vcall (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSequencePoint sequence_point; + EventPipeSequencePointBlock *sequence_point_block = NULL; + + ep_raise_error_if_nok (ep_sequence_point_init (&sequence_point) != NULL); + + test_location = 1; + + sequence_point_block = ep_sequence_point_block_alloc (&sequence_point); + ep_raise_error_if_nok (sequence_point_block != NULL); + + test_location = 2; + + ep_fast_serializable_object_free_vcall ((FastSerializableObject *)sequence_point_block); + +ep_on_exit: + ep_sequence_point_fini (&sequence_point); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_stack_block_free_vcall (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeStackBlock *stack_block = ep_stack_block_alloc (1024); + ep_raise_error_if_nok (stack_block != NULL); + + test_location = 1; + + ep_fast_serializable_object_free_vcall ((FastSerializableObject *)stack_block); + +ep_on_exit: + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_event_block_get_type_name (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeEventBlock *event_block = ep_event_block_alloc (1024, EP_SERIALIZATION_FORMAT_NETTRACE_V4); + ep_raise_error_if_nok (event_block != NULL); + + test_location = 1; + + const char *type_name = (char *)ep_fast_serializable_object_get_type_name ((FastSerializableObject *)event_block); + if (strcmp (type_name, "EventBlock")) { + result = FAILED ("get_type_name for EventPipeEventBlock returned unexpected value, retrieved: %s, expected: %s", type_name, "EventBlock"); + ep_raise_error (); + } + +ep_on_exit: + ep_event_block_free (event_block); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_metadata_block_get_type_name (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeMetadataBlock *metadata_block = ep_metadata_block_alloc (1024); + ep_raise_error_if_nok (metadata_block != NULL); + + test_location = 1; + + const char *type_name = (char *)ep_fast_serializable_object_get_type_name ((FastSerializableObject *)metadata_block); + if (strcmp (type_name, "MetadataBlock")) { + result = FAILED ("get_type_name for EventPipeMetadataBlock returned unexpected value, retrieved: %s, expected: %s", type_name, "MetadataBlock"); + ep_raise_error (); + } + +ep_on_exit: + ep_metadata_block_free (metadata_block); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_sequence_point_block_get_type_name (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSequencePoint sequence_point; + EventPipeSequencePointBlock *sequence_point_block = NULL; + + ep_raise_error_if_nok (ep_sequence_point_init (&sequence_point) != NULL); + + test_location = 1; + + sequence_point_block = ep_sequence_point_block_alloc (&sequence_point); + ep_raise_error_if_nok (sequence_point_block != NULL); + + test_location = 2; + + const char *type_name = (char *)ep_fast_serializable_object_get_type_name ((FastSerializableObject *)sequence_point_block); + if (strcmp (type_name, "SPBlock")) { + result = FAILED ("get_type_name for EventPipeSequencePointBlock returned unexpected value, retrieved: %s, expected: %s", type_name, "SPBlock"); + ep_raise_error (); + } + +ep_on_exit: + ep_sequence_point_block_free (sequence_point_block); + ep_sequence_point_fini (&sequence_point); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_fast_serializer_stack_block_get_type_name (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeStackBlock *stack_block = ep_stack_block_alloc (1024); + ep_raise_error_if_nok (stack_block != NULL); + + test_location = 1; + + const char *type_name = (char *)ep_fast_serializable_object_get_type_name ((FastSerializableObject *)stack_block); + if (strcmp (type_name, "StackBlock")) { + result = FAILED ("get_type_name for EventPipeStackBlock returned unexpected value, retrieved: %s, expected: %s", type_name, "StackBlock"); + ep_raise_error (); + } + +ep_on_exit: + ep_stack_block_free (stack_block); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +//TODO: Add perf test just doing write into fast serializer with different event types (no event alloc/instancing). Write into void +//stream but still write into same memory buffer to do something. + +static Test ep_fastserializer_tests [] = { + {"fast_serializer_object_fast_serialize", test_fast_serializer_object_fast_serialize}, + {"test_fast_serializer_event_block_free_vcall", test_fast_serializer_event_block_free_vcall}, + {"test_fast_serializer_metadata_block_free_vcall", test_fast_serializer_metadata_block_free_vcall}, + {"test_fast_serializer_sequence_point_block_free_vcall", test_fast_serializer_sequence_point_block_free_vcall}, + {"test_fast_serializer_stack_block_free_vcall", test_fast_serializer_stack_block_free_vcall}, + {"test_fast_serializer_event_block_get_type_name", test_fast_serializer_event_block_get_type_name}, + {"test_fast_serializer_metadata_block_get_type_name", test_fast_serializer_metadata_block_get_type_name}, + {"test_fast_serializer_sequence_point_block_get_type_name", test_fast_serializer_sequence_point_block_get_type_name}, + {"test_fast_serializer_stack_block_get_type_name", test_fast_serializer_stack_block_get_type_name}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_fastserializer_tests_init, ep_fastserializer_tests) diff --git a/src/mono/mono/eventpipe/test/ep-file-tests.c b/src/mono/mono/eventpipe/test/ep-file-tests.c new file mode 100644 index 0000000000000..696d2442c9baf --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-file-tests.c @@ -0,0 +1,172 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" + +#define TEST_PROVIDER_NAME "MyTestProvider" +#define TEST_FILE "./ep_test_create_file.txt" + +static RESULT +test_create_file (EventPipeSerializationFormat format) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeFile *file = NULL; + FileStreamWriter *file_stream_writer = NULL; + + file_stream_writer = ep_file_stream_writer_alloc (TEST_FILE); + ep_raise_error_if_nok (file_stream_writer != NULL); + + test_location = 1; + + file = ep_file_alloc ((StreamWriter *)file_stream_writer, format); + ep_raise_error_if_nok (file != NULL); + + file_stream_writer = NULL; + if (!ep_file_initialize_file (file)) { + result = FAILED ("ep_file_initialize_file failed"); + ep_raise_error (); + } + + test_location = 2; + + ep_file_flush (file, EP_FILE_FLUSH_FLAGS_ALL_BLOCKS); + + test_location = 3; + +ep_on_exit: + ep_file_free (file); + ep_file_stream_writer_free (file_stream_writer); + + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_file_write_event (EventPipeSerializationFormat format, bool write_event, bool write_sequence_point) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeFile *file = NULL; + FileStreamWriter *file_stream_writer = NULL; + EventPipeProvider *provider = NULL; + EventPipeEvent *ep_event = NULL; + EventPipeEventInstance *ep_event_instance = NULL; + EventPipeEventMetadataEvent *metadata_event = NULL; + + file_stream_writer = ep_file_stream_writer_alloc (TEST_FILE); + ep_raise_error_if_nok (file_stream_writer != NULL); + + test_location = 1; + + file = ep_file_alloc ((StreamWriter *)file_stream_writer, format); + ep_raise_error_if_nok (file != NULL); + + file_stream_writer = NULL; + if (!ep_file_initialize_file (file)) { + result = FAILED ("ep_file_initialize_file failed"); + ep_raise_error (); + } + + test_location = 2; + + if (write_event) { + provider = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + ep_raise_error_if_nok (provider != NULL); + + test_location = 3; + + ep_event = ep_event_alloc (provider, 1, 1, 1, EP_EVENT_LEVEL_VERBOSE, false, NULL, 0); + ep_raise_error_if_nok (ep_event != NULL); + + test_location = 4; + + ep_event_instance = ep_event_instance_alloc (ep_event, 0, 0, NULL, 0, NULL, NULL); + ep_raise_error_if_nok (ep_event_instance != NULL); + + test_location = 5; + + metadata_event = ep_build_event_metadata_event (ep_event_instance, 1); + ep_raise_error_if_nok (metadata_event != NULL); + + ep_file_write_event (file, (EventPipeEventInstance *)metadata_event, 1, 1 , true); + } + + if (write_sequence_point) { + EventPipeSequencePoint sequence_point; + ep_sequence_point_init (&sequence_point); + ep_file_write_sequence_point (file, &sequence_point); + ep_sequence_point_fini (&sequence_point); + } + + ep_file_flush (file, EP_FILE_FLUSH_FLAGS_ALL_BLOCKS); + + test_location = 6; + +ep_on_exit: + ep_delete_provider (provider); + ep_event_free (ep_event); + ep_event_instance_free (ep_event_instance); + ep_event_metdata_event_free (metadata_event); + ep_file_free (file); + ep_file_stream_writer_free (file_stream_writer); + + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_create_file_netperf_v3 (void) +{ + return test_create_file (EP_SERIALIZATION_FORMAT_NETPERF_V3); +} + +static RESULT +test_create_file_nettrace_v4 (void) +{ + return test_create_file (EP_SERIALIZATION_FORMAT_NETTRACE_V4); +} + +static RESULT +test_file_write_event_netperf_v3 (void) +{ + return test_file_write_event (EP_SERIALIZATION_FORMAT_NETPERF_V3, true, false); +} + +static RESULT +test_file_write_event_nettrace_v4 (void) +{ + return test_file_write_event (EP_SERIALIZATION_FORMAT_NETTRACE_V4, true, false); +} + +static RESULT +test_file_write_sequence_point_netperf_v3 (void) +{ + return test_file_write_event (EP_SERIALIZATION_FORMAT_NETPERF_V3, false, true); +} + +static RESULT +test_file_write_sequence_point_nettrace_v4 (void) +{ + return test_file_write_event (EP_SERIALIZATION_FORMAT_NETTRACE_V4, false, true); +} + +static Test ep_file_tests [] = { + {"test_create_file_netperf_v3", test_create_file_netperf_v3}, + {"test_create_file_nettrace_v4", test_create_file_nettrace_v4}, + {"test_file_write_event_netperf_v3", test_file_write_event_netperf_v3}, + {"test_file_write_event_nettrace_v4", test_file_write_event_nettrace_v4}, + {"test_file_write_sequence_point_netperf_v3", test_file_write_sequence_point_netperf_v3}, + {"test_file_write_sequence_point_nettrace_v4", test_file_write_sequence_point_nettrace_v4}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_file_tests_init, ep_file_tests) diff --git a/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c b/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c new file mode 100644 index 0000000000000..06a45c4c6a5e7 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c @@ -0,0 +1,98 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" + +#define TEST_PROVIDER_NAME "MyTestProvider" +#define TEST_FILE "./ep_test_create_file.txt" + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState eventpipe_memory_start_snapshot; +static _CrtMemState eventpipe_memory_end_snapshot; +static _CrtMemState eventpipe_memory_diff_snapshot; +#endif + +static RESULT +test_provider_callback_data_queue_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_start_snapshot); +#endif + return NULL; +} + +static +void +provider_callback ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_context) +{ + ; +} + +static RESULT +test_provider_callback_data_queue (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeProviderCallbackDataQueue callback_data_queue; + EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); + + EventPipeProviderCallbackData enqueue_callback_data; + EventPipeProviderCallbackData *provider_enqueue_callback_data = ep_provider_callback_data_init ( + &enqueue_callback_data, + "", + provider_callback, + NULL, + 1, + EP_EVENT_LEVEL_LOG_ALWAYS, + true); + + for (uint32_t i = 0; i < 1000; ++i) + ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, provider_enqueue_callback_data); + + EventPipeProviderCallbackData dequeue_callback_data; + uint32_t deque_counter = 0; + while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &dequeue_callback_data)) + deque_counter++; + + if (deque_counter != 1000) { + result = FAILED ("Unexpected number of provider callback invokes"); + ep_raise_error (); + } + +ep_on_exit: + ep_provider_callback_data_queue_fini (provider_callback_data_queue); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_provider_callback_data_queue_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_end_snapshot); + if ( _CrtMemDifference( &eventpipe_memory_diff_snapshot, &eventpipe_memory_start_snapshot, &eventpipe_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &eventpipe_memory_diff_snapshot ); + return FAILED ("Memory leak detected!"); + } +#endif + return NULL; +} + +static Test ep_provider_callback_data_queue_tests [] = { + {"test_provider_callback_data_queue_setup", test_provider_callback_data_queue_setup}, + {"test_provider_callback_data_queue", test_provider_callback_data_queue}, + {"test_provider_callback_data_queue_teardown", test_provider_callback_data_queue_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_provider_callback_data_queue_tests_init, ep_provider_callback_data_queue_tests) diff --git a/src/mono/mono/eventpipe/test/ep-session-tests.c b/src/mono/mono/eventpipe/test/ep-session-tests.c new file mode 100644 index 0000000000000..c9ef8fa79acfe --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-session-tests.c @@ -0,0 +1,244 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" + +#define TEST_PROVIDER_NAME "MyTestProvider" +#define TEST_FILE "./ep_test_create_file.txt" + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState eventpipe_memory_start_snapshot; +static _CrtMemState eventpipe_memory_end_snapshot; +static _CrtMemState eventpipe_memory_diff_snapshot; +#endif + +static RESULT +test_session_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_start_snapshot); +#endif + return NULL; +} + +static RESULT +test_create_delete_session (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + EventPipeSession *test_session = NULL; + + EventPipeProviderConfiguration provider_config; + ep_raise_error_if_nok (ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, "") != NULL); + + test_location = 1; + + EP_CONFIG_LOCK_ENTER + test_session = ep_session_alloc ( + 1, + TEST_FILE, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + 1, + &provider_config, + 1, + false); + EP_CONFIG_LOCK_EXIT + + ep_raise_error_if_nok (test_session != NULL); + +ep_on_exit: + ep_session_free (test_session); + if (test_location != 0) + ep_provider_config_fini (&provider_config); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_add_session_providers (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + EventPipeSession *test_session = NULL; + EventPipeSessionProvider *test_session_provider = NULL; + + EventPipeProviderConfiguration provider_config; + ep_raise_error_if_nok (ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, "") != NULL); + + test_location = 1; + + EP_CONFIG_LOCK_ENTER + test_session = ep_session_alloc ( + 1, + TEST_FILE, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + 1, + &provider_config, + 1, + false); + EP_CONFIG_LOCK_EXIT + + ep_raise_error_if_nok (test_session != NULL); + + test_location = 2; + + if (!ep_session_is_valid (test_session)) { + result = FAILED ("ep_session_is_valid returned false with session providers"); + ep_raise_error (); + } + + test_location = 3; + + test_session_provider = ep_session_provider_alloc (TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, ""); + ep_raise_error_if_nok (test_session_provider != NULL); + + test_location = 4; + + ep_session_add_session_provider (test_session, test_session_provider); + test_session_provider = NULL; + + if (!ep_session_is_valid (test_session)) { + result = FAILED ("ep_session_is_valid returned false with session providers"); + ep_raise_error (); + } + + test_location = 5; + + ep_session_disable (test_session); + + if (ep_session_is_valid (test_session)) { + result = FAILED ("ep_session_is_valid returned true without session providers"); + ep_raise_error (); + } + +ep_on_exit: + ep_session_free (test_session); + if (test_location != 0) + ep_provider_config_fini (&provider_config); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_session_special_get_set (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + EventPipeSession *test_session = NULL; + + EventPipeProviderConfiguration provider_config; + EventPipeProviderConfiguration *current_provider_config = ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, ""); + ep_raise_error_if_nok (current_provider_config != NULL); + + test_location = 1; + + EP_CONFIG_LOCK_ENTER + test_session = ep_session_alloc ( + 1, + TEST_FILE, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + 1, + current_provider_config, + 1, + false); + EP_CONFIG_LOCK_EXIT + + ep_raise_error_if_nok (test_session != NULL); + + test_location = 2; + + if (ep_session_get_rundown_enabled (test_session)) { + result = FAILED ("ep_session_get_rundown_enabled returned true, should be false"); + ep_raise_error (); + } + + test_location = 3; + + ep_session_set_rundown_enabled (test_session, true); + + if (!ep_session_get_rundown_enabled (test_session)) { + result = FAILED ("ep_session_get_rundown_enabled returned false, should be true"); + ep_raise_error (); + } + + test_location = 4; + + if (ep_session_get_ipc_streaming_enabled (test_session)) { + result = FAILED ("ep_session_get_ipc_streaming_enabled returned true, should be false"); + ep_raise_error (); + } + + test_location = 5; + + ep_session_set_ipc_streaming_enabled (test_session, true); + + if (!ep_session_get_ipc_streaming_enabled (test_session)) { + result = FAILED ("ep_session_set_ipc_streaming_enabled returned false, should be true"); + ep_raise_error (); + } + + ep_session_set_ipc_streaming_enabled (test_session, false); + + test_location = 6; + + if (!ep_session_get_wait_event (test_session)) { + result = FAILED ("ep_session_get_wait_event failed"); + ep_raise_error (); + } + + test_location = 7; + + if (!ep_session_get_mask (test_session)) { + result = FAILED ("Unexpected session mask"); + ep_raise_error (); + } + +ep_on_exit: + ep_session_free (test_session); + ep_provider_config_fini (current_provider_config); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_session_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_end_snapshot); + if ( _CrtMemDifference( &eventpipe_memory_diff_snapshot, &eventpipe_memory_start_snapshot, &eventpipe_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &eventpipe_memory_diff_snapshot ); + return FAILED ("Memory leak detected!"); + } +#endif + return NULL; +} + +static Test ep_session_tests [] = { + {"test_session_setup", test_session_setup}, + {"test_create_delete_session", test_create_delete_session}, + {"test_add_session_providers", test_add_session_providers}, + {"test_session_special_get_set", test_session_special_get_set}, + {"test_session_teardown", test_session_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_session_tests_init, ep_session_tests) diff --git a/src/mono/mono/eventpipe/test/ep-setup-tests.c b/src/mono/mono/eventpipe/test/ep-setup-tests.c new file mode 100644 index 0000000000000..30e51463bc169 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-setup-tests.c @@ -0,0 +1,27 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" +#include +#include + +MonoDomain *eventpipe_test_domain; + +static RESULT +test_setup (void) +{ + char *core_root = g_getenv ("CORE_ROOT"); + if (core_root) { + mono_set_assemblies_path (core_root); + g_free (core_root); + } + + eventpipe_test_domain = mono_jit_init_version_for_test_only ("eventpipe-tests", "v4.0.30319"); + + return NULL; +} + +static Test ep_setup_tests [] = { + {"test_setup", test_setup}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_setup_tests_init, ep_setup_tests) diff --git a/src/mono/mono/eventpipe/test/ep-teardown-tests.c b/src/mono/mono/eventpipe/test/ep-teardown-tests.c new file mode 100644 index 0000000000000..3800f9360e725 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-teardown-tests.c @@ -0,0 +1,25 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" +#include + +#define TEST_FILE "./ep_test_create_file.txt" + +extern MonoDomain *eventpipe_test_domain; + +static RESULT +test_teardown (void) +{ + if (eventpipe_test_domain) + mono_jit_cleanup (eventpipe_test_domain); + + unlink (TEST_FILE); + + return NULL; +} + +static Test ep_teardown_tests [] = { + {"test_teardown", test_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_teardown_tests_init, ep_teardown_tests) diff --git a/src/mono/mono/eventpipe/test/ep-test-driver.c b/src/mono/mono/eventpipe/test/ep-test-driver.c new file mode 100644 index 0000000000000..a1aa730b814c7 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-test-driver.c @@ -0,0 +1,5 @@ +#define DRIVER_EXTERNAL_TESTS +#define DRIVER_NAME "eventpipe-tests" + +#include "ep-tests.h" +#include "mono/eglib/test/driver.c" diff --git a/src/mono/mono/eventpipe/test/ep-test-runner.c b/src/mono/mono/eventpipe/test/ep-test-runner.c new file mode 100644 index 0000000000000..7e9072000f921 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-test-runner.c @@ -0,0 +1 @@ +#include "mono/eglib/test/test.c" diff --git a/src/mono/mono/eventpipe/test/ep-test.sln b/src/mono/mono/eventpipe/test/ep-test.sln new file mode 100644 index 0000000000000..4431637a8dbb8 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-test.sln @@ -0,0 +1,127 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30011.22 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ep-test", "ep-test.vcxproj", "{AF48E883-A558-4027-8934-32CFD2750D04}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eglib", "..\..\..\msvc\eglib.vcxproj", "{158073ED-99AE-4196-9EDC-DDB2344F8466}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmonoutils", "..\..\..\msvc\libmonoutils.vcxproj", "{8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}" + ProjectSection(ProjectDependencies) = postProject + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} = {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmonoruntime", "..\..\..\msvc\libmonoruntime.vcxproj", "{C36612BD-22D3-4B95-85E2-7FDC4FC5D739}" + ProjectSection(ProjectDependencies) = postProject + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} = {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgcmonosgen", "..\..\..\msvc\libgcmonosgen.vcxproj", "{C36612BD-22D3-4B95-85E2-7FDC4FC5D740}" + ProjectSection(ProjectDependencies) = postProject + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmini", "..\..\..\msvc\libmini.vcxproj", "{88D2EB79-592D-45F8-B849-AE021C1D983A}" + ProjectSection(ProjectDependencies) = postProject + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} = {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} = {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "static-mono-runtime", "static-mono-runtime", "{B46B84C3-14C4-4C81-B4A3-CE5292663515}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmono-static", "..\..\..\msvc\libmono-static.vcxproj", "{CB0D9E92-293C-439C-9AC7-C5F59B6E0772}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "build-init", "..\..\..\msvc\build-init.vcxproj", "{92AE7622-5F58-4234-9A26-9EC71876B3F4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AF48E883-A558-4027-8934-32CFD2750D04}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF48E883-A558-4027-8934-32CFD2750D04}.Debug|Win32.Build.0 = Debug|Win32 + {AF48E883-A558-4027-8934-32CFD2750D04}.Debug|x64.ActiveCfg = Debug|x64 + {AF48E883-A558-4027-8934-32CFD2750D04}.Debug|x64.Build.0 = Debug|x64 + {AF48E883-A558-4027-8934-32CFD2750D04}.Release|Win32.ActiveCfg = Release|Win32 + {AF48E883-A558-4027-8934-32CFD2750D04}.Release|Win32.Build.0 = Release|Win32 + {AF48E883-A558-4027-8934-32CFD2750D04}.Release|x64.ActiveCfg = Release|x64 + {AF48E883-A558-4027-8934-32CFD2750D04}.Release|x64.Build.0 = Release|x64 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|Win32.ActiveCfg = Debug|Win32 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|Win32.Build.0 = Debug|Win32 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|x64.ActiveCfg = Debug|x64 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|x64.Build.0 = Debug|x64 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|Win32.ActiveCfg = Release|Win32 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|Win32.Build.0 = Release|Win32 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|x64.ActiveCfg = Release|x64 + {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|x64.Build.0 = Release|x64 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|Win32.Build.0 = Debug|Win32 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|x64.ActiveCfg = Debug|x64 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|x64.Build.0 = Debug|x64 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|Win32.ActiveCfg = Release|Win32 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|Win32.Build.0 = Release|Win32 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|x64.ActiveCfg = Release|x64 + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|x64.Build.0 = Release|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|Win32.ActiveCfg = Debug|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|Win32.Build.0 = Debug|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|x64.ActiveCfg = Debug|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|x64.Build.0 = Debug|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|Win32.ActiveCfg = Release|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|Win32.Build.0 = Release|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|x64.ActiveCfg = Release|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|x64.Build.0 = Release|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|Win32.ActiveCfg = Debug|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|Win32.Build.0 = Debug|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|x64.ActiveCfg = Debug|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|x64.Build.0 = Debug|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|Win32.ActiveCfg = Release|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|Win32.Build.0 = Release|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|x64.ActiveCfg = Release|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|x64.Build.0 = Release|x64 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Debug|Win32.ActiveCfg = Debug|Win32 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Debug|Win32.Build.0 = Debug|Win32 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Debug|x64.ActiveCfg = Debug|x64 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Debug|x64.Build.0 = Debug|x64 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Release|Win32.ActiveCfg = Release|Win32 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Release|Win32.Build.0 = Release|Win32 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Release|x64.ActiveCfg = Release|x64 + {88D2EB79-592D-45F8-B849-AE021C1D983A}.Release|x64.Build.0 = Release|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|Win32.Build.0 = Debug|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|x64.ActiveCfg = Debug|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|x64.Build.0 = Debug|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|Win32.ActiveCfg = Release|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|Win32.Build.0 = Release|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|x64.ActiveCfg = Release|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|x64.Build.0 = Release|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|Win32.Build.0 = Debug|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|x64.ActiveCfg = Debug|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|x64.Build.0 = Debug|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|Win32.ActiveCfg = Release|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|Win32.Build.0 = Release|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|x64.ActiveCfg = Release|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + {88D2EB79-592D-45F8-B849-AE021C1D983A} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + {92AE7622-5F58-4234-9A26-9EC71876B3F4} = {B46B84C3-14C4-4C81-B4A3-CE5292663515} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CE83F76A-FA5A-4DF0-B015-5D802539DEFC} + EndGlobalSection +EndGlobal diff --git a/src/mono/mono/eventpipe/test/ep-test.vcxproj b/src/mono/mono/eventpipe/test/ep-test.vcxproj new file mode 100644 index 0000000000000..6687c5d70819c --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-test.vcxproj @@ -0,0 +1,186 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ..\..\.. + + + + + + + + + + + + + + + + + + + + + {cb0d9e92-293c-439c-9ac7-c5f59b6e0772} + + + + {AF48E883-A558-4027-8934-32CFD2750D04} + eventpipe + Win32Proj + 10.0 + + + + Application + false + $(DefaultPlatformToolset) + Unicode + + + Application + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + + + + + + + + + + + + + + + + + + + + + false + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + false + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + true + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + true + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) + Level4 + Disabled + $(ProjectDir)ep-tests-debug.h + + + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + Console + + + + + Level4 + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) + true + true + true + + + %(AdditionalLibraryDirectories) + Console + %(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + X64 + + + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) + Level4 + Disabled + $(ProjectDir)ep-tests-debug.h + + + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + Console + + + + + X64 + + + Level4 + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) + true + true + true + + + %(AdditionalLibraryDirectories) + Console + %(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + + \ No newline at end of file diff --git a/src/mono/mono/eventpipe/test/ep-test.vcxproj.filters b/src/mono/mono/eventpipe/test/ep-test.vcxproj.filters new file mode 100644 index 0000000000000..e9d41287b865a --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-test.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + Source Files\tests + + + Source Files\tests + + + Source Files\tests + + + Source Files\tests + + + Source Files\tests + + + Source Files\tests + + + Source Files\tests + + + Source Files\tests + + + Source Files\testframework + + + Source Files\testframework + + + Source Files\testframework + + + + + {d0fb7679-6e47-42a8-bd98-9c31c4bb065a} + + + {ee850408-9c60-43ab-8845-133cdd03c67a} + + + {0bf8953c-e42a-464e-b422-a451238f319f} + + + {29232fda-0808-499c-9d29-f079a62967e7} + + + {e0fbc587-715b-4470-be21-7645cfe77e5a} + + + + + Header Files\tests + + + Header Files\tests + + + \ No newline at end of file diff --git a/src/mono/mono/eventpipe/test/ep-tests-debug.h b/src/mono/mono/eventpipe/test/ep-tests-debug.h new file mode 100644 index 0000000000000..e86795ea3ff5f --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-tests-debug.h @@ -0,0 +1,8 @@ +#ifndef __EVENTPIPE_TESTS_DEBUG_H__ +#define __EVENTPIPE_TESTS_DEBUG_H__ + +#define _CRTDBG_MAP_ALLOC +#include +#include + +#endif /* __EVENTPIPE_TESTS_DEBUG_H__ */ diff --git a/src/mono/mono/eventpipe/test/ep-tests.c b/src/mono/mono/eventpipe/test/ep-tests.c new file mode 100644 index 0000000000000..2cc0ddb1bad87 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-tests.c @@ -0,0 +1,399 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" + +#define TEST_PROVIDER_NAME "MyTestProvider" +#define TEST_FILE "./ep_test_create_file.txt" + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState eventpipe_memory_start_snapshot; +static _CrtMemState eventpipe_memory_end_snapshot; +static _CrtMemState eventpipe_memory_diff_snapshot; +#endif + +static RESULT +test_eventpipe_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_start_snapshot); +#endif + return NULL; +} + +static RESULT +test_create_delete_provider (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeProvider *test_provider = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + if (!test_provider) { + result = FAILED ("Failed to create provider %s, ep_create_provider returned NULL", TEST_PROVIDER_NAME); + ep_raise_error (); + } + +ep_on_exit: + ep_delete_provider (test_provider); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_stress_create_delete_provider (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeProvider *test_providers [1000] = {0}; + + for (uint32_t i = 0; i < 1000; ++i) { + char *provider_name = g_strdup_printf (TEST_PROVIDER_NAME "_%i", i); + test_providers [i] = ep_create_provider (provider_name, NULL, NULL); + g_free (provider_name); + + if (!test_providers [i]) { + result = FAILED ("Failed to create provider %s_%i, ep_create_provider returned NULL", TEST_PROVIDER_NAME, i); + ep_raise_error (); + } + } + +ep_on_exit: + for (uint32_t i = 0; i < 1000; ++i) { + if (test_providers [i]) + ep_delete_provider (test_providers [i]); + } + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_get_provider (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeProvider *test_provider = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + if (!test_provider) { + result = FAILED ("Failed to create provider %s, ep_create_provider returned NULL", TEST_PROVIDER_NAME); + ep_raise_error (); + } + + test_location = 1; + + EventPipeProvider *returned_test_provider = ep_get_provider (TEST_PROVIDER_NAME); + if (!returned_test_provider) { + result = FAILED ("Failed to get provider %s, ep_get_provider returned NULL", TEST_PROVIDER_NAME); + ep_raise_error (); + } + + test_location = 2; + + ep_delete_provider (test_provider); + test_provider = NULL; + + returned_test_provider = ep_get_provider (TEST_PROVIDER_NAME); + if (returned_test_provider) { + result = FAILED ("Provider %s, still returned from ep_get_provider after deleted", TEST_PROVIDER_NAME); + ep_raise_error (); + } + +ep_on_exit: + ep_delete_provider (test_provider); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_create_same_provider_twice (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeProvider *test_provider = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + if (!test_provider) { + result = FAILED ("Failed to create provider %s, ep_create_provider returned NULL", TEST_PROVIDER_NAME); + ep_raise_error (); + } + + test_location = 1; + + EventPipeProvider *returned_test_provider = ep_get_provider (TEST_PROVIDER_NAME); + if (!returned_test_provider) { + result = FAILED ("Failed to get provider %s, ep_get_provider returned NULL", TEST_PROVIDER_NAME); + ep_raise_error (); + } + + test_location = 2; + + EventPipeProvider *test_provider2 = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + if (test_provider2) { + result = FAILED ("Creating an already existing provider %s, succeeded", TEST_PROVIDER_NAME); + ep_raise_error (); + } + + test_location = 3; + + returned_test_provider = ep_get_provider (TEST_PROVIDER_NAME); + if (!returned_test_provider) { + result = FAILED ("Failed to get provider %s, ep_get_provider returned NULL", TEST_PROVIDER_NAME); + ep_raise_error (); + } + +ep_on_exit: + ep_delete_provider (test_provider); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + + +static RESULT +test_enable_disable (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSessionID session_id = 0; + EventPipeProviderConfiguration provider_config; + EventPipeProviderConfiguration *current_provider_config =ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, ""); + ep_raise_error_if_nok (current_provider_config != NULL); + + test_location = 1; + + session_id = ep_enable ( + TEST_FILE, + 1, + current_provider_config, + 1, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + false); + + if (!session_id) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 2; + + if (!ep_enabled ()) { + result = FAILED ("event pipe disabled"); + ep_raise_error (); + } + +ep_on_exit: + ep_disable (session_id); + ep_provider_config_fini (current_provider_config); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static bool provider_callback_data; + +static +void +provider_callback ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_context) +{ + *(bool *)callback_context = true; +} + +static RESULT +test_create_delete_provider_with_callback (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSessionID session_id = 0; + EventPipeProvider *test_provider = NULL; + EventPipeProviderConfiguration provider_config; + + EventPipeProviderConfiguration *current_provider_config =ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, ""); + ep_raise_error_if_nok (current_provider_config != NULL); + + test_location = 1; + + session_id = ep_enable ( + TEST_FILE, + 1, + current_provider_config, + 1, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + false); + + if (!session_id) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 2; + + test_provider = ep_create_provider (TEST_PROVIDER_NAME, provider_callback, &provider_callback_data); + ep_raise_error_if_nok (test_provider != NULL); + + test_location = 3; + + if (!provider_callback_data) { + result = FAILED ("Provider callback not called"); + ep_raise_error (); + } + +ep_on_exit: + ep_delete_provider (test_provider); + ep_disable (session_id); + ep_provider_config_fini (current_provider_config); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_build_event_metadata (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeProvider *provider = NULL; + EventPipeEvent *ep_event = NULL; + EventPipeEventInstance *ep_event_instance = NULL; + EventPipeEventMetadataEvent *metadata_event = NULL; + + provider = ep_create_provider (TEST_PROVIDER_NAME, NULL, NULL); + ep_raise_error_if_nok (provider != NULL); + + test_location = 1; + + ep_event = ep_event_alloc (provider, 1, 1, 1, EP_EVENT_LEVEL_VERBOSE, false, NULL, 0); + ep_raise_error_if_nok (ep_event != NULL); + + test_location = 2; + + ep_event_instance = ep_event_instance_alloc (ep_event, 0, 0, NULL, 0, NULL, NULL); + ep_raise_error_if_nok (ep_event_instance != NULL); + + test_location = 3; + + metadata_event = ep_build_event_metadata_event (ep_event_instance, 1); + ep_raise_error_if_nok (metadata_event != NULL); + + test_location = 4; + +ep_on_exit: + ep_delete_provider (provider); + ep_event_free (ep_event); + ep_event_instance_free (ep_event_instance); + ep_event_metdata_event_free (metadata_event); + + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_start_session_streaming (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSessionID session_id = 0; + EventPipeProviderConfiguration provider_config; + + EventPipeProviderConfiguration *current_provider_config =ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOG_ALWAYS, ""); + ep_raise_error_if_nok (current_provider_config != NULL); + + test_location = 1; + + session_id = ep_enable ( + TEST_FILE, + 1, + current_provider_config, + 1, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + false); + + if (!session_id) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 2; + + ep_start_streaming (session_id); + +ep_on_exit: + ep_disable (session_id); + ep_provider_config_fini (current_provider_config); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_eventpipe_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_end_snapshot); + if ( _CrtMemDifference( &eventpipe_memory_diff_snapshot, &eventpipe_memory_start_snapshot, &eventpipe_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &eventpipe_memory_diff_snapshot ); + return FAILED ("Memory leak detected!"); + } +#endif + return NULL; +} + +static Test ep_tests [] = { + {"test_eventpipe_setup", test_eventpipe_setup}, + {"test_create_delete_provider", test_create_delete_provider}, + {"test_stress_create_delete_provider", test_stress_create_delete_provider}, + {"test_get_provider", test_get_provider}, + {"test_create_same_provider_twice", test_create_same_provider_twice}, + {"test_enable_disable", test_enable_disable}, + {"test_create_delete_provider_with_callback", test_create_delete_provider_with_callback}, + {"test_build_event_metadata", test_build_event_metadata}, + {"test_start_session_streaming", test_start_session_streaming}, + {"test_eventpipe_teardown", test_eventpipe_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_tests_init, ep_tests) diff --git a/src/mono/mono/eventpipe/test/ep-tests.h b/src/mono/mono/eventpipe/test/ep-tests.h new file mode 100644 index 0000000000000..c8e56be313a6e --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-tests.h @@ -0,0 +1,30 @@ +#ifndef _EVENTPIPE_TESTS_H +#define _EVENTPIPE_TESTS_H + +#include "eglib/test/test.h" + +DEFINE_TEST_GROUP_INIT_H(ep_setup_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_fastserializer_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_provider_callback_data_queue_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_file_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_session_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_thread_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_tests_init); +DEFINE_TEST_GROUP_INIT_H(fake_tests_init); +DEFINE_TEST_GROUP_INIT_H(ep_teardown_tests_init); + +const +static Group test_groups [] = { + {"setup", ep_setup_tests_init}, + {"fastserialzier", ep_fastserializer_tests_init}, + {"provider-callback-dataqueue", ep_provider_callback_data_queue_tests_init}, + {"file", ep_file_tests_init}, + {"session", ep_session_tests_init}, + {"thread", ep_thread_tests_init}, + {"eventpipe", ep_tests_init}, + {"fake", fake_tests_init}, + {"teardown", ep_teardown_tests_init}, + {NULL, NULL} +}; + +#endif /* _EVENTPIPE_TESTS_H */ diff --git a/src/mono/mono/eventpipe/test/ep-thread-tests.c b/src/mono/mono/eventpipe/test/ep-thread-tests.c new file mode 100644 index 0000000000000..9f68befe532a0 --- /dev/null +++ b/src/mono/mono/eventpipe/test/ep-thread-tests.c @@ -0,0 +1,478 @@ +#include "mono/eventpipe/ep.h" +#include "eglib/test/test.h" + +#define TEST_FILE "./ep_test_create_file.txt" + +#ifdef _CRTDBG_MAP_ALLOC +static _CrtMemState eventpipe_memory_start_snapshot; +static _CrtMemState eventpipe_memory_end_snapshot; +static _CrtMemState eventpipe_memory_diff_snapshot; +#endif + +static RESULT +test_thread_setup (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_start_snapshot); +#endif + return NULL; +} + +static RESULT +test_create_free_thread (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeThread *thread = ep_thread_alloc (); + if (!thread) { + result = FAILED ("Failed to create thread"); + ep_raise_error (); + } + +ep_on_exit: + ep_thread_free (thread); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_addref_release_thread (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeThread *thread = ep_thread_alloc (); + if (!thread) { + result = FAILED ("Failed to create thread"); + ep_raise_error (); + } + + test_location = 1; + + if (ep_rt_volatile_load_uint32_t ((const volatile uint32_t *)ep_thread_get_ref_count_ref (thread)) != 0) { + result = FAILED ("Ref count should start at 0"); + ep_raise_error (); + } + + test_location = 2; + + ep_thread_addref (thread); + + if (ep_rt_volatile_load_uint32_t ((const volatile uint32_t *)ep_thread_get_ref_count_ref (thread)) != 1) { + result = FAILED ("addref should increment 1"); + ep_raise_error (); + } + + test_location = 3; + + ep_thread_release (thread); + thread = NULL; + +ep_on_exit: + ep_thread_free (thread); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_get_or_create_thread (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeThread *thread = ep_thread_get (); + if (thread) { + result = FAILED ("ep_thread_get should return NULL"); + ep_raise_error (); + } + + test_location = 1; + + thread = ep_thread_get_or_create (); + if (!thread) { + result = FAILED ("ep_thread_get_or_create should not return NULL"); + ep_raise_error (); + } + + test_location = 2; + + thread = ep_thread_get (); + if (!thread) { + result = FAILED ("ep_thread_get should not return NULL"); + ep_raise_error (); + } + + test_location = 3; + + if (ep_rt_volatile_load_uint32_t ((const volatile uint32_t *)ep_thread_get_ref_count_ref (thread)) != 1) { + result = FAILED ("thread ref count should be 1"); + ep_raise_error (); + } + + test_location = 4; + + // Need to emulate a thread exit to make sure TLS gets cleaned up for current thread + // or we will get memory leaks reported. + ep_rt_mono_thread_exited (); + + thread = ep_thread_get (); + if (thread) { + result = FAILED ("ep_thread_get should return NULL"); + ep_raise_error (); + } + +ep_on_exit: + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_thread_activity_id (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + uint8_t empty_id [EP_ACTIVITY_ID_SIZE] = {0}; + uint8_t current_activity_id [EP_ACTIVITY_ID_SIZE]; + uint8_t new_activity_id [EP_ACTIVITY_ID_SIZE]; + + ep_thread_create_activity_id (new_activity_id, sizeof (new_activity_id)); + if (!memcmp (empty_id, new_activity_id, sizeof (new_activity_id))) { + result = FAILED ("Created activity id is empty"); + ep_raise_error (); + } + + test_location = 1; + + EventPipeThread *thread = ep_thread_get (); + if (thread) { + result = FAILED ("ep_thread_get should return NULL"); + ep_raise_error (); + } + + test_location = 2; + + thread = ep_thread_get_or_create (); + if (!thread) { + result = FAILED ("ep_thread_get_or_create should not return NULL"); + ep_raise_error (); + } + + test_location = 3; + + ep_thread_get_activity_id (thread, current_activity_id, sizeof (current_activity_id)); + if (memcmp (empty_id, current_activity_id, sizeof (current_activity_id))) { + result = FAILED ("Current activity id is not empty"); + ep_raise_error (); + } + + test_location = 4; + + ep_thread_set_activity_id (thread, new_activity_id, sizeof (new_activity_id)); + + ep_thread_get_activity_id (thread, current_activity_id, sizeof (current_activity_id)); + if (memcmp (new_activity_id, current_activity_id, sizeof (current_activity_id))) { + result = FAILED ("Current activity id doesn't match previously set activity id"); + ep_raise_error (); + } + + test_location = 5; + + // Need to emulate a thread exit to make sure TLS gets cleaned up for current thread + // or we will get memory leaks reported. + ep_rt_mono_thread_exited (); + + thread = ep_thread_get (); + if (thread) { + result = FAILED ("ep_thread_get should return NULL"); + ep_raise_error (); + } + +ep_on_exit: + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_thread_is_rundown_thread (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeThread *thread = ep_thread_alloc (); + if (!thread) { + result = FAILED ("Failed to create thread"); + ep_raise_error (); + } + + test_location = 1; + + if (ep_thread_is_rundown_thread (thread)) { + result = FAILED ("Thread is a rundown thread"); + ep_raise_error (); + } + + test_location = 2; + + EventPipeSession dummy_session; + ep_thread_set_as_rundown_thread (thread, &dummy_session); + if (!ep_thread_is_rundown_thread (thread)) { + result = FAILED ("Thread is not a rundown thread"); + ep_raise_error (); + } + + test_location = 3; + + if (ep_thread_get_rundown_session (thread) != &dummy_session) { + result = FAILED ("Unexpected rundown session"); + ep_raise_error (); + } + + test_location = 4; + + ep_thread_set_as_rundown_thread (thread, NULL); + + if (ep_thread_is_rundown_thread (thread)) { + result = FAILED ("Thread is a rundown thread"); + ep_raise_error (); + } + +ep_on_exit: + ep_thread_free (thread); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_thread_lock (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeThread *thread = ep_thread_alloc (); + if (!thread) { + result = FAILED ("Failed to create thread"); + ep_raise_error (); + } + + test_location = 1; + + ep_thread_requires_lock_not_held (thread); + + ep_rt_spin_lock_aquire (ep_thread_get_rt_lock_ref (thread)); + + ep_thread_requires_lock_held (thread); + + ep_rt_spin_lock_release (ep_thread_get_rt_lock_ref (thread)); + + ep_thread_requires_lock_not_held (thread); + +ep_on_exit: + ep_thread_free (thread); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_thread_session_write (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeThread *thread = ep_thread_alloc (); + if (!thread) { + result = FAILED ("Failed to create thread"); + ep_raise_error (); + } + + test_location = 1; + + uint32_t session_write = ep_thread_get_session_write_in_progress (thread); + if (session_write) { + result = FAILED ("Session write is in progress"); + ep_raise_error (); + } + + test_location = 2; + + ep_thread_set_session_write_in_progress (thread, 1); + + session_write = ep_thread_get_session_write_in_progress (thread); + if (session_write != 1) { + result = FAILED ("Wrong session id in write progress"); + ep_raise_error (); + } + + test_location = 3; + + ep_thread_set_session_write_in_progress (thread, 0); + + session_write = ep_thread_get_session_write_in_progress (thread); + if (session_write) { + result = FAILED ("Session write is in progress"); + ep_raise_error (); + } + +ep_on_exit: + ep_thread_free (thread); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_thread_session_state (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + EventPipeThread *thread = NULL; + EventPipeProviderConfiguration *provider_config = NULL; + EventPipeSession *session = NULL; + EventPipeThreadSessionState *session_state = NULL; + + thread = ep_thread_alloc (); + if (!thread) { + result = FAILED ("Failed to create thread"); + ep_raise_error (); + } + + ep_thread_addref (thread); + + test_location = 1; + + { + EventPipeProviderConfiguration dummy_config; + if (!ep_provider_config_init (&dummy_config, "DummyProvider", 0, 0, "")) { + result = FAILED ("Failed to init provider config"); + ep_raise_error (); + } + provider_config = &dummy_config; + } + + test_location = 2; + + EP_CONFIG_LOCK_ENTER + session = ep_session_alloc ( + 1, + TEST_FILE, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + 1, + provider_config, + 1, + false); + EP_CONFIG_LOCK_EXIT + + if (!session) { + result = FAILED ("Failed to alloc session"); + ep_raise_error (); + } + + test_location = 3; + + ep_rt_spin_lock_aquire (ep_thread_get_rt_lock_ref (thread)); + session_state = ep_thread_get_or_create_session_state (thread, session); + ep_rt_spin_lock_release (ep_thread_get_rt_lock_ref (thread)); + + if (!session_state) { + result = FAILED ("Failed to alloc session state"); + ep_raise_error (); + } + + test_location = 4; + + ep_rt_spin_lock_aquire (ep_thread_get_rt_lock_ref (thread)); + EventPipeThreadSessionState *current_session_state = ep_thread_get_or_create_session_state (thread, session); + ep_rt_spin_lock_release (ep_thread_get_rt_lock_ref (thread)); + + if (current_session_state != session_state) { + result = FAILED ("Second call to get_or_create_session_state allocated new session_state"); + ep_raise_error (); + } + + test_location = 5; + + ep_rt_spin_lock_aquire (ep_thread_get_rt_lock_ref (thread)); + current_session_state = ep_thread_get_session_state (thread, session); + ep_rt_spin_lock_release (ep_thread_get_rt_lock_ref (thread)); + + if (current_session_state != session_state) { + result = FAILED ("Call to get_session_state allocated returned unexpected session"); + ep_raise_error (); + } + +ep_on_exit: + if (thread && session_state) { + ep_rt_spin_lock_aquire (ep_thread_get_rt_lock_ref (thread)); + ep_thread_delete_session_state (thread, session); + ep_rt_spin_lock_release (ep_thread_get_rt_lock_ref (thread)); + } + ep_session_free (session); + ep_provider_config_fini (provider_config); + ep_thread_release (thread); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT +test_thread_teardown (void) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtMemCheckpoint (&eventpipe_memory_end_snapshot); + if ( _CrtMemDifference( &eventpipe_memory_diff_snapshot, &eventpipe_memory_start_snapshot, &eventpipe_memory_end_snapshot) ) { + _CrtMemDumpStatistics( &eventpipe_memory_diff_snapshot ); + return FAILED ("Memory leak detected!"); + } +#endif + return NULL; +} + +static Test ep_thread_tests [] = { + {"test_thread_setup", test_thread_setup}, + {"test_create_free_thread", test_create_free_thread}, + {"test_addref_release_thread", test_addref_release_thread}, + {"test_get_or_create_thread", test_get_or_create_thread}, + {"test_thread_activity_id", test_thread_activity_id}, + {"test_thread_is_rundown_thread", test_thread_is_rundown_thread}, + {"test_thread_lock", test_thread_lock}, + {"test_thread_session_write", test_thread_session_write}, + {"test_thread_session_state", test_thread_session_state}, + {"test_thread_teardown", test_thread_teardown}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ep_thread_tests_init, ep_thread_tests) diff --git a/src/mono/mono/metadata/Makefile.am b/src/mono/mono/metadata/Makefile.am index 0415d87bee410..d9ad09f5cca39 100644 --- a/src/mono/mono/metadata/Makefile.am +++ b/src/mono/mono/metadata/Makefile.am @@ -91,6 +91,10 @@ if !ENABLE_ILGEN ilgen_libraries = libmono-ilgen.la endif +if ENABLE_PERFTRACING +eventpipe_libs = $(top_builddir)/mono/eventpipe/libeventpipe.la +endif + BUNDLE_ZLIB_PATH=$(top_builddir)/mono/zlib/libz.la if HAVE_STATIC_ZLIB @@ -103,7 +107,7 @@ Z_LIBS=$(BUNDLE_ZLIB_PATH) endif endif -noinst_LTLIBRARIES = libmonoruntime-config.la $(support_libraries) $(boehm_libraries) $(sgen_libraries) +noinst_LTLIBRARIES = libmonoruntime-config.la $(support_libraries) $(boehm_libraries) $(sgen_libraries) $(shim_libraries) lib_LTLIBRARIES = $(icall_table_libraries) $(ilgen_libraries) @@ -136,6 +140,26 @@ libmonoruntime_support_la_SOURCES = support.c libmonoruntime_support_la_LDFLAGS = $(Z_LIBS) libmonoruntime_support_la_CFLAGS = $(filter-out @CXX_REMOVE_CFLAGS@, @CFLAGS@) @ZLIB_CFLAGS@ +if ENABLE_NETCORE +if HAVE_SYS_ICU +shim_libraries = libmonoruntime-shimglobalization.la + +nodist_libmonoruntime_shimglobalization_la_SOURCES = \ + @ICU_SHIM_PATH@/pal_calendarData.c \ + @ICU_SHIM_PATH@/pal_casing.c \ + @ICU_SHIM_PATH@/pal_collation.c \ + @ICU_SHIM_PATH@/pal_idna.c \ + @ICU_SHIM_PATH@/pal_locale.c \ + @ICU_SHIM_PATH@/pal_localeNumberData.c \ + @ICU_SHIM_PATH@/pal_localeStringData.c \ + @ICU_SHIM_PATH@/pal_normalization.c \ + @ICU_SHIM_PATH@/pal_timeZoneInfo.c \ + @ICU_SHIM_PATH@/pal_icushim.c + +libmonoruntime_shimglobalization_la_CFLAGS = @ICU_CFLAGS@ -I$(top_srcdir)/../libraries/Native/Unix/Common/ +endif +endif + # # This library contains the icall tables if the runtime was configured with --disable-icall-tables # @@ -149,7 +173,7 @@ if BITCODE if WASM libmono_icall_table_la_LIBADD = # empty to avoid duplicate symbols when enabling dynamic linking else -libmono_icall_table_la_LIBADD = $(glib_libs) ../utils/libmonoutils.la ../sgen/libmonosgen.la libmonoruntimesgen.la +libmono_icall_table_la_LIBADD = $(glib_libs) ../utils/libmonoutils.la ../sgen/libmonosgen.la $(eventpipe_libs) libmonoruntimesgen.la endif endif endif @@ -173,7 +197,7 @@ if BITCODE if WASM libmono_ilgen_la_LIBADD = # empty to avoid duplicate symbols when enabling dynamic linking else -libmono_ilgen_la_LIBADD = $(glib_libs) ../utils/libmonoutils.la ../sgen/libmonosgen.la libmonoruntimesgen.la +libmono_ilgen_la_LIBADD = $(glib_libs) ../utils/libmonoutils.la ../sgen/libmonosgen.la $(eventpipe_libs) libmonoruntimesgen.la endif endif endif @@ -240,6 +264,7 @@ common_sources = \ domain-internals.h \ environment.c \ environment.h \ + icall-eventpipe.c \ exception.c \ exception.h \ exception-internals.h \ @@ -424,12 +449,12 @@ if !ENABLE_MSVC_ONLY libmonoruntime_la_SOURCES = $(common_sources) $(icall_tables_sources) $(ilgen_sources) $(gc_dependent_sources) $(null_gc_sources) $(boehm_sources) # Add CXX_ADD_CFLAGS per-library until/unless https://github.com/dotnet/corefx/pull/31342. libmonoruntime_la_CFLAGS = $(BOEHM_DEFINES) @CXX_ADD_CFLAGS@ -libmonoruntime_la_LIBADD = libmonoruntime-config.la $(support_libraries) +libmonoruntime_la_LIBADD = libmonoruntime-config.la $(support_libraries) $(shim_libraries) libmonoruntimesgen_la_SOURCES = $(common_sources) $(icall_tables_sources) $(ilgen_sources) $(gc_dependent_sources) $(sgen_sources) # Add CXX_ADD_CFLAGS per-library until/unless https://github.com/dotnet/corefx/pull/31342. libmonoruntimesgen_la_CFLAGS = $(SGEN_DEFINES) @CXX_ADD_CFLAGS@ -libmonoruntimesgen_la_LIBADD = libmonoruntime-config.la $(support_libraries) +libmonoruntimesgen_la_LIBADD = libmonoruntime-config.la $(support_libraries) $(shim_libraries) endif # !ENABLE_MSVC_ONLY diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index d503e3e5c0b07..f00ea0345beeb 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -828,9 +828,6 @@ mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext * gpointer mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error); -gpointer -mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper, MonoError *error); - gpointer mono_runtime_create_delegate_trampoline (MonoClass *klass); diff --git a/src/mono/mono/metadata/debug-mono-ppdb.c b/src/mono/mono/metadata/debug-mono-ppdb.c index 28c78c237b0e0..a5634f6c1e4cd 100644 --- a/src/mono/mono/metadata/debug-mono-ppdb.c +++ b/src/mono/mono/metadata/debug-mono-ppdb.c @@ -497,7 +497,7 @@ mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrAr if (source_files) sindexes = g_ptr_array_new (); - if (!method->token) + if (!method->token || tables [MONO_TABLE_METHODBODY].rows == 0) return; method_idx = mono_metadata_token_index (method->token); diff --git a/src/mono/mono/metadata/icall-eventpipe.c b/src/mono/mono/metadata/icall-eventpipe.c new file mode 100644 index 0000000000000..9f64e90cc44db --- /dev/null +++ b/src/mono/mono/metadata/icall-eventpipe.c @@ -0,0 +1,489 @@ +#include +#include +#include + +#ifdef ENABLE_NETCORE +#include + +#ifdef ENABLE_PERFTRACING +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef enum _EventPipeActivityControlCode { + EP_ACTIVITY_CONTROL_GET_ID = 1, + EP_ACTIVITY_CONTROL_SET_ID = 2, + EP_ACTIVITY_CONTROL_CREATE_ID = 3, + EP_ACTIVITY_CONTROL_GET_SET_ID = 4, + EP_ACTIVITY_CONTROL_CREATE_SET_ID = 5 +} EventPipeActivityControlCode; + +typedef struct _EventPipeProviderConfigurationNative { + gunichar2 *provider_name; + uint64_t keywords; + uint32_t logging_level; + gunichar2 *filter_data; +} EventPipeProviderConfigurationNative; + +typedef struct _EventProviderEventData { + uint64_t ptr; + uint32_t size; + uint32_t reserved; +} EventProviderEventData; + +typedef struct _EventPipeSessionInfo { + int64_t starttime_as_utc_filetime; + int64_t start_timestamp; + int64_t timestamp_frequency; +} EventPipeSessionInfo; + +typedef struct _EventPipeEventInstanceData { + intptr_t provider_id; + uint32_t event_id; + uint32_t thread_id; + int64_t timestamp; + uint8_t activity_id [EP_ACTIVITY_ID_SIZE]; + uint8_t related_activity_id [EP_ACTIVITY_ID_SIZE]; + const uint8_t *payload; + uint32_t payload_len; +} EventPipeEventInstanceData; + +gboolean ep_rt_mono_initialized; +MonoNativeTlsKey ep_rt_mono_thread_holder_tls_id; +gpointer ep_rt_mono_rand_provider; + +static ep_rt_thread_holder_alloc_func thread_holder_alloc_callback_func; +static ep_rt_thread_holder_free_func thread_holder_free_callback_func; + +void +mono_eventpipe_raise_thread_exited (uint64_t); + +static +gboolean +rand_try_get_bytes_func (guchar *buffer, gssize buffer_size, MonoError *error) +{ + g_assert (ep_rt_mono_rand_provider != NULL); + return mono_rand_try_get_bytes (&ep_rt_mono_rand_provider, buffer, buffer_size, error); +} + +static +EventPipeThread * +eventpipe_thread_get (void) +{ + EventPipeThreadHolder *thread_holder = mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id); + return thread_holder ? ep_thread_holder_get_thread (thread_holder) : NULL; +} + +static +EventPipeThread * +eventpipe_thread_get_or_create (void) +{ + EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id); + if (!thread_holder && thread_holder_alloc_callback_func) { + thread_holder = thread_holder_alloc_callback_func (); + mono_native_tls_set_value (ep_rt_mono_thread_holder_tls_id, thread_holder); + } + return ep_thread_holder_get_thread (thread_holder); +} + +static +void +eventpipe_thread_exited (void) +{ + if (ep_rt_mono_initialized) { + EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id); + if (thread_holder && thread_holder_free_callback_func) + thread_holder_free_callback_func (thread_holder); + mono_native_tls_set_value (ep_rt_mono_thread_holder_tls_id, NULL); + } +} + +static +void +profiler_eventpipe_thread_exited (MonoProfiler *prof, uintptr_t tid) +{ + eventpipe_thread_exited (); +} + +void +mono_eventpipe_init ( + EventPipeMonoFuncTable *table, + ep_rt_thread_holder_alloc_func thread_holder_alloc_func, + ep_rt_thread_holder_free_func thread_holder_free_func) +{ + g_assert (table != NULL); + table->ep_rt_mono_100ns_datetime = mono_100ns_datetime; + table->ep_rt_mono_100ns_ticks = mono_100ns_ticks; + table->ep_rt_mono_cpu_count = mono_cpu_count; + table->ep_rt_mono_process_current_pid = mono_process_current_pid; + table->ep_rt_mono_native_thread_id_get = mono_native_thread_id_get; + table->ep_rt_mono_native_thread_id_equals = mono_native_thread_id_equals; + table->ep_rt_mono_runtime_is_shutting_down = mono_runtime_is_shutting_down; + table->ep_rt_mono_rand_try_get_bytes = rand_try_get_bytes_func; + table->ep_rt_mono_thread_get = eventpipe_thread_get; + table->ep_rt_mono_thread_get_or_create = eventpipe_thread_get_or_create; + table->ep_rt_mono_thread_exited = eventpipe_thread_exited; + table->ep_rt_mono_w32file_close = mono_w32file_close; + table->ep_rt_mono_w32file_create = mono_w32file_create; + table->ep_rt_mono_w32file_write = mono_w32file_write; + + thread_holder_alloc_callback_func = thread_holder_alloc_func; + thread_holder_free_callback_func = thread_holder_free_func; + mono_native_tls_alloc (&ep_rt_mono_thread_holder_tls_id, NULL); + + mono_100ns_ticks (); + mono_rand_open (); + ep_rt_mono_rand_provider = mono_rand_init (NULL, 0); + + ep_rt_mono_initialized = TRUE; + + MonoProfilerHandle profiler = mono_profiler_create (NULL); + mono_profiler_set_thread_stopped_callback (profiler, profiler_eventpipe_thread_exited); +} + +void +mono_eventpipe_fini (void) +{ + if (ep_rt_mono_initialized) + mono_rand_close (ep_rt_mono_rand_provider); + + ep_rt_mono_rand_provider = NULL; + thread_holder_alloc_callback_func = NULL; + thread_holder_free_callback_func = NULL; + ep_rt_mono_initialized = FALSE; +} + +gconstpointer +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_CreateProvider ( + MonoStringHandle provider_name, + MonoDelegateHandle callback_func, + MonoError *error) +{ + EventPipeProvider *provider = NULL; + + if (MONO_HANDLE_IS_NULL (provider_name)) { + mono_error_set_argument_null (error, "providerName", ""); + return NULL; + } + + char *provider_name_utf8 = mono_string_handle_to_utf8 (provider_name, error); + + //TODO: Need to pin delegate if we switch to safe mode or maybe we should get funcptr in icall? + provider = ep_create_provider (provider_name_utf8, MONO_HANDLE_GETVAL (callback_func, delegate_trampoline), NULL); + + g_free (provider_name_utf8); + return provider; +} + +intptr_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DefineEvent ( + intptr_t provider_handle, + uint32_t event_id, + int64_t keywords, + uint32_t event_version, + uint32_t level, + const uint8_t *metadata, + uint32_t metadata_len) +{ + g_assert (provider_handle != 0); + + EventPipeProvider *provider = (EventPipeProvider *)provider_handle; + EventPipeEvent *ep_event = ep_provider_add_event (provider, event_id, (uint64_t)keywords, event_version, (EventPipeEventLevel)level, /* needStack = */ true, metadata, metadata_len); + + g_assert (ep_event != NULL); + return (intptr_t)ep_event; +} + +void +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DeleteProvider (intptr_t provider_handle) +{ + if (provider_handle) { + ep_delete_provider ((EventPipeProvider *)provider_handle); + } +} + +void +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Disable (uint64_t session_id) +{ + ep_disable (session_id); +} + +uint64_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Enable ( + const gunichar2 *output_file, + /* EventPipeSerializationFormat */int32_t format, + uint32_t circular_buffer_size_mb, + /* EventPipeProviderConfigurationNative[] */const void *providers, + uint32_t providers_len) +{ + ERROR_DECL (error); + EventPipeSessionID session_id = 0; + + if (circular_buffer_size_mb == 0 || format > EP_SERIALIZATION_FORMAT_COUNT || providers_len == 0 || providers == NULL) + return 0; + + char *output_file_utf8 = mono_utf16_to_utf8 (output_file, g_utf16_len (output_file), error); + + session_id = ep_enable ( + output_file_utf8, + circular_buffer_size_mb, + providers, + providers_len, + output_file != NULL ? EP_SESSION_TYPE_FILE : EP_SESSION_TYPE_LISTENER, + (EventPipeSerializationFormat)format, + true, + NULL, + true); + ep_start_streaming (session_id); + + g_free (output_file_utf8); + return session_id; +} + +int32_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_EventActivityIdControl ( + uint32_t control_code, + /* GUID * */uint8_t *activity_id) +{ + int32_t result = 0; + EventPipeThread *thread = ep_thread_get (); + + if (thread == NULL) + return 1; + + uint8_t current_activity_id [EP_ACTIVITY_ID_SIZE]; + EventPipeActivityControlCode activity_control_code = (EventPipeActivityControlCode)control_code; + switch (activity_control_code) { + case EP_ACTIVITY_CONTROL_GET_ID: + ep_thread_get_activity_id (thread, activity_id, EP_ACTIVITY_ID_SIZE); + break; + case EP_ACTIVITY_CONTROL_SET_ID: + ep_thread_set_activity_id (thread, activity_id, EP_ACTIVITY_ID_SIZE); + break; + case EP_ACTIVITY_CONTROL_CREATE_ID: + ep_thread_create_activity_id (activity_id, EP_ACTIVITY_ID_SIZE); + break; + case EP_ACTIVITY_CONTROL_GET_SET_ID: + ep_thread_get_activity_id (thread, activity_id, EP_ACTIVITY_ID_SIZE); + ep_thread_create_activity_id (current_activity_id, G_N_ELEMENTS (current_activity_id)); + ep_thread_set_activity_id (thread, current_activity_id, G_N_ELEMENTS (current_activity_id)); + break; + default: + result = 1; + break; + } + + return result; +} + +MonoBoolean +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetNextEvent ( + uint64_t session_id, + /* EventPipeEventInstanceData * */void *instance) +{ + g_assert (instance != NULL); + + EventPipeEventInstance *const next_instance = ep_get_next_event (session_id); + EventPipeEventInstanceData *const data = (EventPipeEventInstanceData *)instance; + if (next_instance && data) { + const EventPipeEvent *const ep_event = ep_event_instance_get_ep_event (next_instance); + if (ep_event) { + data->provider_id = (intptr_t)ep_event_get_provider (ep_event); + data->event_id = ep_event_get_event_id (ep_event); + } + data->thread_id = ep_event_instance_get_thread_id (next_instance); + data->timestamp = ep_event_instance_get_timestamp (next_instance); + memcpy (&data->activity_id, ep_event_instance_get_activity_id_cref (next_instance), EP_ACTIVITY_ID_SIZE); + memcpy (&data->related_activity_id, ep_event_instance_get_related_activity_id_cref (next_instance), EP_ACTIVITY_ID_SIZE); + data->payload = ep_event_instance_get_data (next_instance); + data->payload_len = ep_event_instance_get_data_len (next_instance); + } + + return next_instance != NULL; +} + +intptr_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetProvider (const gunichar2 *provider_name) +{ + ERROR_DECL (error); + char * provider_name_utf8 = NULL; + EventPipeProvider *provider = NULL; + + if (provider_name) { + provider_name_utf8 = mono_utf16_to_utf8 (provider_name, g_utf16_len (provider_name), error); + provider = ep_get_provider (provider_name_utf8); + } + + g_free (provider_name_utf8); + return (intptr_t)provider; +} + +MonoBoolean +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetSessionInfo ( + uint64_t session_id, + /* EventPipeSessionInfo * */void *session_info) +{ + bool result = false; + if (session_info) { + EventPipeSession *session = ep_get_session ((EventPipeSessionID)session_id); + if (session) { + EventPipeSessionInfo *instance = (EventPipeSessionInfo *)session_info; + instance->starttime_as_utc_filetime = ep_session_get_session_start_time (session); + instance->start_timestamp = ep_session_get_session_start_timestamp (session); + instance->timestamp_frequency = ep_perf_frequency_query (); + result = true; + } + } + + return result; +} + +intptr_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t session_id) +{ + return (intptr_t)ep_get_wait_handle (session_id); +} + +void +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData ( + intptr_t event_handle, + /* EventProviderEventData[] */const void *event_data, + uint32_t data_len, + /* GUID * */const uint8_t *activity_id, + /* GUID * */const uint8_t *related_activity_id) +{ + ; +} + +#else /* ENABLE_PERFTRACING */ + +gconstpointer +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_CreateProvider ( + MonoStringHandle provider_name, + MonoDelegateHandle callback_func, + MonoError *error) +{ + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.CreateProvider"); + return NULL; +} + +intptr_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DefineEvent ( + intptr_t provider_handle, + uint32_t event_id, + int64_t keywords, + uint32_t event_version, + uint32_t level, + const uint8_t *metadata, + uint32_t metadata_len) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.DefineEvent"); + mono_error_set_pending_exception (error); + return 0; +} + +void +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DeleteProvider (intptr_t provider_handle) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.DeleteProvider"); + mono_error_set_pending_exception (error); +} + +void +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Disable (uint64_t session_id) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.Disable"); + mono_error_set_pending_exception (error); +} + +uint64_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Enable ( + const gunichar2 *output_file, + /* EventPipeSerializationFormat */int32_t format, + uint32_t circular_buffer_size_mb, + /* EventPipeProviderConfigurationNative[] */const void *providers, + uint32_t providers_len) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.Enable"); + mono_error_set_pending_exception (error); + return 0; +} + +int32_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_EventActivityIdControl ( + uint32_t control_code, + /* GUID * */uint8_t *activity_id) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.EventActivityIdControl"); + mono_error_set_pending_exception (error); + return 0; +} + +MonoBoolean +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetNextEvent ( + uint64_t session_id, + /* EventPipeEventInstanceData * */void *instance) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.GetNextEvent"); + mono_error_set_pending_exception (error); + return FALSE; +} + +intptr_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetProvider (const gunichar2 *provider_name) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.GetProvider"); + mono_error_set_pending_exception (error); + return 0; +} + +MonoBoolean +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetSessionInfo ( + uint64_t session_id, + /* EventPipeSessionInfo * */void *session_info) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.GetSessionInfo"); + mono_error_set_pending_exception (error); + return FALSE; +} + +intptr_t +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t session_id) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.GetWaitHandle"); + mono_error_set_pending_exception (error); + return 0; +} + +void +ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData ( + intptr_t event_handle, + /* EventProviderEventData[] */const void *event_data, + uint32_t data_len, + /* GUID * */const uint8_t *activity_id, + /* GUID * */const uint8_t *related_activity_id) +{ + ERROR_DECL (error); + mono_error_set_not_implemented (error, "System.Diagnostics.Tracing.EventPipeInternal.WriteEventData"); + mono_error_set_pending_exception (error); +} + +#endif /* ENABLE_PERFTRACING */ +#endif /* ENABLE_NETCORE */ + +MONO_EMPTY_SOURCE_FILE (eventpipe_rt_mono); diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 18c2c1e826711..c51006c362ed1 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -7310,7 +7310,7 @@ ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionTypeHandle ref_ return_val_if_nok (error, NULL_HANDLE); } - mono_delegate_ctor_with_method (delegate, target, NULL, method, error); + mono_delegate_ctor (delegate, target, NULL, method, error); return_val_if_nok (error, NULL_HANDLE); return delegate; } @@ -8427,115 +8427,6 @@ ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *volatile* cate mono_get_runtime_callbacks ()->debug_log (level, *category, *message); } -#ifdef ENABLE_NETCORE -#define EVENT_PIPE_DUMMY_PROVIDER_ID 1 -#define EVENT_PIPE_DUMMY_SESSION_ID 1 -#define EVENT_PIPE_DUMMY_EVENT_ID 1 -#define EVENT_PIPE_ERROR_SUCCESS 0 -#define EVENT_PIPE_INVALID_WAIT_HANDLE 0 - -typedef enum _EventPipeSerializationFormat{ - NetPerf, - NetTrace -} EventPipeSerializationFormat; - -typedef struct _EventPipeProviderConfigurationNative { - gunichar2 *provider_name; - uint64_t keywords; - uint32_t logging_level; - gunichar2 *filter_data; -} EventPipeProviderConfigurationNative; - -typedef struct _EventProviderEventData { - uint64_t ptr; - uint32_t size; - uint32_t reserved; -} EventProviderEventData; - -typedef struct _EventPipeSessionInfo { - int64_t starttime_as_utc_filetime; - int64_t start_timestamp; - int64_t timestamp_frequency; -} EventPipeSessionInfo; - -typedef struct _EventPipeEventInstanceData { - intptr_t provider_id; - uint32_t event_id; - uint32_t thread_id; - int64_t timestamp; - uint8_t activity_id[16]; - uint8_t related_activity_id[16]; - const uint8_t *payload; - uint32_t payload_length; -} EventPipeEventInstanceData; - -gconstpointer -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_CreateProvider (MonoStringHandle provider_name, MonoDelegateHandle callback_func, MonoError *error) -{ - return GUINT_TO_POINTER (EVENT_PIPE_DUMMY_PROVIDER_ID); -} - -intptr_t -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DefineEvent (intptr_t prov_handle, uint32_t event_id, int64_t keywords, uint32_t event_version, uint32_t level, const uint8_t *metadata, uint32_t metadata_len) -{ - return EVENT_PIPE_DUMMY_EVENT_ID; -} - -void -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DeleteProvider (intptr_t prov_handle) -{ - ; -} - -void -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Disable (uint64_t session_id) -{ - ; -} - -uint64_t -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Enable (const_gunichar2_ptr output_file, /* EventPipeSerializationFormat */int32_t format, uint32_t circular_buffer_size_mb, /* EventPipeProviderConfigurationNative[] */const void *providers, uint32_t num_providers) -{ - return EVENT_PIPE_DUMMY_SESSION_ID; -} - -int32_t -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_EventActivityIdControl (uint32_t control_code, /* GUID * */uint8_t *activity_id) -{ - return EVENT_PIPE_ERROR_SUCCESS; -} - -MonoBoolean -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetNextEvent (uint64_t session_id, /* EventPipeEventInstanceData * */void *instance) -{ - return FALSE; -} - -intptr_t -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetProvider (const_gunichar2_ptr provider_name) -{ - return EVENT_PIPE_DUMMY_PROVIDER_ID; -} - -MonoBoolean -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetSessionInfo (uint64_t session_id, /* EventPipeSessionInfo * */void *session_info) -{ - return FALSE; -} - -intptr_t -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t session_id) -{ - return EVENT_PIPE_INVALID_WAIT_HANDLE; -} - -void -ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (intptr_t event_handle, /* EventProviderEventData[] */const void *event_data, uint32_t data_count, /* GUID * */const uint8_t *activity_id, /* GUID * */const uint8_t *related_activity_id) -{ - ; -} -#endif /* ENABLE_NETCORE */ - #ifndef HOST_WIN32 static inline void mono_icall_write_windows_debug_string (const gunichar2 *message) diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index 3d4d47c6c0177..0fda88735990c 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -2286,6 +2286,7 @@ mono_wrapper_caches_free (MonoWrapperCaches *cache) free_hash (cache->delegate_invoke_cache); free_hash (cache->delegate_begin_invoke_cache); free_hash (cache->delegate_end_invoke_cache); + free_hash (cache->delegate_bound_static_invoke_cache); free_hash (cache->runtime_invoke_signature_cache); free_hash (cache->delegate_abstract_invoke_cache); @@ -2430,7 +2431,6 @@ mono_image_close_except_pools (MonoImage *image) g_hash_table_destroy (image->name_cache); } - free_hash (image->delegate_bound_static_invoke_cache); free_hash (image->ldfld_wrapper_cache); free_hash (image->ldflda_wrapper_cache); free_hash (image->stfld_wrapper_cache); diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index 476376ce5d25f..07f6e7186c885 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -13,6 +13,16 @@ #include #include +#ifdef ENABLE_NETCORE +#if defined(TARGET_OSX) +#define MONO_LOADER_LIBRARY_NAME "libcoreclr.dylib" +#elif defined(TARGET_ANDROID) +#define MONO_LOADER_LIBRARY_NAME "libruntime-android.so" +#else +#define MONO_LOADER_LIBRARY_NAME "libcoreclr.so" +#endif +#endif + typedef struct _MonoLoadedImages MonoLoadedImages; typedef struct _MonoAssemblyLoadContext MonoAssemblyLoadContext; diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 95adfa6cbbaeb..30b6b55b506ba 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -512,7 +512,7 @@ mono_ftnptr_to_delegate_impl (MonoClass *klass, gpointer ftn, MonoError *error) gpointer compiled_ptr = mono_compile_method_checked (wrapper, error); goto_if_nok (error, leave); - mono_delegate_ctor_with_method (MONO_HANDLE_CAST (MonoObject, d), this_obj, compiled_ptr, wrapper, error); + mono_delegate_ctor (MONO_HANDLE_CAST (MonoObject, d), this_obj, compiled_ptr, wrapper, error); goto_if_nok (error, leave); } @@ -2228,7 +2228,11 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt return res; cache_key = method->klass; } else if (static_method_with_first_arg_bound) { - cache = get_cache (&get_method_image (target_method)->delegate_bound_static_invoke_cache, + GHashTable **cache_ptr; + + cache_ptr = &mono_method_get_wrapper_cache (target_method)->delegate_bound_static_invoke_cache; + + cache = get_cache (cache_ptr, (GHashFunc)mono_signature_hash, (GCompareFunc)mono_metadata_signature_equal); /* @@ -6264,6 +6268,36 @@ mono_marshal_asany_impl (MonoObjectHandle o, MonoMarshalNative string_encoding, return res; } + case MONO_TYPE_SZARRAY: { + //TODO: Implement structs and in-params for all value types + MonoClass *klass = t->data.klass; + MonoClass *eklass = m_class_get_element_class (klass); + MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o); + + // we only support char[] for in-params; we return a pointer to the managed heap here, and that's not 'in'-safe + if ((param_attrs & PARAM_ATTRIBUTE_IN) && eklass != mono_get_char_class ()) + break; + + if (m_class_get_rank (klass) > 1) + break; + + if (arr->bounds) + if (arr->bounds->lower_bound != 0) + break; + + if (mono_class_is_auto_layout (eklass)) + break; + + if (m_class_is_valuetype (eklass) && (mono_class_is_explicit_layout (eklass) || m_class_is_blittable (eklass) || m_class_is_enumtype (eklass))) + return arr->vector; + + if (eklass == mono_get_char_class ()) { + char *res = mono_utf16_to_utf8 ((mono_unichar2 *) arr->vector, arr->max_length, error); + return_val_if_nok (error, NULL); + return res; + } + break; + } default: break; } @@ -6324,6 +6358,20 @@ mono_marshal_free_asany_impl (MonoObjectHandle o, gpointer ptr, MonoMarshalNativ mono_marshal_free (ptr); break; } + case MONO_TYPE_SZARRAY: { + MonoClass *klass = t->data.klass; + MonoClass *eklass = m_class_get_element_class (klass); + MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o); + + if (eklass != mono_get_char_class ()) + break; + + mono_unichar2 *utf16_array = g_utf8_to_utf16 ((const char *)ptr, arr->max_length, NULL, NULL, NULL); + g_free (ptr); + memcpy (arr->vector, utf16_array, arr->max_length * sizeof (mono_unichar2)); + g_free (utf16_array); + break; + } default: break; } @@ -6548,8 +6596,8 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method) if (image->wrapper_caches.delegate_abstract_invoke_cache) g_hash_table_foreach_remove (image->wrapper_caches.delegate_abstract_invoke_cache, signature_pointer_pair_matches_pointer, method); // FIXME: Need to clear the caches in other images as well - if (image->delegate_bound_static_invoke_cache) - g_hash_table_remove (image->delegate_bound_static_invoke_cache, mono_method_signature_internal (method)); + if (image->wrapper_caches.delegate_bound_static_invoke_cache) + g_hash_table_remove (image->wrapper_caches.delegate_bound_static_invoke_cache, mono_method_signature_internal (method)); if (marshal_mutex_initialized) mono_marshal_unlock (); diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 30b7f4e78d3b6..561748a33842a 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -251,6 +251,7 @@ typedef struct { * indexed by SignaturePointerPair */ GHashTable *delegate_abstract_invoke_cache; + GHashTable *delegate_bound_static_invoke_cache; /* * indexed by MonoMethod pointers @@ -502,7 +503,6 @@ struct _MonoImage { /* * indexed by SignaturePointerPair */ - GHashTable *delegate_bound_static_invoke_cache; GHashTable *native_func_wrapper_cache; /* diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index 91b88a79f8b32..6b441a96e93ed 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -758,7 +758,7 @@ netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, c // We allow a special name to dlopen from the running process namespace, which is not present in CoreCLR if (strcmp (scope, "__Internal") == 0) { if (!internal_module) - internal_module = mono_dl_open (NULL, MONO_DL_LAZY, &error_msg); + internal_module = mono_dl_open_self (&error_msg); module = internal_module; if (!module) { @@ -1240,6 +1240,9 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou #endif #ifdef ENABLE_NETCORE +#ifndef HOST_WIN32 +retry_with_libcoreclr: +#endif // FIXME: these flags are not getting passed correctly module = netcore_lookup_native_library (alc, image, new_scope, 0); #else @@ -1262,6 +1265,13 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou addr = pinvoke_probe_for_symbol (module, piinfo, new_import, &error_msg); if (!addr) { +#if defined(ENABLE_NETCORE) && !defined(HOST_WIN32) + if (strcmp (new_scope, "__Internal") == 0) { + g_free ((char *)new_scope); + new_scope = g_strdup (MONO_LOADER_LIBRARY_NAME); + goto retry_with_libcoreclr; + } +#endif status_out->err_code = LOOKUP_PINVOKE_ERR_NO_SYM; status_out->err_arg = g_strdup (new_import); goto exit; diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index 9f7ef48a5ea82..ee34045d181ad 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -820,10 +820,9 @@ typedef struct { void (*set_cast_details) (MonoClass *from, MonoClass *to); void (*debug_log) (int level, MonoString *category, MonoString *message); gboolean (*debug_log_is_enabled) (void); - void (*init_delegate) (MonoDelegateHandle delegate, MonoError *error); + void (*init_delegate) (MonoDelegateHandle delegate, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error); MonoObject* (*runtime_invoke) (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error); void* (*compile_method) (MonoMethod *method, MonoError *error); - gpointer (*create_jump_trampoline) (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper, MonoError *error); gpointer (*create_jit_trampoline) (MonoDomain *domain, MonoMethod *method, MonoError *error); /* used to free a dynamic method */ void (*free_method) (MonoDomain *domain, MonoMethod *method); @@ -881,11 +880,8 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod * void mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args, MonoError *error); -gboolean -mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error); - -gboolean -mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error); +void +mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error); MonoMethod * mono_get_delegate_invoke_checked (MonoClass *klass, MonoError *error); diff --git a/src/mono/mono/metadata/object-offsets.h b/src/mono/mono/metadata/object-offsets.h index 9a36613866d77..82f901714646e 100644 --- a/src/mono/mono/metadata/object-offsets.h +++ b/src/mono/mono/metadata/object-offsets.h @@ -298,6 +298,14 @@ DECL_OFFSET(CallContext, stack_size) DECL_OFFSET(CallContext, stack) #endif +#if defined(TARGET_X86) +DECL_OFFSET(CallContext, eax) +DECL_OFFSET(CallContext, edx) +DECL_OFFSET(CallContext, fret) +DECL_OFFSET(CallContext, stack_size) +DECL_OFFSET(CallContext, stack) +#endif + #if defined(TARGET_X86) DECL_OFFSET(GSharedVtCallInfo, stack_usage) DECL_OFFSET(GSharedVtCallInfo, vret_slot) diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 952b2be7c1cc0..c9bacf3ad2aa6 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -802,18 +802,6 @@ mono_compile_method_checked (MonoMethod *method, MonoError *error) return res; } -gpointer -mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper, MonoError *error) -{ - gpointer res; - - MONO_REQ_GC_NEUTRAL_MODE; - - error_init (error); - res = callbacks.create_jump_trampoline (domain, method, add_sync_wrapper, error); - return res; -} - gpointer mono_runtime_create_delegate_trampoline (MonoClass *klass) { @@ -8714,7 +8702,7 @@ mono_print_unhandled_exception (MonoObject *exc) } /** - * mono_delegate_ctor_with_method: + * mono_delegate_ctor: * \param this pointer to an uninitialized delegate object * \param target target object * \param addr pointer to native code @@ -8724,82 +8712,22 @@ mono_print_unhandled_exception (MonoObject *exc) * associated with \p addr. This is useful when sharing generic code. * In that case \p addr will most probably not be associated with the * correct instantiation of the method. - * On failure returns FALSE and sets \p error. + * If \method is NULL, it is looked up using \addr in the JIT info tables. */ -gboolean -mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error) +void +mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; - error_init (error); MonoDelegateHandle delegate = MONO_HANDLE_CAST (MonoDelegate, this_obj); - g_assert (!MONO_HANDLE_IS_NULL (this_obj)); + UnlockedIncrement (&mono_stats.delegate_creations); MonoClass *klass = mono_handle_class (this_obj); g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class)); - if (method) - MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method); - - UnlockedIncrement (&mono_stats.delegate_creations); - - if (addr) - MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, addr); - -#ifndef DISABLE_REMOTING - if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) { - if (callbacks.interp_get_remoting_invoke) { - MONO_HANDLE_SETVAL (delegate, interp_method, gpointer, callbacks.interp_get_remoting_invoke (method, addr, error)); - } else { - g_assert (method); - method = mono_marshal_get_remoting_invoke (method, error); - return_val_if_nok (error, FALSE); - MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, mono_compile_method_checked (method, error)); - } - return_val_if_nok (error, FALSE); - } -#endif - - MONO_HANDLE_SET (delegate, target, target); - MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, callbacks.create_delegate_trampoline (MONO_HANDLE_DOMAIN (delegate), mono_handle_class (delegate))); - g_assert (callbacks.init_delegate); - callbacks.init_delegate (delegate, error); - return_val_if_nok (error, FALSE); - return TRUE; -} - -/** - * mono_delegate_ctor: - * \param this pointer to an uninitialized delegate object - * \param target target object - * \param addr pointer to native code - * \param error set on error. - * This is used to initialize a delegate. - * On failure returns FALSE and sets \p error. - */ -gboolean -mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error) -{ - MONO_REQ_GC_UNSAFE_MODE; - - error_init (error); - MonoDomain *domain = mono_domain_get (); - MonoJitInfo *ji; - MonoMethod *method = NULL; - - g_assert (addr); - - ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)); - /* Shared code */ - if (!ji && domain != mono_get_root_domain ()) - ji = mono_jit_info_table_find (mono_get_root_domain (), mono_get_addr_from_ftnptr (addr)); - if (ji) { - method = mono_jit_info_get_method (ji); - g_assert (!mono_class_is_gtd (method->klass)); - } - - return mono_delegate_ctor_with_method (this_obj, target, addr, method, error); + /* Done by the EE */ + callbacks.init_delegate (delegate, target, addr, method, error); } /** diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index c6f2d7fd3340a..c28ce829a4990 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -1958,7 +1958,7 @@ _mono_reflection_get_type_from_info (MonoAssemblyLoadContext *alc, MonoTypeNameP MonoAssemblyByNameRequest req; mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, alc); req.requesting_assembly = NULL; - req.basedir = image->assembly->basedir; + req.basedir = image ? image->assembly->basedir : NULL; assembly = mono_assembly_request_byname (&info->assembly, &req, NULL); if (!assembly) return NULL; diff --git a/src/mono/mono/mini/Makefile.am.in b/src/mono/mono/mini/Makefile.am.in index 4fa894984cc16..a8e9891def5b7 100755 --- a/src/mono/mono/mini/Makefile.am.in +++ b/src/mono/mono/mini/Makefile.am.in @@ -29,6 +29,10 @@ endif glib_libs = $(monodir)/mono/eglib/libeglib.la +if ENABLE_PERFTRACING +eventpipe_libs = $(monodir)/mono/eventpipe/libeventpipe.la +endif + boehm_libs= \ $(monodir)/mono/metadata/libmonoruntime.la \ $(monodir)/mono/utils/libmonoutils.la \ @@ -39,6 +43,7 @@ sgen_libs = \ $(monodir)/mono/metadata/libmonoruntimesgen.la \ $(monodir)/mono/sgen/libmonosgen.la \ $(monodir)/mono/utils/libmonoutils.la \ + $(eventpipe_libs) \ $(glib_libs) if ENABLE_LLVM diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 762a5a743fc29..adb9cab48538c 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -68,6 +68,7 @@ #include "mini-gc.h" #include "mini-llvm.h" #include "mini-runtime.h" +#include "interp/interp.h" static MonoMethod* try_get_method_nofail (MonoClass *klass, const char *method_name, int param_count, int flags) @@ -8608,7 +8609,7 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean if (gsharedvt_out && g_hash_table_lookup (acfg->gsharedvt_out_signatures, sig)) add_out = FALSE; - if (!add_in && !add_out) + if (!add_in && !add_out && !interp_in) return; if (mini_is_gsharedvt_variable_signature (sig)) @@ -8637,7 +8638,6 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean if (interp_in) { wrapper = mini_get_interp_in_wrapper (sig); add_extra_method (acfg, wrapper); - //printf ("X: %s\n", mono_method_full_name (wrapper, 1)); } #endif } @@ -8965,7 +8965,16 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) for (l = cfg->interp_in_signatures; l; l = l->next) { MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data); - add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE, FALSE); + /* + * Interpreter methods in llvmonly+interp mode are called using gsharedvt_in wrappers, + * since we already generate those in llvmonly mode. But methods with a large + * number of arguments need special processing (see interp_create_method_pointer_llvmonly), + * which only interp_in wrappers do. + */ + if (sig->param_count > MAX_INTERP_ENTRY_ARGS) + add_gsharedvt_wrappers (acfg, sig, FALSE, FALSE, TRUE); + else + add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE, FALSE); } } else if (mono_aot_mode_is_full (&acfg->aot_opts) && mono_aot_mode_is_interp (&acfg->aot_opts)) { /* The interpreter uses these wrappers to call aot-ed code */ diff --git a/src/mono/mono/mini/aot-runtime-wasm.c b/src/mono/mono/mini/aot-runtime-wasm.c index ccc5a26510c93..8f26a725abde7 100644 --- a/src/mono/mono/mini/aot-runtime-wasm.c +++ b/src/mono/mono/mini/aot-runtime-wasm.c @@ -63,13 +63,7 @@ type_to_c (MonoType *t) } } -#if TARGET_SIZEOF_VOID_P == 4 -#define FIDX(x) ((x) * 2) -#else #define FIDX(x) (x) -#endif - - typedef union { gint64 l; diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 1c04902fcc8d2..df3f5b614779c 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -148,6 +148,8 @@ struct MonoAotModule { guint32 *unbox_trampolines_end; guint32 *unbox_trampoline_addresses; guint8 *unwind_info; + /* Maps method index -> unbox tramp */ + gpointer *unbox_tramp_per_method; /* Points to the mono EH data created by LLVM */ guint8 *mono_eh_frame; @@ -5644,7 +5646,6 @@ read_page_trampoline_uwinfo (MonoTrampInfo *info, int tramp_type, gboolean is_ge static unsigned char* get_new_trampoline_from_page (int tramp_type) { - MonoImage *image; TrampolinePage *page; int count; void *tpage; @@ -6051,6 +6052,16 @@ mono_aot_get_unbox_trampoline (MonoMethod *method, gpointer addr) return mono_aot_get_unbox_arbitrary_trampoline (addr); } + if (!amodule->unbox_tramp_per_method) { + gpointer arr = g_new0 (gpointer, amodule->info.nmethods); + mono_memory_barrier (); + gpointer old_arr = mono_atomic_cas_ptr ((volatile gpointer*)&amodule->unbox_tramp_per_method, arr, NULL); + if (old_arr) + g_free (arr); + } + if (amodule->unbox_tramp_per_method [method_index]) + return amodule->unbox_tramp_per_method [method_index]; + if (amodule->info.llvm_unbox_tramp_indexes) { int unbox_tramp_idx; @@ -6069,6 +6080,10 @@ mono_aot_get_unbox_trampoline (MonoMethod *method, gpointer addr) g_assert (unbox_tramp_idx < amodule->info.llvm_unbox_tramp_num); code = ((gpointer*)(amodule->info.llvm_unbox_trampolines))[unbox_tramp_idx]; g_assert (code); + + mono_memory_barrier (); + amodule->unbox_tramp_per_method [method_index] = code; + return code; } @@ -6076,8 +6091,12 @@ mono_aot_get_unbox_trampoline (MonoMethod *method, gpointer addr) gpointer (*get_tramp) (int) = (gpointer (*)(int))amodule->info.llvm_get_unbox_tramp; code = get_tramp (method_index); - if (code) + if (code) { + mono_memory_barrier (); + amodule->unbox_tramp_per_method [method_index] = code; + return code; + } } ut = amodule->unbox_trampolines; @@ -6114,9 +6133,14 @@ mono_aot_get_unbox_trampoline (MonoMethod *method, gpointer addr) return FALSE; } + tinfo->method = method; tinfo->code_size = *(guint32*)symbol_addr; + tinfo->unwind_ops = mono_arch_get_cie_program (); mono_aot_tramp_info_register (tinfo, NULL); + mono_memory_barrier (); + amodule->unbox_tramp_per_method [method_index] = code; + /* The caller expects an ftnptr */ return mono_create_ftnptr (mono_domain_get (), code); } diff --git a/src/mono/mono/mini/debugger-agent.c b/src/mono/mono/mini/debugger-agent.c index 9e61992328189..f76e887e6db88 100644 --- a/src/mono/mono/mini/debugger-agent.c +++ b/src/mono/mono/mini/debugger-agent.c @@ -4589,7 +4589,16 @@ get_object_id_for_debugger_method (MonoClass* async_builder_class) ERROR_DECL (error); GPtrArray *array = mono_class_get_methods_by_name (async_builder_class, "get_ObjectIdForDebugger", 0x24, 1, FALSE, error); mono_error_assert_ok (error); - g_assert (array->len == 1); + if (array->len != 1) { + g_ptr_array_free (array, TRUE); + //if we don't find method get_ObjectIdForDebugger we try to find the property Task to continue async debug. + MonoProperty *prop = mono_class_get_property_from_name_internal (async_builder_class, "Task"); + if (!prop) { + DEBUG_PRINTF (1, "Impossible to debug async methods.\n"); + return NULL; + } + return prop->get; + } MonoMethod *method = (MonoMethod *)g_ptr_array_index (array, 0); g_ptr_array_free (array, TRUE); return method; @@ -4607,7 +4616,9 @@ get_class_to_get_builder_field(DbgEngineStackFrame *frame) MonoGenericContext context; MonoType *inflated_type; - g_assert (this_obj); + if (!this_obj) + return NULL; + context = mono_get_generic_context_from_stack_frame (frame->ji, this_obj->vtable); inflated_type = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (original_class), &context, error); mono_error_assert_ok (error); /* FIXME don't swallow the error */ @@ -4632,7 +4643,8 @@ get_async_method_builder (DbgEngineStackFrame *frame) klass = get_class_to_get_builder_field(frame); builder_field = mono_class_get_field_from_name_full (klass, "<>t__builder", NULL); - g_assert (builder_field); + if (!builder_field) + return NULL; this_addr = get_this_addr (frame); if (!this_addr) @@ -4671,7 +4683,8 @@ get_this_async_id (DbgEngineStackFrame *frame) return 0; builder_field = mono_class_get_field_from_name_full (get_class_to_get_builder_field(frame), "<>t__builder", NULL); - g_assert (builder_field); + if (!builder_field) + return 0; tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); if (tls) { @@ -4680,6 +4693,11 @@ get_this_async_id (DbgEngineStackFrame *frame) } method = get_object_id_for_debugger_method (mono_class_from_mono_type_internal (builder_field->type)); + if (!method) { + if (tls) + tls->disable_breakpoints = old_disable_breakpoints; + return 0; + } obj = mono_runtime_try_invoke (method, builder, NULL, &ex, error); mono_error_assert_ok (error); @@ -4695,9 +4713,11 @@ static gboolean set_set_notification_for_wait_completion_flag (DbgEngineStackFrame *frame) { MonoClassField *builder_field = mono_class_get_field_from_name_full (get_class_to_get_builder_field(frame), "<>t__builder", NULL); - g_assert (builder_field); + if (!builder_field) + return FALSE; gpointer builder = get_async_method_builder (frame); - g_assert (builder); + if (!builder) + return FALSE; MonoMethod* method = get_set_notification_method (mono_class_from_mono_type_internal (builder_field->type)); if (method == NULL) @@ -5071,7 +5091,10 @@ ss_create_init_args (SingleStepReq *ss_req, SingleStepArgs *args) * We are stopped at a throw site. Stepping should go to the catch site. */ frame = tls->catch_frame; - g_assert (frame.type == FRAME_TYPE_MANAGED || frame.type == FRAME_TYPE_INTERP); + if (frame.type != FRAME_TYPE_MANAGED && frame.type != FRAME_TYPE_INTERP) { + DEBUG_PRINTF (1, "Current frame is not managed nor interpreter.\n"); + return ERR_INVALID_ARGUMENT; + } /* * Find the seq point corresponding to the landing site ip, which is the first seq @@ -5080,7 +5103,10 @@ ss_create_init_args (SingleStepReq *ss_req, SingleStepArgs *args) found_sp = mono_find_next_seq_point_for_native_offset (frame.domain, frame.method, frame.native_offset, &info, &args->sp); if (!found_sp) no_seq_points_found (frame.method, frame.native_offset); - g_assert (found_sp); + if (!found_sp) { + DEBUG_PRINTF (1, "Could not find next sequence point.\n"); + return ERR_INVALID_ARGUMENT; + } method = frame.method; @@ -5125,7 +5151,10 @@ ss_create_init_args (SingleStepReq *ss_req, SingleStepArgs *args) found_sp = mono_find_prev_seq_point_for_native_offset (frame->de.domain, frame->de.method, frame->de.native_offset, &info, &args->sp); if (!found_sp) no_seq_points_found (frame->de.method, frame->de.native_offset); - g_assert (found_sp); + if (!found_sp) { + DEBUG_PRINTF (1, "Could not find next sequence point.\n"); + return ERR_INVALID_ARGUMENT; + } method = frame->de.method; } } @@ -8861,7 +8890,11 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g if (mono_class_get_context (klass)) { ERROR_DECL (error); result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), error); - g_assert (is_ok (error)); /* FIXME don't swallow the error */ + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + return ERR_INVALID_ARGUMENT; + } } } } @@ -8999,7 +9032,12 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g char *s; s = mono_string_to_utf8_checked_internal ((MonoString *)val, error); - mono_error_assert_ok (error); + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + g_free (s); + return ERR_INVALID_ARGUMENT; + } buffer_add_byte (buf, TOKEN_TYPE_STRING); buffer_add_string (buf, s); g_free (s); @@ -9062,7 +9100,11 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g tmp_context.method_inst = ginst; inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error); - g_assert (is_ok (error)); /* FIXME don't swallow the error */ + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + return ERR_INVALID_ARGUMENT; + } if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) return ERR_INVALID_ARGUMENT; buffer_add_methodid (buf, domain, inflated); @@ -9489,7 +9531,10 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) set_interp_var (m_class_get_this_arg (frame->actual_method->klass), addr, val_buf); } else { var = jit->this_var; - g_assert (var); + if (!var) { + add_error_string (buf, "Invalid this object"); + return ERR_INVALID_ARGUMENT; + } set_var (m_class_get_this_arg (frame->actual_method->klass), var, &frame->ctx, frame->de.domain, val_buf, frame->reg_locations, &tls->restore_state.ctx); } @@ -9532,9 +9577,11 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf) index = decode_int (p, &p, end); len = decode_int (p, &p, end); - g_assert (index >= 0 && len >= 0); + if (index < 0 || len < 0) + return ERR_INVALID_ARGUMENT; // Reordered to avoid integer overflow - g_assert (!(index > arr->max_length - len)); + if (index > arr->max_length - len) + return ERR_INVALID_ARGUMENT; esize = mono_array_element_size (arr->obj.vtable->klass); for (i = index; i < index + len; ++i) { @@ -9546,9 +9593,11 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf) index = decode_int (p, &p, end); len = decode_int (p, &p, end); - g_assert (index >= 0 && len >= 0); + if (index < 0 || len < 0) + return ERR_INVALID_ARGUMENT; // Reordered to avoid integer overflow - g_assert (!(index > arr->max_length - len)); + if (index > arr->max_length - len) + return ERR_INVALID_ARGUMENT; esize = mono_array_element_size (arr->obj.vtable->klass); for (i = index; i < index + len; ++i) { diff --git a/src/mono/mono/mini/dwarfwriter.c b/src/mono/mono/mini/dwarfwriter.c index bf2ff736feb33..c93151ec613c4 100644 --- a/src/mono/mono/mini/dwarfwriter.c +++ b/src/mono/mono/mini/dwarfwriter.c @@ -181,6 +181,12 @@ emit_int32 (MonoDwarfWriter *w, int value) mono_img_writer_emit_int32 (w->w, value); } +static void +emit_symbol (MonoDwarfWriter *w, const char *symbol) +{ + mono_img_writer_emit_symbol (w->w, symbol); +} + static void emit_symbol_diff (MonoDwarfWriter *w, const char *end, const char* start, int offset) { @@ -799,6 +805,7 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSLis w->cie_program = base_unwind_program; emit_section_change (w, ".debug_abbrev", 0); + emit_label (w, ".Ldebug_abbrev_start"); emit_dwarf_abbrev (w, ABBREV_COMPILE_UNIT, DW_TAG_compile_unit, TRUE, compile_unit_attr, G_N_ELEMENTS (compile_unit_attr)); emit_dwarf_abbrev (w, ABBREV_SUBPROGRAM, DW_TAG_subprogram, TRUE, @@ -842,7 +849,7 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSLis emit_symbol_diff (w, ".Ldebug_info_end", ".Ldebug_info_begin", 0); /* length */ emit_label (w, ".Ldebug_info_begin"); emit_int16 (w, 0x2); /* DWARF version 2 */ - emit_int32 (w, 0); /* .debug_abbrev offset */ + emit_symbol (w, ".Ldebug_abbrev_start"); /* .debug_abbrev offset */ emit_byte (w, sizeof (target_mgreg_t)); /* address size */ /* Compilation unit */ diff --git a/src/mono/mono/mini/exceptions-x86.c b/src/mono/mono/mini/exceptions-x86.c index 22e54bc9258a5..d8f6f769a1c51 100644 --- a/src/mono/mono/mini/exceptions-x86.c +++ b/src/mono/mono/mini/exceptions-x86.c @@ -1242,3 +1242,15 @@ mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func) MONO_CONTEXT_SET_IP (ctx, func); } + +void +mono_arch_undo_ip_adjustment (MonoContext *ctx) +{ + ctx->eip++; +} + +void +mono_arch_do_ip_adjustment (MonoContext *ctx) +{ + ctx->eip--; +} diff --git a/src/mono/mono/mini/image-writer.c b/src/mono/mono/mini/image-writer.c index 7314c5ee8308a..b191269667aa4 100644 --- a/src/mono/mono/mini/image-writer.c +++ b/src/mono/mono/mini/image-writer.c @@ -410,11 +410,14 @@ create_reloc (MonoImageWriter *acfg, const char *end, const char* start, int off BinReloc *reloc; reloc = (BinReloc *)mono_mempool_alloc0 (acfg->mempool, sizeof (BinReloc)); reloc->val1 = mono_mempool_strdup (acfg->mempool, end); - if (strcmp (start, ".") == 0) { - reloc->val2_section = acfg->cur_section; - reloc->val2_offset = acfg->cur_section->cur_offset; - } else { - reloc->val2 = mono_mempool_strdup (acfg->mempool, start); + if (start) + { + if (strcmp (start, ".") == 0) { + reloc->val2_section = acfg->cur_section; + reloc->val2_offset = acfg->cur_section->cur_offset; + } else { + reloc->val2 = mono_mempool_strdup (acfg->mempool, start); + } } reloc->offset = offset; reloc->section = acfg->cur_section; @@ -424,6 +427,13 @@ create_reloc (MonoImageWriter *acfg, const char *end, const char* start, int off return reloc; } +static void +bin_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) +{ + create_reloc (acfg, symbol, NULL, 0); + acfg->cur_section->cur_offset += 4; +} + static void bin_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) { @@ -1924,6 +1934,23 @@ asm_writer_emit_int32 (MonoImageWriter *acfg, int value) fprintf (acfg->fp, "%d", value); } +static void +asm_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) +{ + if (acfg->mode != EMIT_LONG) { + acfg->mode = EMIT_LONG; + acfg->col_count = 0; + } + + symbol = get_label (symbol); + + if ((acfg->col_count++ % 8) == 0) + fprintf (acfg->fp, "\n\t%s ", AS_INT32_DIRECTIVE); + else + fprintf (acfg->fp, ","); + fprintf (acfg->fp, "%s", symbol); +} + static void asm_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) { @@ -2213,6 +2240,19 @@ mono_img_writer_emit_int32 (MonoImageWriter *acfg, int value) #endif } +void +mono_img_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) +{ +#ifdef USE_BIN_WRITER + if (acfg->use_bin_writer) + bin_writer_emit_symbol (acfg, symbol); + else + asm_writer_emit_symbol (acfg, symbol); +#else + asm_writer_emit_symbol (acfg, symbol); +#endif +} + void mono_img_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) { diff --git a/src/mono/mono/mini/image-writer.h b/src/mono/mono/mini/image-writer.h index 0c34246422e8b..309ec37c059a7 100644 --- a/src/mono/mono/mini/image-writer.h +++ b/src/mono/mono/mini/image-writer.h @@ -98,6 +98,8 @@ void mono_img_writer_emit_int16 (MonoImageWriter *w, int value); void mono_img_writer_emit_int32 (MonoImageWriter *w, int value); +void mono_img_writer_emit_symbol (MonoImageWriter *w, const char *symbol); + void mono_img_writer_emit_symbol_diff (MonoImageWriter *w, const char *end, const char* start, int offset); void mono_img_writer_emit_zero_bytes (MonoImageWriter *w, int num); diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index b335170438670..b88e969bab9d6 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -151,6 +151,7 @@ struct InterpMethod { gpointer jit_wrapper; gpointer jit_addr; MonoMethodSignature *jit_sig; + gint32 jit_vt_res_size; gpointer jit_entry; gpointer llvmonly_unbox_entry; MonoType *rtype; @@ -181,7 +182,11 @@ typedef struct _StackFragment StackFragment; struct _StackFragment { guint8 *pos, *end; struct _StackFragment *next; - double data [1]; +#if SIZEOF_VOID_P == 4 + /* Align data field to MINT_VT_ALIGNMENT */ + gint32 pad; +#endif + double data [MONO_ZERO_LEN_ARRAY]; }; typedef struct { @@ -201,7 +206,6 @@ typedef struct { const unsigned short *ip; GSList *finally_ips; FrameClauseArgs *clause_args; - gboolean is_void : 1; } InterpState; struct InterpFrame { diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index d2e388df90741..4ac1b20a67f18 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -221,12 +221,11 @@ frame_stack_free (FrameStack *stack) * Reinitialize a frame. */ static void -reinit_frame (InterpFrame *frame, InterpFrame *parent, InterpMethod *imethod, stackval *stack_args, stackval *retval) +reinit_frame (InterpFrame *frame, InterpFrame *parent, InterpMethod *imethod, stackval *stack_args) { frame->parent = parent; frame->imethod = imethod; frame->stack_args = stack_args; - frame->retval = retval; frame->stack = NULL; frame->ip = NULL; frame->state.ip = NULL; @@ -1290,16 +1289,9 @@ static InterpMethodArguments* build_args_from_sig (MonoMethodSignature *sig, Int break; #endif case MONO_TYPE_R4: -#if SIZEOF_VOID_P == 8 case MONO_TYPE_R8: -#endif margs->flen++; break; -#if SIZEOF_VOID_P == 4 - case MONO_TYPE_R8: - margs->flen += 2; - break; -#endif default: g_error ("build_args_from_sig: not implemented yet (1): 0x%x\n", ptype); } @@ -1384,11 +1376,7 @@ static InterpMethodArguments* build_args_from_sig (MonoMethodSignature *sig, Int #if DEBUG_INTERP g_print ("build_args_from_sig: margs->fargs [%d]: %p (%f) (frame @ %d)\n", int_f, margs->fargs [int_f], margs->fargs [int_f], i); #endif -#if SIZEOF_VOID_P == 4 - int_f += 2; -#else - int_f++; -#endif + int_f ++; break; default: g_error ("build_args_from_sig: not implemented yet (2): 0x%x\n", ptype); @@ -1669,7 +1657,7 @@ interp_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpoint MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoDelegate, this_obj), interp_method, gpointer, imethod); - mono_delegate_ctor (this_obj, target, entry, error); + mono_delegate_ctor (this_obj, target, entry, imethod->method, error); } /* @@ -2313,6 +2301,21 @@ do_jit_call (stackval *sp, unsigned char *vt_sp, ThreadContext *context, InterpF rmethod->jit_addr = addr; rmethod->jit_sig = sig; + + if (sig->ret->type != MONO_TYPE_VOID) { + int mt = mint_type (sig->ret); + if (mt == MINT_TYPE_VT) { + MonoClass *klass = mono_class_from_mono_type_internal (sig->ret); + /* + * We cache this size here, instead of the instruction stream of the + * calling instruction, to save space for common callvirt instructions + * that could end up doing a jit call. + */ + gint32 size = mono_class_value_size (klass, NULL); + rmethod->jit_vt_res_size = ALIGN_TO (size, MINT_VT_ALIGNMENT); + } + } + mono_memory_barrier (); rmethod->jit_wrapper = jit_wrapper; @@ -2500,7 +2503,7 @@ do_transform_method (InterpFrame *frame, ThreadContext *context) return mono_error_convert_to_exception (error); } -static guchar* +static void copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp_start) { stackval *first_arg = sp - csig->param_count; @@ -2509,8 +2512,9 @@ copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp_sta /* * We need to have the varargs linearly on the stack so the ArgIterator * can iterate over them. We pass the signature first and then copy them - * one by one on the vtstack. At the end we pass the original vt_stack - * so the callee (MINT_ARGLIST) can find the varargs space. + * one by one on the vtstack. The callee (MINT_ARGLIST) will be able to + * find this space by adding the current vt_sp pointer in the parent frame + * with the amount of vtstack space used by the parameters. */ *(gpointer*)vt_sp = csig; vt_sp += sizeof (gpointer); @@ -2523,13 +2527,6 @@ copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp_sta stackval_to_data (csig->params [i], &first_arg [i], vt_sp, FALSE); vt_sp += arg_size; } - - vt_sp += sizeof (gpointer); - vt_sp = (guchar*)ALIGN_PTR_TO (vt_sp, MINT_VT_ALIGNMENT); - - ((gpointer*)vt_sp) [-1] = vt_sp_start; - - return vt_sp; } /* @@ -2542,8 +2539,6 @@ copy_varargs_vtstack (MonoMethodSignature *csig, stackval *sp, guchar *vt_sp_sta * this/static * ret/void * 16 arguments -> 64 functions. */ -#define MAX_INTERP_ENTRY_ARGS 8 - #define INTERP_ENTRY_BASE(_method, _this_arg, _res) \ InterpEntryData data; \ (data).rmethod = (_method); \ @@ -2830,8 +2825,14 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE * to use a ftndesc. The caller uses a normal signature, while the * entry functions use a gsharedvt_in signature, so wrap the entry function in * a gsharedvt_in_sig wrapper. + * We use a gsharedvt_in_sig wrapper instead of an interp_in wrapper, because they + * are mostly the same, and they are already generated. The exception is the + * wrappers for methods with more than 8 arguments, those are different. */ - wrapper = mini_get_gsharedvt_in_sig_wrapper (sig); + if (sig->param_count > MAX_INTERP_ENTRY_ARGS) + wrapper = mini_get_interp_in_wrapper (sig); + else + wrapper = mini_get_gsharedvt_in_sig_wrapper (sig); entry_wrapper = mono_jit_compile_method_jit_only (wrapper, error); mono_error_assertf_ok (error, "couldn't compile wrapper \"%s\" for \"%s\"", @@ -2839,8 +2840,7 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL)); if (sig->param_count > MAX_INTERP_ENTRY_ARGS) { - g_assert_not_reached (); - //entry_func = (gpointer)interp_entry_general; + entry_func = (gpointer)interp_entry_general; } else if (sig->hasthis) { if (sig->ret->type == MONO_TYPE_VOID) entry_func = entry_funcs_instance [sig->param_count]; @@ -2952,7 +2952,7 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e } } else { #ifndef MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE - mono_error_assertf_ok (error, "couldn't compile wrapper \"%s\" for \"%s\"", + g_assertion_message ("couldn't compile wrapper \"%s\" for \"%s\"", mono_method_get_name_full (wrapper, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL), mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL)); #else @@ -3140,25 +3140,10 @@ mono_interp_isinst (MonoObject* object, MonoClass* klass) return isinst; } -// Do not inline use of alloca. -// Do not inline in case order of frame addresses matters. -static MONO_NEVER_INLINE void -mono_interp_calli_nat_dynamic_pinvoke ( - // Parameters are sorted by name. - guchar* code, - ThreadContext* context, - MonoMethodSignature* csignature, - MonoError* error, - InterpFrame *parent_frame, - stackval *retval, - stackval *sp) +static MONO_NEVER_INLINE InterpMethod* +mono_interp_get_native_func_wrapper (InterpMethod* imethod, MonoMethodSignature* csignature, guchar* code) { - InterpFrame frame = {parent_frame, NULL, sp, retval}; - - // Recompute to limit parameters, which can also contribute to caller stack. - InterpMethod* const imethod = parent_frame->imethod; - - g_assert (imethod->method->dynamic && csignature->pinvoke); + ERROR_DECL(error); /* Pinvoke call is missing the wrapper. See mono_get_native_calli_wrapper */ MonoMarshalSpec** mspecs = g_newa0 (MonoMarshalSpec*, csignature->param_count + 1); @@ -3172,13 +3157,10 @@ mono_interp_calli_nat_dynamic_pinvoke ( if (mspecs [i]) mono_metadata_free_marshal_spec (mspecs [i]); - { - ERROR_DECL (error); - frame.imethod = mono_interp_get_imethod (imethod->domain, m, error); - mono_error_cleanup (error); /* FIXME: don't swallow the error */ - } + InterpMethod *cmethod = mono_interp_get_imethod (imethod->domain, m, error); + mono_error_cleanup (error); /* FIXME: don't swallow the error */ - interp_exec_method (&frame, context, NULL, error); + return cmethod; } // Do not inline in case order of frame addresses matters. @@ -3348,7 +3330,6 @@ method_entry (ThreadContext *context, InterpFrame *frame, frame->state.ip = ip; \ frame->state.sp = sp; \ frame->state.vt_sp = vt_sp; \ - frame->state.is_void = is_void; \ frame->state.finally_ips = finally_ips; \ frame->state.clause_args = clause_args; \ } while (0) @@ -3357,7 +3338,6 @@ method_entry (ThreadContext *context, InterpFrame *frame, #define LOAD_INTERP_STATE(frame) do { \ ip = frame->state.ip; \ sp = frame->state.sp; \ - is_void = frame->state.is_void; \ vt_sp = frame->state.vt_sp; \ finally_ips = frame->state.finally_ips; \ clause_args = frame->state.clause_args; \ @@ -3385,8 +3365,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs { InterpMethod *cmethod; MonoException *ex; - gboolean is_void; - stackval *retval; /* Interpreter main loop state (InterpState) */ const guint16 *ip = NULL; @@ -3472,7 +3450,12 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs MINT_IN_BREAK; MINT_IN_CASE(MINT_ARGLIST) sp->data.p = vt_sp; - *(gpointer*)sp->data.p = ((gpointer*)frame->retval->data.p) [-1]; + /* + * We know we have been called by an MINT_CALL_VARARG and the amount of vtstack + * used by the parameters is at ip [-1] (the last argument to MINT_CALL_VARARG that + * is embedded in the instruction stream). + */ + *(gpointer*)sp->data.p = frame->parent->state.vt_sp + frame->parent->state.ip [-1]; vt_sp += ALIGN_TO (sizeof (gpointer), MINT_VT_ALIGNMENT); ++ip; ++sp; @@ -3575,6 +3558,13 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs ip++; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_POP_VT) { + int i32 = READ32 (ip + 1); + vt_sp -= ALIGN_TO (i32, MINT_VT_ALIGNMENT); + sp--; + ip += 3; + MINT_IN_BREAK; + } MINT_IN_CASE(MINT_POP1) { sp [-2] = sp [-1]; sp--; @@ -3620,7 +3610,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs } MINT_IN_CASE(MINT_CALL_DELEGATE) { MonoMethodSignature *csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [1]]; - is_void = csignature->ret->type == MONO_TYPE_VOID; int param_count = csignature->param_count; MonoDelegate *del = (MonoDelegate*) sp [-param_count - 1].data.o; gboolean is_multicast = del->method == NULL; @@ -3659,8 +3648,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs } } cmethod = del_imethod; - retval = sp; - sp->data.p = vt_sp; + vt_sp -= ip [2]; sp -= param_count + 1; if (!is_multicast) { if (cmethod->param_count == param_count + 1) { @@ -3684,7 +3672,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs memmove (sp, sp + 1, param_count * sizeof (stackval)); } } - ip += 2; + ip += 3; goto call; } @@ -3694,7 +3682,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs frame->ip = ip; csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [1]]; - ip += 2; --sp; cmethod = (InterpMethod*)sp->data.p; @@ -3703,14 +3690,11 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs mono_interp_error_cleanup (error); /* FIXME: don't swallow the error */ } - is_void = csignature->ret->type == MONO_TYPE_VOID; - retval = is_void ? NULL : sp; - - sp->data.p = vt_sp; /* decrement by the actual number of args */ sp -= csignature->param_count; if (csignature->hasthis) --sp; + vt_sp -= ip [2]; if (csignature->hasthis) { MonoObject *this_arg = (MonoObject*)sp->data.p; @@ -3720,6 +3704,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs sp [0].data.p = unboxed; } } + ip += 3; goto call; } @@ -3738,58 +3723,73 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs ip += 4; MINT_IN_BREAK; } - MINT_IN_CASE(MINT_CALLI_NAT) { + MINT_IN_CASE(MINT_CALLI_NAT_DYNAMIC) { MonoMethodSignature* csignature; frame->ip = ip; csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [1]]; + --sp; + guchar* code = (guchar*)sp->data.p; + + /* decrement by the actual number of args */ + sp -= csignature->param_count; + if (csignature->hasthis) + --sp; + vt_sp -= ip [2]; + + cmethod = mono_interp_get_native_func_wrapper (frame->imethod, csignature, code); + ip += 3; + goto call; + } + MINT_IN_CASE(MINT_CALLI_NAT) { + MonoMethodSignature* csignature; + stackval retval; + + frame->ip = ip; + + csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [1]]; + --sp; guchar* const code = (guchar*)sp->data.p; - retval = sp; - sp->data.p = vt_sp; /* decrement by the actual number of args */ sp -= csignature->param_count; if (csignature->hasthis) --sp; + vt_sp -= ip [2]; + /* If this is a vt return, the pinvoke will write the result directly to vt_sp */ + retval.data.p = vt_sp; - if (frame->imethod->method->dynamic && csignature->pinvoke) { - mono_interp_calli_nat_dynamic_pinvoke (code, context, csignature, error, frame, retval, sp); - } else { - const gboolean save_last_error = ip [-3 + 2]; - ves_pinvoke_method (csignature, (MonoFuncV)code, context, frame, retval, save_last_error, sp); - } + gboolean save_last_error = ip [4]; + ves_pinvoke_method (csignature, (MonoFuncV)code, context, frame, &retval, save_last_error, sp); CHECK_RESUME_STATE (context); if (csignature->ret->type != MONO_TYPE_VOID) { - *sp = *retval; + *sp = retval; + vt_sp += ip [3]; sp++; } + ip += 5; MINT_IN_BREAK; } - MINT_IN_CASE(MINT_CALLVIRT_FAST) - MINT_IN_CASE(MINT_VCALLVIRT_FAST) { + MINT_IN_CASE(MINT_CALLVIRT_FAST) { MonoObject *this_arg; - is_void = *ip == MINT_VCALLVIRT_FAST; int slot; frame->ip = ip; cmethod = (InterpMethod*)frame->imethod->data_items [ip [1]]; slot = (gint16)ip [2]; - ip += 3; - sp->data.p = vt_sp; - - retval = is_void ? NULL : sp; /* decrement by the actual number of args */ sp -= cmethod->param_count + cmethod->hasthis; - + vt_sp -= ip [3]; this_arg = (MonoObject*)sp->data.p; + ip += 4; cmethod = get_virtual_method_fast (cmethod, this_arg->vtable, slot); if (m_class_is_valuetype (this_arg->vtable->klass) && m_class_is_valuetype (cmethod->method->klass)) { @@ -3827,8 +3827,10 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs CHECK_RESUME_STATE (context); - if (cmethod->rtype->type != MONO_TYPE_VOID) + if (cmethod->rtype->type != MONO_TYPE_VOID) { sp++; + vt_sp += cmethod->jit_vt_res_size; + } } MINT_IN_BREAK; @@ -3842,59 +3844,56 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs csig = (MonoMethodSignature*) frame->imethod->data_items [ip [2]]; frame->ip = ip; - - // Retval must be set unconditionally due to MINT_ARGLIST. - // is_void guides exit_frame instead of retval nullness. - retval = sp; - is_void = csig->ret->type == MONO_TYPE_VOID; - /* Push all vararg arguments from normal sp to vt_sp together with the signature */ - vt_sp = copy_varargs_vtstack (csig, sp, vt_sp); - - ip += 3; - sp->data.p = vt_sp; + copy_varargs_vtstack (csig, sp, vt_sp); + vt_sp -= ip [3]; /* decrement by the actual number of args */ // FIXME This seems excessive: frame and csig param_count. sp -= cmethod->param_count + cmethod->hasthis + csig->param_count - csig->sentinelpos; + ip += 4; goto call; } - MINT_IN_CASE(MINT_VCALL) - MINT_IN_CASE(MINT_CALL) - MINT_IN_CASE(MINT_CALLVIRT) - MINT_IN_CASE(MINT_VCALLVIRT) { + MINT_IN_CASE(MINT_CALLVIRT) { // FIXME CALLVIRT opcodes are not used on netcore. We should kill them. - // FIXME braces from here until call: label. - is_void = *ip == MINT_VCALL || *ip == MINT_VCALLVIRT; - gboolean is_virtual; - is_virtual = *ip == MINT_CALLVIRT || *ip == MINT_VCALLVIRT; - cmethod = (InterpMethod*)frame->imethod->data_items [ip [1]]; - sp->data.p = vt_sp; - retval = is_void ? NULL : sp; /* decrement by the actual number of args */ sp -= ip [2]; + vt_sp -= ip [3]; - if (is_virtual) { - MonoObject *this_arg = (MonoObject*)sp->data.p; + MonoObject *this_arg = (MonoObject*)sp->data.p; - cmethod = get_virtual_method (cmethod, this_arg->vtable); - if (m_class_is_valuetype (this_arg->vtable->klass) && m_class_is_valuetype (cmethod->method->klass)) { - /* unbox */ - gpointer unboxed = mono_object_unbox_internal (this_arg); - sp [0].data.p = unboxed; - } + cmethod = get_virtual_method (cmethod, this_arg->vtable); + if (m_class_is_valuetype (this_arg->vtable->klass) && m_class_is_valuetype (cmethod->method->klass)) { + /* unbox */ + gpointer unboxed = mono_object_unbox_internal (this_arg); + sp [0].data.p = unboxed; } frame->ip = ip; #ifdef ENABLE_EXPERIMENT_TIERED ip += 5; #else - ip += 3; + ip += 4; +#endif + goto call; + } + MINT_IN_CASE(MINT_CALL) { + cmethod = (InterpMethod*)frame->imethod->data_items [ip [1]]; + + /* decrement by the actual number of args */ + sp -= ip [2]; + vt_sp -= ip [3]; + + frame->ip = ip; +#ifdef ENABLE_EXPERIMENT_TIERED + ip += 5; +#else + ip += 4; #endif -call:; +call: /* * Make a non-recursive call by loading the new interpreter state based on child frame, * and going back to the main loop. @@ -3910,7 +3909,7 @@ call:; // Not free currently, but will be when allocation attempted. frame->next_free = child_frame; } - reinit_frame (child_frame, frame, cmethod, sp, retval); + reinit_frame (child_frame, frame, cmethod, sp); frame = child_frame; } if (method_entry (context, frame, @@ -3933,18 +3932,21 @@ call:; error_init_reuse (error); frame->ip = ip; sp -= rmethod->param_count + rmethod->hasthis; + vt_sp -= ip [2]; do_jit_call (sp, vt_sp, context, frame, rmethod, error); if (!is_ok (error)) { MonoException *ex = mono_error_convert_to_exception (error); THROW_EX (ex, ip); } - ip += 2; CHECK_RESUME_STATE (context); - if (rmethod->rtype->type != MONO_TYPE_VOID) + if (rmethod->rtype->type != MONO_TYPE_VOID) { sp++; + vt_sp += rmethod->jit_vt_res_size; + } + ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_JIT_CALL2) { @@ -3977,7 +3979,7 @@ call:; MonoMethodSignature *sig = (MonoMethodSignature*) frame->imethod->data_items [ip [2]]; sp->data.p = vt_sp; - retval = sp; + stackval *retval = sp; sp -= sig->param_count; if (sig->hasthis) @@ -3999,7 +4001,13 @@ call:; } MINT_IN_CASE(MINT_RET) --sp; - *frame->retval = *sp; + if (frame->parent) { + frame->parent->state.sp [0] = *sp; + frame->parent->state.sp++; + } else { + // FIXME This can only happen in a few wrappers. Add separate opcode for it + *frame->retval = *sp; + } if (sp > frame->stack) g_warning_d ("ret: more values on stack: %d", sp - frame->stack); goto exit_frame; @@ -4008,9 +4016,19 @@ call:; g_warning_ds ("ret.void: more values on stack: %d %s", sp - frame->stack, mono_method_full_name (frame->imethod->method, TRUE)); goto exit_frame; MINT_IN_CASE(MINT_RET_VT) { + gpointer dest_vt; int const i32 = READ32 (ip + 1); --sp; - memcpy(frame->retval->data.p, sp->data.p, i32); + if (frame->parent) { + dest_vt = frame->parent->state.vt_sp; + /* Push the valuetype in the parent frame */ + frame->parent->state.sp [0].data.p = dest_vt; + frame->parent->state.sp++; + frame->parent->state.vt_sp += ALIGN_TO (i32, MINT_VT_ALIGNMENT); + } else { + dest_vt = frame->retval->data.p; + } + memcpy (dest_vt, sp->data.p, i32); if (sp > frame->stack) g_warning_d ("ret.vt: more values on stack: %d", sp - frame->stack); goto exit_frame; @@ -4980,6 +4998,22 @@ call:; ip += 3; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_NEWOBJ_STRING) { + frame->ip = ip; + + cmethod = (InterpMethod*)frame->imethod->data_items [ip [1]]; + + const int param_count = ip [2]; + if (param_count) { + sp -= param_count; + memmove (sp + 1, sp, param_count * sizeof (stackval)); + } + // `this` is implicit null. The created string will be returned + // by the call, even though the call has void return (?!). + sp->data.p = NULL; + ip += 3; + goto call; + } MINT_IN_CASE(MINT_NEWOBJ_FAST) { MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [ip [3]]; INIT_VTABLE (vtable); @@ -5063,8 +5097,6 @@ call:; // on the stack before the call, instead of the call forming it. call_newobj: ++sp; // Point sp at added extra param, after return value. - is_void = TRUE; - retval = NULL; goto call; MINT_IN_CASE(MINT_NEWOBJ) { @@ -5102,15 +5134,6 @@ call:; g_assert (!m_class_is_valuetype (newobj_class)); - // This branch could be avoided. Move it to transform, and use a new opcode NEWOBJ_STRING. - if (newobj_class == mono_defaults.string_class) { - retval = sp; - ++sp; - sp->data.p = NULL; // first parameter - is_void = TRUE; - goto call; - } - MonoDomain* const domain = frame->imethod->domain; MonoVTable *vtable = mono_class_vtable_checked (domain, newobj_class, error); if (!is_ok (error) || !mono_runtime_class_init_full (vtable, error)) { @@ -7176,8 +7199,6 @@ call:; if (!clause_args && frame->parent && frame->parent->state.ip) { /* Return to the main loop after a non-recursive interpreter call */ //printf ("R: %s -> %s %p\n", mono_method_get_full_name (frame->imethod->method), mono_method_get_full_name (frame->parent->imethod->method), frame->parent->state.ip); - stackval *retval = frame->retval; - InterpFrame* const child_frame = frame; frame = frame->parent; @@ -7187,10 +7208,6 @@ call:; CHECK_RESUME_STATE (context); - if (!is_void) { - *sp = *retval; - sp ++; - } goto main_loop; } diff --git a/src/mono/mono/mini/interp/interp.h b/src/mono/mono/mini/interp/interp.h index 40c9e96829e23..198d423f7f4f5 100644 --- a/src/mono/mono/mini/interp/interp.h +++ b/src/mono/mono/mini/interp/interp.h @@ -14,6 +14,8 @@ #define INTERP_ICALL_TRAMP_FARGS 4 #endif +#define MAX_INTERP_ENTRY_ARGS 8 + struct _InterpMethodArguments { size_t ilen; gpointer *iargs; diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index d3a7a73b17718..fd8691ba36b13 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -16,6 +16,7 @@ OPDEF(MINT_LDNULL, "ldnull", 1, Pop0, Push1, MintOpNoArgs) OPDEF(MINT_DUP, "dup", 1, Pop1, Push2, MintOpNoArgs) OPDEF(MINT_DUP_VT, "dup.vt", 3, Pop1, Push2, MintOpInt) OPDEF(MINT_POP, "pop", 1, Pop1, Push0, MintOpNoArgs) +OPDEF(MINT_POP_VT, "pop.vt", 3, Pop1, Push0, MintOpNoArgs) OPDEF(MINT_POP1, "pop1", 1, Pop2, Push1, MintOpNoArgs) OPDEF(MINT_RET, "ret", 1, Pop1, Push0, MintOpNoArgs) @@ -380,6 +381,7 @@ OPDEF(MINT_ENDFILTER, "endfilter", 1, Pop0, Push0, MintOpNoArgs) OPDEF(MINT_NEWOBJ, "newobj", 2, VarPop, Push1, MintOpMethodToken) OPDEF(MINT_NEWOBJ_ARRAY, "newobj_array", 3, VarPop, Push1, MintOpMethodToken) +OPDEF(MINT_NEWOBJ_STRING, "newobj_string", 3, VarPop, Push1, MintOpMethodToken) OPDEF(MINT_NEWOBJ_FAST, "newobj_fast", 4, VarPop, Push1, MintOpMethodToken) OPDEF(MINT_NEWOBJ_VT_FAST, "newobj_vt_fast", 3, VarPop, Push1, MintOpMethodToken) OPDEF(MINT_NEWOBJ_VTST_FAST, "newobj_vtst_fast", 4, VarPop, Push1, MintOpMethodToken) @@ -698,17 +700,15 @@ OPDEF(MINT_ARRAY_ELEMENT_SIZE, "array_element_size", 1, Pop1, Push1, MintOpNoArg OPDEF(MINT_ARRAY_IS_PRIMITIVE, "array_is_primitive", 1, Pop1, Push1, MintOpNoArgs) /* Calls */ -OPDEF(MINT_CALL, "call", 3, VarPop, Push1, MintOpMethodToken) -OPDEF(MINT_VCALL, "vcall", 3, VarPop, Push0, MintOpMethodToken) -OPDEF(MINT_CALLVIRT, "callvirt", 3, VarPop, Push1, MintOpMethodToken) -OPDEF(MINT_VCALLVIRT, "vcallvirt", 3, VarPop, Push0, MintOpMethodToken) -OPDEF(MINT_CALLVIRT_FAST, "callvirt.fast", 3, VarPop, Push1, MintOpMethodToken) -OPDEF(MINT_VCALLVIRT_FAST, "vcallvirt.fast", 3, VarPop, Push0, MintOpMethodToken) -OPDEF(MINT_CALL_DELEGATE, "call.delegate", 2, VarPop, VarPush, MintOpMethodToken) -OPDEF(MINT_CALLI, "calli", 2, VarPop, VarPush, MintOpMethodToken) -OPDEF(MINT_CALLI_NAT, "calli.nat", 3, VarPop, VarPush, MintOpMethodToken) +OPDEF(MINT_CALL, "call", 4, VarPop, Push1, MintOpMethodToken) +OPDEF(MINT_CALLVIRT, "callvirt", 4, VarPop, Push1, MintOpMethodToken) +OPDEF(MINT_CALLVIRT_FAST, "callvirt.fast", 4, VarPop, Push1, MintOpMethodToken) +OPDEF(MINT_CALL_DELEGATE, "call.delegate", 3, VarPop, VarPush, MintOpMethodToken) +OPDEF(MINT_CALLI, "calli", 3, VarPop, VarPush, MintOpMethodToken) +OPDEF(MINT_CALLI_NAT, "calli.nat", 5, VarPop, VarPush, MintOpMethodToken) +OPDEF(MINT_CALLI_NAT_DYNAMIC, "calli.nat.dynamic", 3, VarPop, VarPush, MintOpMethodToken) OPDEF(MINT_CALLI_NAT_FAST, "calli.nat.fast", 4, VarPop, VarPush, MintOpMethodToken) -OPDEF(MINT_CALL_VARARG, "call.vararg", 3, VarPop, VarPush, MintOpMethodToken) +OPDEF(MINT_CALL_VARARG, "call.vararg", 4, VarPop, VarPush, MintOpMethodToken) OPDEF(MINT_CALLRUN, "callrun", 3, VarPop, VarPush, MintOpNoArgs) OPDEF(MINT_ICALL_V_V, "mono_icall_v_v", 2, Pop0, Push0, MintOpClassToken) /* not really */ @@ -726,7 +726,7 @@ OPDEF(MINT_ICALL_PPPPP_P, "mono_icall_ppppp_p", 2, Pop5, Push1, MintOpClassToken OPDEF(MINT_ICALL_PPPPPP_V, "mono_icall_pppppp_v", 2, Pop6, Push0, MintOpClassToken) OPDEF(MINT_ICALL_PPPPPP_P, "mono_icall_pppppp_p", 2, Pop6, Push1, MintOpClassToken) // FIXME: MintOp -OPDEF(MINT_JIT_CALL, "mono_jit_call", 2, VarPop, VarPush, MintOpNoArgs) +OPDEF(MINT_JIT_CALL, "mono_jit_call", 3, VarPop, VarPush, MintOpNoArgs) OPDEF(MINT_JIT_CALL2, "mono_jit_call2", 5, VarPop, VarPush, MintOpNoArgs) OPDEF(MINT_MONO_LDPTR, "mono_ldptr", 2, Pop0, Push1, MintOpClassToken) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index c9bf7a6b28c78..4bca4e3752c66 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2169,7 +2169,6 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target guint32 vt_res_size = 0; int op = -1; int native = 0; - int is_void = 0; int need_null_check = is_virtual; gboolean is_delegate_invoke = FALSE; @@ -2368,10 +2367,12 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target vararg_stack = ALIGN_TO (vararg_stack, align); vararg_stack += arg_size; } - /* allocate space for the pointer to varargs space start */ - vararg_stack += sizeof (gpointer); - vt_stack_used += ALIGN_TO (vararg_stack, MINT_VT_ALIGNMENT); + /* + * MINT_CALL_VARARG needs this space on the vt stack. Make sure the + * vtstack space is sufficient. + */ PUSH_VT (td, vararg_stack); + POP_VT (td, vararg_stack); } if (need_null_check) { @@ -2418,6 +2419,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target vt_stack_used += size; } } + /* Pop the vt stack used by the arguments */ + td->vt_sp -= vt_stack_used; /* need to handle typedbyref ... */ if (csignature->ret->type != MONO_TYPE_VOID) { @@ -2435,8 +2438,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target PUSH_VT(td, vt_res_size); } PUSH_TYPE(td, stack_type[mt], klass); - } else - is_void = TRUE; + } if (op >= 0) { interp_add_ins (td, op); @@ -2459,40 +2461,62 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target interp_add_ins (td, MINT_JIT_CALL); td->last_ins->data [0] = get_data_item_index (td, (void *)mono_interp_get_imethod (domain, target_method, error)); mono_error_assert_ok (error); + td->last_ins->data [1] = vt_stack_used; } else { -#ifndef MONO_ARCH_HAS_NO_PROPER_MONOCTX - /* Try using fast icall path for simple signatures */ - if (native && !method->dynamic) - op = interp_icall_op_for_sig (csignature); -#endif - if (csignature->call_convention == MONO_CALL_VARARG) - interp_add_ins (td, MINT_CALL_VARARG); - else if (is_delegate_invoke) - interp_add_ins (td, MINT_CALL_DELEGATE); - else if (calli) - interp_add_ins (td, native ? ((op != -1) ? MINT_CALLI_NAT_FAST : MINT_CALLI_NAT) : MINT_CALLI); - else if (is_virtual && !mono_class_is_marshalbyref (target_method->klass)) - interp_add_ins (td, is_void ? MINT_VCALLVIRT_FAST : MINT_CALLVIRT_FAST); - else if (is_virtual) - interp_add_ins (td, is_void ? MINT_VCALLVIRT : MINT_CALLVIRT); - else - interp_add_ins (td, is_void ? MINT_VCALL : MINT_CALL); - if (is_delegate_invoke) { + interp_add_ins (td, MINT_CALL_DELEGATE); td->last_ins->data [0] = get_data_item_index (td, (void *)csignature); + td->last_ins->data [1] = vt_stack_used; } else if (calli) { - td->last_ins->data [0] = get_data_item_index (td, (void *)csignature); +#ifndef MONO_ARCH_HAS_NO_PROPER_MONOCTX + /* Try using fast icall path for simple signatures */ + if (native && !method->dynamic) + op = interp_icall_op_for_sig (csignature); +#endif if (op != -1) { - td->last_ins->data[1] = op; - if (td->last_ins->opcode == MINT_CALLI_NAT_FAST) - td->last_ins->data[2] = save_last_error; - } else if (op == -1 && td->last_ins->opcode == MINT_CALLI_NAT) { - td->last_ins->data[1] = save_last_error; + interp_add_ins (td, MINT_CALLI_NAT_FAST); + td->last_ins->data [1] = op; + td->last_ins->data [2] = save_last_error; + } else if (native && method->dynamic && csignature->pinvoke) { + interp_add_ins (td, MINT_CALLI_NAT_DYNAMIC); + td->last_ins->data [1] = vt_stack_used; + } else if (native) { + interp_add_ins (td, MINT_CALLI_NAT); +#ifdef TARGET_X86 + /* Windows not tested/supported yet */ + g_assertf (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C, "Interpreter supports only cdecl pinvoke on x86"); +#endif + td->last_ins->data [1] = vt_stack_used; + td->last_ins->data [2] = vt_res_size; + td->last_ins->data [3] = save_last_error; + } else { + interp_add_ins (td, MINT_CALLI); + td->last_ins->data [1] = vt_stack_used; } + td->last_ins->data [0] = get_data_item_index (td, (void *)csignature); } else { InterpMethod *imethod = mono_interp_get_imethod (domain, target_method, error); + return_val_if_nok (error, FALSE); + + if (csignature->call_convention == MONO_CALL_VARARG) { + interp_add_ins (td, MINT_CALL_VARARG); + td->last_ins->data [1] = get_data_item_index (td, (void *)csignature); + } else if (is_virtual && !mono_class_is_marshalbyref (target_method->klass)) { + interp_add_ins (td, MINT_CALLVIRT_FAST); + if (mono_class_is_interface (target_method->klass)) + td->last_ins->data [1] = -2 * MONO_IMT_SIZE + mono_method_get_imt_slot (target_method); + else + td->last_ins->data [1] = mono_method_get_vtable_slot (target_method); + } else if (is_virtual) { + interp_add_ins (td, MINT_CALLVIRT); + td->last_ins->data [1] = imethod->param_count + imethod->hasthis; + } else { + interp_add_ins (td, MINT_CALL); + td->last_ins->data [1] = imethod->param_count + imethod->hasthis; + } td->last_ins->data [0] = get_data_item_index (td, (void *)imethod); - td->last_ins->data [1] = imethod->param_count + imethod->hasthis; + td->last_ins->data [2] = vt_stack_used; + #ifdef ENABLE_EXPERIMENT_TIERED if (MINT_IS_PATCHABLE_CALL (td->last_ins->opcode)) { g_assert (!calli && !is_virtual); @@ -2500,25 +2524,9 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target g_hash_table_insert (td->patchsite_hash, td->last_ins, target_method); } #endif - return_val_if_nok (error, FALSE); - if (csignature->call_convention == MONO_CALL_VARARG) - td->last_ins->data [1] = get_data_item_index (td, (void *)csignature); - else if (is_virtual && !mono_class_is_marshalbyref (target_method->klass)) { - /* FIXME Use fastpath also for MBRO. Asserts in mono_method_get_vtable_slot */ - if (mono_class_is_interface (target_method->klass)) - td->last_ins->data [1] = -2 * MONO_IMT_SIZE + mono_method_get_imt_slot (target_method); - else - td->last_ins->data [1] = mono_method_get_vtable_slot (target_method); - } } } td->ip += 5; - if (vt_stack_used != 0 || vt_res_size != 0) { - interp_add_ins (td, MINT_VTRESULT); - td->last_ins->data [0] = vt_res_size; - WRITE32_INS (td->last_ins, 1, &vt_stack_used); - td->vt_sp -= vt_stack_used; - } return TRUE; } @@ -3733,14 +3741,15 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, } case CEE_POP: CHECK_STACK(td, 1); - SIMPLE_OP(td, MINT_POP); if (td->sp [-1].type == STACK_TYPE_VT) { int size = mono_class_value_size (td->sp [-1].klass, NULL); size = ALIGN_TO (size, MINT_VT_ALIGNMENT); - interp_add_ins (td, MINT_VTRESULT); - td->last_ins->data [0] = 0; - WRITE32_INS (td->last_ins, 1, &size); + interp_add_ins (td, MINT_POP_VT); + WRITE32_INS (td->last_ins, 0, &size); td->vt_sp -= size; + td->ip++; + } else { + SIMPLE_OP(td, MINT_POP); } --td->sp; break; @@ -4604,6 +4613,10 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, interp_add_ins (td, MINT_NEWOBJ_ARRAY); td->last_ins->data [0] = get_data_item_index (td, m->klass); td->last_ins->data [1] = csignature->param_count; + } else if (klass == mono_defaults.string_class) { + interp_add_ins (td, MINT_NEWOBJ_STRING); + td->last_ins->data [0] = get_data_item_index (td, mono_interp_get_imethod (domain, m, error)); + td->last_ins->data [1] = csignature->param_count; } else if (m_class_get_image (klass) == mono_defaults.corlib && !strcmp (m_class_get_name (m->klass), "ByReference`1") && !strcmp (m->name, ".ctor")) { @@ -6425,16 +6438,10 @@ get_inst_stack_usage (TransformData *td, InterpInst *ins, int *pop, int *push) case MINT_JIT_CALL: case MINT_CALL: case MINT_CALLVIRT: - case MINT_CALLVIRT_FAST: - case MINT_VCALL: - case MINT_VCALLVIRT: - case MINT_VCALLVIRT_FAST: { + case MINT_CALLVIRT_FAST: { InterpMethod *imethod = (InterpMethod*) td->data_items [ins->data [0]]; *pop = imethod->param_count + imethod->hasthis; - if (opcode == MINT_JIT_CALL) - *push = imethod->rtype->type != MONO_TYPE_VOID; - else - *push = opcode == MINT_CALL || opcode == MINT_CALLVIRT || opcode == MINT_CALLVIRT_FAST; + *push = imethod->rtype->type != MONO_TYPE_VOID; break; } #ifndef ENABLE_NETCORE @@ -6453,6 +6460,7 @@ get_inst_stack_usage (TransformData *td, InterpInst *ins, int *pop, int *push) } case MINT_CALLI: case MINT_CALLI_NAT: + case MINT_CALLI_NAT_DYNAMIC: case MINT_CALLI_NAT_FAST: { MonoMethodSignature *csignature = (MonoMethodSignature*) td->data_items [ins->data [0]]; *pop = csignature->param_count + csignature->hasthis + 1; @@ -6483,6 +6491,7 @@ get_inst_stack_usage (TransformData *td, InterpInst *ins, int *pop, int *push) break; } case MINT_NEWOBJ_ARRAY: + case MINT_NEWOBJ_STRING: *pop = ins->data [1]; *push = 1; break; @@ -7335,7 +7344,7 @@ interp_cprop (TransformData *td) sp [-i].ins = NULL; memset (sp, 0, sizeof (StackContentInfo)); sp++; - } else if (ins->opcode == MINT_POP) { + } else if (ins->opcode == MINT_POP || ins->opcode == MINT_POP_VT) { sp--; if (sp->ins) { // The top of the stack is not used by any instructions. Kill both the diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index 6a833649fb02b..b50d3163996a8 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -67,6 +67,7 @@ ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared) { ERROR_DECL (error); MonoMethod *res; + gpointer addr; if (obj == NULL) { mono_error_set_null_reference (error); @@ -93,8 +94,28 @@ ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared) } /* An rgctx wrapper is added by the trampolines no need to do it here */ + gboolean need_unbox = m_class_is_valuetype (res->klass) && !m_class_is_valuetype (method->klass); + if (need_unbox) { + /* + * We can't return a jump trampoline here, because the trampoline code + * can't determine whenever to add an unbox trampoline (ldvirtftn) or + * not (ldftn). So compile the method here. + */ + addr = mono_compile_method_checked (res, error); + if (!is_ok (error)) { + mono_error_set_pending_exception (error); + return NULL; + } + + if (mono_llvm_only && mono_method_needs_static_rgctx_invoke (res, FALSE)) + // FIXME: + g_assert_not_reached (); - return mono_ldftn (res); + addr = mini_add_method_trampoline (res, addr, mono_method_needs_static_rgctx_invoke (res, FALSE), TRUE); + } else { + addr = mono_ldftn (res); + } + return addr; } void* @@ -1463,7 +1484,7 @@ ves_icall_mono_delegate_ctor (MonoObject *this_obj_raw, MonoObject *target_raw, mono_error_set_pending_exception (error); goto leave; } - mono_delegate_ctor (this_obj, target, addr, error); + mono_delegate_ctor (this_obj, target, addr, NULL, error); mono_error_set_pending_exception (error); leave: diff --git a/src/mono/mono/mini/llvm-intrinsics.h b/src/mono/mono/mini/llvm-intrinsics.h index 74b2ed3d62eff..f937df8bb8bf5 100644 --- a/src/mono/mono/mini/llvm-intrinsics.h +++ b/src/mono/mono/mini/llvm-intrinsics.h @@ -206,7 +206,10 @@ INTRINS(SSE_TESTZ, x86_sse41_ptestz) INTRINS(SSE_PBLENDVB, x86_sse41_pblendvb) INTRINS(SSE_BLENDVPS, x86_sse41_blendvps) INTRINS(SSE_BLENDVPD, x86_sse41_blendvpd) +#if LLVM_API_VERSION < 700 +// Clang 7 and above use a sequence of IR operations to represent pmuldq. INTRINS(SSE_PMULDQ, x86_sse41_pmuldq) +#endif INTRINS(SSE_PHMINPOSUW, x86_sse41_phminposuw) INTRINS(SSE_MPSADBW, x86_sse41_mpsadbw) INTRINS(PCLMULQDQ, x86_pclmulqdq) diff --git a/src/mono/mono/mini/llvm-jit.cpp b/src/mono/mono/mini/llvm-jit.cpp index 325e09c2cc383..1c16963c2909f 100644 --- a/src/mono/mono/mini/llvm-jit.cpp +++ b/src/mono/mono/mini/llvm-jit.cpp @@ -185,7 +185,7 @@ init_function_pass_manager (legacy::FunctionPassManager &fpm) } else { auto info = reg->getPassInfo (pass->getPassID()); auto name = info->getPassArgument (); - printf("Opt pass is ignored: %.*s\n", name.size(), name.data()); + printf("Opt pass is ignored: %.*s\n", (int) name.size(), name.data()); } } // -place-safepoints pass is mandatory diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 8a8a5b070637b..7907193b5e0ff 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -1035,6 +1035,16 @@ mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code) return (MonoVTable*)regs [MONO_ARCH_RGCTX_REG]; } +GSList* +mono_arch_get_cie_program (void) +{ + GSList *l = NULL; + + mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ARMREG_SP, 0); + + return l; +} + host_mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg) { diff --git a/src/mono/mono/mini/mini-generic-sharing.c b/src/mono/mono/mini/mini-generic-sharing.c index 9bf9c2cf528e8..7ef020e8c5548 100644 --- a/src/mono/mono/mini/mini-generic-sharing.c +++ b/src/mono/mono/mini/mini-generic-sharing.c @@ -26,6 +26,7 @@ #include "aot-runtime.h" #include "mini-runtime.h" #include "llvmonly-runtime.h" +#include "interp/interp.h" #define ALLOW_PARTIAL_SHARING TRUE //#define ALLOW_PARTIAL_SHARING FALSE @@ -1335,8 +1336,10 @@ get_wrapper_shared_type (MonoType *t) /* Returns the intptr type for types that are passed in a single register */ static MonoType* -get_wrapper_shared_type_reg (MonoType *t) +get_wrapper_shared_type_reg (MonoType *t, gboolean pinvoke) { + MonoType *orig_t = t; + t = get_wrapper_shared_type (t); if (t->byref) return t; @@ -1364,6 +1367,15 @@ get_wrapper_shared_type_reg (MonoType *t) case MONO_TYPE_ARRAY: case MONO_TYPE_PTR: return mono_get_int_type (); + case MONO_TYPE_GENERICINST: + if (orig_t->type == MONO_TYPE_VALUETYPE && pinvoke) + /* + * These are translated to instances of Mono.ValueTuple, but generic types + * cannot be passed in pinvoke. + */ + return orig_t; + else + return t; default: return t; } @@ -1375,9 +1387,9 @@ mini_get_underlying_reg_signature (MonoMethodSignature *sig) MonoMethodSignature *res = mono_metadata_signature_dup (sig); int i; - res->ret = get_wrapper_shared_type_reg (sig->ret); + res->ret = get_wrapper_shared_type_reg (sig->ret, sig->pinvoke); for (i = 0; i < sig->param_count; ++i) - res->params [i] = get_wrapper_shared_type_reg (sig->params [i]); + res->params [i] = get_wrapper_shared_type_reg (sig->params [i], sig->pinvoke); res->generic_param_count = 0; res->is_inflated = 0; @@ -1700,7 +1712,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) return res; } - if (sig->param_count > 8) + if (sig->param_count > MAX_INTERP_ENTRY_ARGS) /* Call the generic interpreter entry point, the specialized ones only handle a limited number of arguments */ generic = TRUE; diff --git a/src/mono/mono/mini/mini-llvm-cpp.cpp b/src/mono/mono/mini/mini-llvm-cpp.cpp index cbe40546561f7..e9ef878222294 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.cpp +++ b/src/mono/mono/mini/mini-llvm-cpp.cpp @@ -229,6 +229,13 @@ mono_llvm_build_weighted_branch (LLVMBuilderRef builder, LLVMValueRef cond, LLVM return wrap (ins); } +LLVMValueRef +mono_llvm_build_exact_ashr (LLVMBuilderRef builder, LLVMValueRef lhs, LLVMValueRef rhs) { + auto b = unwrap (builder); + auto ins = b->CreateAShr (unwrap (lhs), unwrap (rhs), "", true); + return wrap (ins); +} + void mono_llvm_add_string_metadata (LLVMValueRef insref, const char* label, const char* text) { diff --git a/src/mono/mono/mini/mini-llvm-cpp.h b/src/mono/mono/mini/mini-llvm-cpp.h index d9b2e427c7932..9173b6341e4f6 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.h +++ b/src/mono/mono/mini/mini-llvm-cpp.h @@ -104,6 +104,9 @@ mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef addr, LLVMValueRef LLVMValueRef mono_llvm_build_weighted_branch (LLVMBuilderRef builder, LLVMValueRef cond, LLVMBasicBlockRef t, LLVMBasicBlockRef f, uint32_t t_weight, uint32_t f_weight); +LLVMValueRef +mono_llvm_build_exact_ashr (LLVMBuilderRef builder, LLVMValueRef lhs, LLVMValueRef rhs); + void mono_llvm_add_string_metadata (LLVMValueRef insref, const char* label, const char* text); diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index f5aef1fd1b396..fa99c276130ed 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -4572,14 +4572,19 @@ emit_landing_pad (EmitContext *ctx, int group_index, int group_size) } static LLVMValueRef -create_const_vector_i32 (const int *mask, int count) +create_const_vector (LLVMTypeRef t, const int *vals, int count) { - LLVMValueRef *llvm_mask = g_new (LLVMValueRef, count); + g_assert (count <= 16); + LLVMValueRef llvm_vals [16]; for (int i = 0; i < count; i++) - llvm_mask [i] = LLVMConstInt (LLVMInt32Type (), mask [i], FALSE); - LLVMValueRef vec = LLVMConstVector (llvm_mask, count); - g_free (llvm_mask); - return vec; + llvm_vals [i] = LLVMConstInt (t, vals [i], FALSE); + return LLVMConstVector (llvm_vals, count); +} + +static LLVMValueRef +create_const_vector_i32 (const int *mask, int count) +{ + return create_const_vector (LLVMInt32Type (), mask, count); } static LLVMValueRef @@ -8582,10 +8587,23 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) } case OP_SSE41_MUL: { - // NOTE: LLVM 7 and later use shifts here - // however, pmuldq is still available so I guess it's fine to keep using it +#if LLVM_API_VERSION < 700 LLVMValueRef args [] = { lhs, rhs }; values [ins->dreg] = call_intrins (ctx, INTRINS_SSE_PMULDQ, args, dname); +#else + const int shift_vals [] = { 32, 32 }; + const LLVMValueRef args [] = { + convert (ctx, lhs, sse_i8_t), + convert (ctx, rhs, sse_i8_t), + }; + LLVMValueRef mul_args [2] = { 0 }; + LLVMValueRef shift_vec = create_const_vector (LLVMInt64Type (), shift_vals, 2); + for (int i = 0; i < 2; ++i) { + LLVMValueRef padded = LLVMBuildShl (builder, args [i], shift_vec, ""); + mul_args[i] = mono_llvm_build_exact_ashr (builder, padded, shift_vec); + } + values [ins->dreg] = LLVMBuildNSWMul (builder, mul_args [0], mul_args [1], dname); +#endif break; } diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index a8bac8f41474f..ca2a59cf11a20 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -74,6 +74,10 @@ #include #include +#ifdef ENABLE_PERFTRACING +#include +#endif + #include "mini.h" #include "seq-points.h" #include "tasklets.h" @@ -516,6 +520,7 @@ mono_tramp_info_register_internal (MonoTrampInfo *info, MonoDomain *domain, gboo copy->code = info->code; copy->code_size = info->code_size; copy->name = g_strdup (info->name); + copy->method = info->method; if (info->unwind_ops) { copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, ©->uw_info_len); @@ -546,8 +551,8 @@ mono_tramp_info_register_internal (MonoTrampInfo *info, MonoDomain *domain, gboo mono_jit_lock (); tramp_infos = g_slist_prepend (tramp_infos, copy); mono_jit_unlock (); - } else if (copy->uw_info) { - /* Only register trampolines that have unwind infos */ + } else if (copy->uw_info || info->method) { + /* Only register trampolines that have unwind info */ register_trampoline_jit_info (domain, copy); } @@ -3748,7 +3753,7 @@ create_delegate_method_ptr (MonoMethod *method, MonoError *error) func = mono_compile_method_checked (method, error); return_val_if_nok (error, NULL); } else { - gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, error); + gpointer trampoline = mono_create_jump_trampoline (mono_domain_get (), method, TRUE, error); return_val_if_nok (error, NULL); func = mono_create_ftnptr (mono_domain_get (), trampoline); } @@ -3756,9 +3761,52 @@ create_delegate_method_ptr (MonoMethod *method, MonoError *error) } static void -mini_init_delegate (MonoDelegateHandle delegate, MonoError *error) +mini_init_delegate (MonoDelegateHandle delegate, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error) { MonoDelegate *del = MONO_HANDLE_RAW (delegate); + MonoDomain *domain = MONO_HANDLE_DOMAIN (delegate); + + if (!method) { + MonoJitInfo *ji; + + g_assert (addr); + ji = mono_jit_info_table_find_internal (domain, mono_get_addr_from_ftnptr (addr), TRUE, TRUE); + /* Shared code */ + if (!ji && domain != mono_get_root_domain ()) + ji = mono_jit_info_table_find_internal (mono_get_root_domain (), mono_get_addr_from_ftnptr (addr), TRUE, TRUE); + if (ji) { + if (ji->is_trampoline) { + /* Could be an unbox trampoline etc. */ + method = ji->d.tramp_info->method; + } else { + method = mono_jit_info_get_method (ji); + g_assert (!mono_class_is_gtd (method->klass)); + } + } + } + + if (method) + MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method); + + if (addr) + MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, addr); + +#ifndef DISABLE_REMOTING + if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) { + if (mono_use_interpreter) { + MONO_HANDLE_SETVAL (delegate, interp_method, gpointer, mini_get_interp_callbacks ()->get_remoting_invoke (method, addr, error)); + } else { + g_assert (method); + method = mono_marshal_get_remoting_invoke (method, error); + return_if_nok (error); + MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, mono_compile_method_checked (method, error)); + } + return_if_nok (error); + } +#endif + + MONO_HANDLE_SET (delegate, target, target); + MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, mono_create_delegate_trampoline (domain, mono_handle_class (delegate))); if (mono_use_interpreter) { mini_get_interp_callbacks ()->init_delegate (del, error); @@ -4377,7 +4425,6 @@ mini_init (const char *filename, const char *runtime_version) #define JIT_TRAMPOLINES_WORK #ifdef JIT_TRAMPOLINES_WORK callbacks.compile_method = mono_jit_compile_method; - callbacks.create_jump_trampoline = mono_create_jump_trampoline; callbacks.create_jit_trampoline = mono_create_jit_trampoline; callbacks.create_delegate_trampoline = mono_create_delegate_trampoline; callbacks.free_method = mono_jit_free_method; @@ -4488,6 +4535,10 @@ mini_init (const char *filename, const char *runtime_version) mono_install_get_class_from_name (mono_aot_get_class_from_name); mono_install_jit_info_find_in_aot (mono_aot_find_jit_info); +#ifdef ENABLE_PERFTRACING + ep_init (); +#endif + mono_profiler_state.context_enable = mini_profiler_context_enable; mono_profiler_state.context_get_this = mini_profiler_context_get_this; mono_profiler_state.context_get_argument = mini_profiler_context_get_argument; @@ -4949,6 +5000,9 @@ mini_cleanup (MonoDomain *domain) mono_runtime_print_stats (); jit_stats_cleanup (); mono_jit_dump_cleanup (); +#ifdef ENABLE_PERFTRACING + ep_shutdown (); +#endif } #else void diff --git a/src/mono/mono/mini/mini-wasm-debugger.c b/src/mono/mono/mini/mini-wasm-debugger.c index 10238975b3511..603b331d1f0ba 100644 --- a/src/mono/mono/mini/mini-wasm-debugger.c +++ b/src/mono/mono/mini/mini-wasm-debugger.c @@ -37,6 +37,7 @@ EMSCRIPTEN_KEEPALIVE int mono_wasm_setup_single_step (int kind); EMSCRIPTEN_KEEPALIVE void mono_wasm_get_object_properties (int object_id, gboolean expand_value_types); EMSCRIPTEN_KEEPALIVE void mono_wasm_get_array_values (int object_id); EMSCRIPTEN_KEEPALIVE void mono_wasm_get_array_value_expanded (int object_id, int idx); +EMSCRIPTEN_KEEPALIVE void mono_wasm_invoke_getter_on_object (int object_id, const char* name); //JS functions imported that we use extern void mono_wasm_add_frame (int il_offset, int method_token, const char *assembly_name, const char *method_name); @@ -955,6 +956,26 @@ are_getters_allowed (const char *class_name) return FALSE; } +static void +invoke_and_describe_getter_value (MonoObject *obj, MonoProperty *p) +{ + ERROR_DECL (error); + MonoObject *res; + MonoObject *exc; + + MonoMethodSignature *sig = mono_method_signature_internal (p->get); + + res = mono_runtime_try_invoke (p->get, obj, NULL, &exc, error); + if (!is_ok (error) && exc == NULL) + exc = (MonoObject*) mono_error_convert_to_exception (error); + if (exc) + describe_value (mono_get_object_type (), &exc, TRUE); + else if (!res || !m_class_is_valuetype (mono_object_class (res))) + describe_value (sig->ret, &res, TRUE); + else + describe_value (sig->ret, mono_object_unbox_internal (res), TRUE); +} + static void describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAsyncLocalThis, gboolean expandValueType) { @@ -962,7 +983,6 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs MonoProperty *p; MonoMethodSignature *sig; gpointer iter = NULL; - ERROR_DECL (error); gboolean is_valuetype; int pnum; char *klass_name; @@ -1004,11 +1024,7 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs iter = NULL; pnum = 0; while ((p = mono_class_get_properties (klass, &iter))) { - DEBUG_PRINTF (2, "mono_class_get_properties - %s - %s\n", p->name, p->get->name); if (p->get->name) { //if get doesn't have name means that doesn't have a getter implemented and we don't want to show value, like VS debug - MonoObject *res; - MonoObject *exc; - if (isAsyncLocalThis && (p->name[0] != '<' || (p->name[0] == '<' && p->name[1] == '>'))) continue; @@ -1019,9 +1035,12 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs if (!getters_allowed) { // not allowed to call the getter here char *ret_class_name = mono_class_full_name (mono_class_from_mono_type_internal (sig->ret)); - mono_wasm_add_typed_value ("getter", ret_class_name, 0); - g_free (ret_class_name); + // getters not supported for valuetypes, yet + gboolean invokable = !is_valuetype && sig->param_count == 0; + mono_wasm_add_typed_value ("getter", ret_class_name, invokable); + + g_free (ret_class_name); continue; } @@ -1031,15 +1050,7 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs continue; } - res = mono_runtime_try_invoke (p->get, obj, NULL, &exc, error); - if (!is_ok (error) && exc == NULL) - exc = (MonoObject*) mono_error_convert_to_exception (error); - if (exc) - describe_value (mono_get_object_type (), &exc, TRUE); - else if (!res || !m_class_is_valuetype (mono_object_class (res))) - describe_value (sig->ret, &res, TRUE); - else - describe_value (sig->ret, mono_object_unbox_internal (res), TRUE); + invoke_and_describe_getter_value (obj, p); } pnum ++; } @@ -1093,6 +1104,36 @@ describe_object_properties (guint64 objectId, gboolean isAsyncLocalThis, gboolea return TRUE; } +static gboolean +invoke_getter_on_object (guint64 objectId, const char *name) +{ + ObjRef *ref = (ObjRef *)g_hash_table_lookup (objrefs, GINT_TO_POINTER (objectId)); + if (!ref) { + DEBUG_PRINTF (1, "invoke_getter_on_object no objRef found for id %llu\n", objectId); + return FALSE; + } + + MonoObject *obj = mono_gchandle_get_target_internal (ref->handle); + if (!obj) { + DEBUG_PRINTF (1, "invoke_getter_on_object !obj\n"); + return FALSE; + } + + MonoClass *klass = mono_object_class (obj); + gpointer iter = NULL; + MonoProperty *p; + while ((p = mono_class_get_properties (klass, &iter))) { + //if get doesn't have name means that doesn't have a getter implemented and we don't want to show value, like VS debug + if (!p->get->name || strcasecmp (p->name, name) != 0) + continue; + + invoke_and_describe_getter_value (obj, p); + return TRUE; + } + + return FALSE; +} + static gboolean describe_array_values (guint64 objectId) { @@ -1277,6 +1318,11 @@ mono_wasm_get_array_value_expanded (int object_id, int idx) describe_array_value_expanded (object_id, idx); } +EMSCRIPTEN_KEEPALIVE void +mono_wasm_invoke_getter_on_object (int object_id, const char* name) +{ + invoke_getter_on_object (object_id, name); +} // Functions required by debugger-state-machine. gsize mono_debugger_tls_thread_id (DebuggerTlsData *debuggerTlsData) diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index 8f1eef7f0c150..70e182efef6cb 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -455,6 +455,14 @@ mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code) return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG]; } +GSList* +mono_arch_get_cie_program (void) +{ + GSList *l = NULL; + + return l; +} + gpointer mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) { diff --git a/src/mono/mono/mini/mini-x86.c b/src/mono/mono/mini/mini-x86.c index 464dc5d969d61..e717acdec8527 100644 --- a/src/mono/mono/mini/mini-x86.c +++ b/src/mono/mono/mini/mini-x86.c @@ -567,6 +567,112 @@ static gboolean storage_in_ireg (ArgStorage storage) return (storage == ArgInIReg || storage == ArgValuetypeInReg); } +static int +arg_need_temp (ArgInfo *ainfo) +{ + /* + * We always fetch the double value from the fpstack. In that case, we + * need to have a separate tmp that is the double value casted to float + */ + if (ainfo->storage == ArgOnFloatFpStack) + return sizeof (float); + return 0; +} + +static gpointer +arg_get_storage (CallContext *ccontext, ArgInfo *ainfo) +{ + switch (ainfo->storage) { + case ArgOnStack: + return ccontext->stack + ainfo->offset; + case ArgOnDoubleFpStack: + return &ccontext->fret; + case ArgInIReg: + /* If pair, the storage is for EDX:EAX */ + return &ccontext->eax; + default: + g_error ("Arg storage type not yet supported"); + } +} + +static void +arg_get_val (CallContext *ccontext, ArgInfo *ainfo, gpointer dest) +{ + g_assert (ainfo->storage == ArgOnFloatFpStack); + + *(float*) dest = (float)ccontext->fret; +} + +void +mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) +{ + CallInfo *cinfo = get_call_info (NULL, sig); + const MonoEECallbacks *interp_cb = mini_get_interp_callbacks (); + gpointer storage; + ArgInfo *ainfo; + + memset (ccontext, 0, sizeof (CallContext)); + + ccontext->stack_size = ALIGN_TO (cinfo->stack_usage, MONO_ARCH_FRAME_ALIGNMENT); + if (ccontext->stack_size) + ccontext->stack = (guint8*)g_calloc (1, ccontext->stack_size); + + if (sig->ret->type != MONO_TYPE_VOID) { + ainfo = &cinfo->ret; + if (ainfo->storage == ArgOnStack) { + /* This is a value type return. The pointer to vt storage is pushed as first argument */ + g_assert (ainfo->offset == 0); + g_assert (ainfo->nslots == 1); + storage = interp_cb->frame_arg_to_storage ((MonoInterpFrameHandle)frame, sig, -1); + *(host_mgreg_t*)ccontext->stack = (host_mgreg_t)storage; + } + } + + g_assert (!sig->hasthis); + + for (int i = 0; i < sig->param_count; i++) { + ainfo = &cinfo->args [i]; + + storage = arg_get_storage (ccontext, ainfo); + + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, i, storage); + } + + g_free (cinfo); +} + +void +mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig) +{ + const MonoEECallbacks *interp_cb; + CallInfo *cinfo; + ArgInfo *ainfo; + gpointer storage; + + /* No return value */ + if (sig->ret->type == MONO_TYPE_VOID) + return; + + interp_cb = mini_get_interp_callbacks (); + cinfo = get_call_info (NULL, sig); + ainfo = &cinfo->ret; + + /* Check if return value was stored directly at address passed in reg */ + if (cinfo->ret.storage != ArgOnStack) { + int temp_size = arg_need_temp (ainfo); + + if (temp_size) { + storage = alloca (temp_size); + arg_get_val (ccontext, ainfo, storage); + } else { + storage = arg_get_storage (ccontext, ainfo); + } + interp_cb->data_to_frame_arg ((MonoInterpFrameHandle)frame, sig, -1, storage); + } + + g_free (cinfo); +} + /* * mono_arch_get_argument_info: * @csig: a method signature diff --git a/src/mono/mono/mini/mini-x86.h b/src/mono/mono/mini/mini-x86.h index 6791b57074e9f..6d44cb5f2bf18 100644 --- a/src/mono/mono/mini/mini-x86.h +++ b/src/mono/mono/mini/mini-x86.h @@ -204,6 +204,10 @@ typedef struct { #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1 +#define MONO_ARCH_INTERPRETER_SUPPORTED 1 +#define MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED 1 +#define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP 1 + #define MONO_ARCH_HAVE_CMOV_OPS 1 #ifdef MONO_ARCH_SIMD_INTRINSICS @@ -332,6 +336,17 @@ struct CallInfo { ArgInfo args [1]; }; +typedef struct { + /* EAX:EDX */ + host_mgreg_t eax; + host_mgreg_t edx; + /* Floating point return value read from the top of x86 fpstack */ + double fret; + /* Stack usage, used for passing params on stack */ + guint32 stack_size; + guint8 *stack; +} CallContext; + guint32 mono_x86_get_this_arg_offset (MonoMethodSignature *sig); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 0e632d0f4f617..1d09d6d4668d4 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -1943,8 +1943,8 @@ enum { /* * Information about a trampoline function. */ - struct MonoTrampInfo - { +struct MonoTrampInfo +{ /* * The native code of the trampoline. Not owned by this structure. */ @@ -1966,6 +1966,11 @@ enum { MonoJitICallInfo *jit_icall_info; + /* + * The method the trampoline is associated with, if any. + */ + MonoMethod *method; + /* * Encoded unwind info loaded from AOT images */ diff --git a/src/mono/mono/mini/monovm.c b/src/mono/mono/mini/monovm.c index d1aff44ed68f6..32185645d985f 100644 --- a/src/mono/mono/mini/monovm.c +++ b/src/mono/mono/mini/monovm.c @@ -181,6 +181,9 @@ parse_properties (int propertyCount, const char **propertyKeys, const char **pro } else if (prop_len == 30 && !strncmp (propertyKeys [i], "System.Globalization.Invariant", 30)) { // TODO: Ideally we should propagate this through AppContext options g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", propertyValues [i], TRUE); + } else if (prop_len == 27 && !strncmp (propertyKeys [i], "System.Globalization.UseNls", 27)) { + // TODO: Ideally we should propagate this through AppContext options + g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_USENLS", propertyValues [i], TRUE); } else { #if 0 // can't use mono logger, it's not initialized yet. diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c index ea4c1a9574c02..50f904bcd0fee 100644 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ b/src/mono/mono/mini/simd-intrinsics-netcore.c @@ -4,6 +4,7 @@ #include #include +#include "mini.h" #if defined(DISABLE_JIT) @@ -18,7 +19,6 @@ mono_simd_intrinsics_init (void) * Only LLVM is supported as a backend. */ -#include "mini.h" #include "mini-runtime.h" #include "ir-emit.h" #ifdef ENABLE_LLVM diff --git a/src/mono/mono/mini/tramp-x86.c b/src/mono/mono/mini/tramp-x86.c index 196a3bf9ad818..10900c8113d71 100644 --- a/src/mono/mono/mini/tramp-x86.c +++ b/src/mono/mono/mini/tramp-x86.c @@ -719,3 +719,92 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo return buf; } + +gpointer +mono_arch_get_interp_to_native_trampoline (MonoTrampInfo **info) +{ +#ifndef DISABLE_INTERPRETER + guint8 *start = NULL, *code; + guint8 *label_start_copy, *label_exit_copy; + MonoJumpInfo *ji = NULL; + GSList *unwind_ops = NULL; + int buf_len; + int ccontext_offset, target_offset; + + buf_len = 512; + start = code = (guint8 *) mono_global_codeman_reserve (buf_len); + + x86_push_reg (code, X86_EBP); + /* args are on the stack, above saved EBP and pushed return EIP */ + target_offset = 2 * sizeof (target_mgreg_t); + ccontext_offset = target_offset + sizeof (target_mgreg_t); + x86_mov_reg_reg (code, X86_EBP, X86_ESP); + + /* Save some used regs and align stack to 16 bytes */ + x86_push_reg (code, X86_EDI); + x86_push_reg (code, X86_ESI); + + /* load pointer to CallContext* into ESI */ + x86_mov_reg_membase (code, X86_ESI, X86_EBP, ccontext_offset, sizeof (target_mgreg_t)); + + /* allocate the stack space necessary for the call */ + x86_mov_reg_membase (code, X86_ECX, X86_ESI, MONO_STRUCT_OFFSET (CallContext, stack_size), sizeof (target_mgreg_t)); + x86_alu_reg_reg (code, X86_SUB, X86_ESP, X86_ECX); + + /* copy stack from the CallContext, ESI = source, EDI = dest, ECX bytes to copy */ + x86_mov_reg_membase (code, X86_ESI, X86_ESI, MONO_STRUCT_OFFSET (CallContext, stack), sizeof (target_mgreg_t)); + x86_mov_reg_reg (code, X86_EDI, X86_ESP); + + label_start_copy = code; + x86_test_reg_reg (code, X86_ECX, X86_ECX); + label_exit_copy = code; + x86_branch8 (code, X86_CC_Z, 0, FALSE); + x86_mov_reg_membase (code, X86_EDX, X86_ESI, 0, sizeof (target_mgreg_t)); + x86_mov_membase_reg (code, X86_EDI, 0, X86_EDX, sizeof (target_mgreg_t)); + x86_alu_reg_imm (code, X86_ADD, X86_EDI, sizeof (target_mgreg_t)); + x86_alu_reg_imm (code, X86_ADD, X86_ESI, sizeof (target_mgreg_t)); + x86_alu_reg_imm (code, X86_SUB, X86_ECX, sizeof (target_mgreg_t)); + x86_jump_code (code, label_start_copy); + x86_patch (label_exit_copy, code); + + /* load target addr */ + x86_mov_reg_membase (code, X86_EAX, X86_EBP, target_offset, sizeof (target_mgreg_t)); + + /* call into native function */ + x86_call_reg (code, X86_EAX); + + /* Save return values into CallContext* */ + x86_mov_reg_membase (code, X86_ESI, X86_EBP, ccontext_offset, sizeof (target_mgreg_t)); + x86_mov_membase_reg (code, X86_ESI, MONO_STRUCT_OFFSET (CallContext, eax), X86_EAX, sizeof (target_mgreg_t)); + x86_mov_membase_reg (code, X86_ESI, MONO_STRUCT_OFFSET (CallContext, edx), X86_EDX, sizeof (target_mgreg_t)); + + /* + * We always pop ST0, even if we don't have return value. We seem to get away with + * this because fpstack is either empty or has one fp return value on top and the cpu + * doesn't trap if we read top of empty stack. + */ + x86_fst_membase (code, X86_ESI, MONO_STRUCT_OFFSET (CallContext, fret), TRUE, TRUE); + + /* restore ESI, EDI which were saved below rbp */ + x86_mov_reg_membase (code, X86_EDI, X86_EBP, - sizeof (target_mgreg_t), sizeof (target_mgreg_t)); + x86_mov_reg_membase (code, X86_ESI, X86_EBP, - 2 * sizeof (target_mgreg_t), sizeof (target_mgreg_t)); + x86_mov_reg_reg (code, X86_ESP, X86_EBP); + + x86_pop_reg (code, X86_EBP); + + x86_ret (code); + + g_assertf ((code - start) <= buf_len, "%d %d", (int)(code - start), buf_len); + + mono_arch_flush_icache (start, code - start); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_HELPER, NULL)); + + if (info) + *info = mono_tramp_info_create ("interp_to_native_trampoline", start, code - start, ji, unwind_ops); + + return start; +#else + g_assert_not_reached (); + return NULL; +#endif /* DISABLE_INTERPRETER */ +} diff --git a/src/mono/mono/tests/Makefile.am b/src/mono/mono/tests/Makefile.am index 566388ce2e457..6b20fc9c525b8 100755 --- a/src/mono/mono/tests/Makefile.am +++ b/src/mono/mono/tests/Makefile.am @@ -1947,72 +1947,17 @@ INTERP_DISABLED_TESTS += calli_sig_check.exe # Test is too sensitive. INTERP_DISABLED_TESTS += localloc-noinit.exe - -# bug-48015.exe: be careful when re-enabling, it happens that it returns with exit code 0, but doesn't actually execute the test. +INTERP_DISABLED_TESTS += dim-diamondshape.exe +INTERP_DISABLED_TESTS += pinvoke3.exe +INTERP_DISABLED_TESTS += cominterop.exe # bug-60862.exe: missing support to map IP->method; only works on platforms with altstack support. -# bug-60843.exe: something goes wrong when turning the decoded enum value into a boxed enum, so the loaded value ends up being random bytes - -if ARM -INTERP_DISABLED_TESTS += \ - appdomain-unload-callback.exe \ - appdomain-unload.exe \ - assemblyresolve_event6.exe \ - async-with-cb-throws.exe \ - block_guard_restore_aligment_on_exit.exe \ - bug-323114.exe \ - bug-335131.2.exe \ - bug-415577.exe \ - bug-45841-fpstack-exceptions.exe \ - bug-48015.exe \ - bug-60862.exe \ - bug-80307.exe \ - bug-80392.2.exe \ - bug445361.exe \ - calliGenericTest.exe \ - cominterop.exe \ - context-static.exe \ - delegate-async-exit.exe \ - delegate-delegate-exit.exe \ - delegate-exit.exe \ - delegate1.exe \ - delegate3.exe \ - delegate5.exe \ - delegate8.exe \ - delegate9.exe \ - dim-diamondshape.exe \ - dynamic-method-stack-traces.exe \ - even-odd.exe \ - exception18.exe \ - field-access.exe \ - finalizer-exception.exe \ - handleref.exe \ - monitor-abort.exe \ - nullable_boxing.2.exe \ - pinvoke2.exe \ - pinvoke3.exe \ - remoting2.exe \ - remoting3.exe \ - safehandle.2.exe \ - stackframes-async.2.exe \ - static-constructor.exe \ - threadpool-exceptions2.exe \ - threadpool-exceptions3.exe \ - threadpool-exceptions4.exe \ - threadpool-exceptions5.exe \ - threadpool-exceptions6.exe \ - thunks.exe \ - typeload-unaligned.exe \ - vararg.exe \ - vararg2.exe \ - vararg3.exe -endif +INTERP_DISABLED_TESTS += bug-60862.exe +# bug-48015.exe: remoting test that fails on fullaotinterp scenarios +INTERP_DISABLED_TESTS += bug-48015.exe if ARM64 INTERP_DISABLED_TESTS += \ - bug-48015.exe \ - bug-80307.exe \ - dim-diamondshape.exe \ - pinvoke3.exe + bug-80307.exe # Test is too sensitive. DISABLED_TESTS += localloc-noinit.exe @@ -2024,16 +1969,6 @@ if HOST_WIN32 DISABLED_TESTS += localloc-noinit.exe endif -if AMD64 -INTERP_DISABLED_TESTS += \ - assemblyresolve_event6.exe \ - bug-48015.exe \ - bug-60862.exe \ - cominterop.exe \ - dim-diamondshape.exe \ - pinvoke3.exe -endif - TESTS_CS=$(filter-out $(DISABLED_TESTS),$(TESTS_CS_SRC:.cs=.exe)) TESTS_IL=$(filter-out $(DISABLED_TESTS),$(TESTS_IL_SRC:.il=.exe)) TESTS_BENCH=$(filter-out $(DISABLED_TESTS),$(TESTS_BENCH_SRC:.cs=.exe)) diff --git a/src/mono/mono/tools/offsets-tool/offsets-tool.py b/src/mono/mono/tools/offsets-tool/offsets-tool.py index d44e436e22985..f9f7170aac319 100644 --- a/src/mono/mono/tools/offsets-tool/offsets-tool.py +++ b/src/mono/mono/tools/offsets-tool/offsets-tool.py @@ -125,6 +125,11 @@ def require_emscipten_path (args): self.target = Target ("TARGET_ARM64", "TARGET_IOS", IOS_DEFINES) self.target_args += ["-arch", "arm64"] self.target_args += ["-isysroot", args.sysroot] + elif "i386-apple-darwin10" == args.abi: + require_sysroot (args) + self.target = Target ("TARGET_X86", "", IOS_DEFINES) + self.target_args += ["-arch", "i386"] + self.target_args += ["-isysroot", args.sysroot] # watchOS elif "armv7k-apple-darwin" == args.abi: diff --git a/src/mono/mono/utils/mono-dl-posix.c b/src/mono/mono/utils/mono-dl-posix.c index 1900a1acf5621..a6c767c8285db 100644 --- a/src/mono/mono/utils/mono-dl-posix.c +++ b/src/mono/mono/utils/mono-dl-posix.c @@ -136,10 +136,10 @@ mono_dl_convert_flags (int flags) #ifdef ENABLE_NETCORE // Specifying both will default to LOCAL - if (flags & MONO_DL_LOCAL) - lflags |= RTLD_LOCAL; - else if (flags & MONO_DL_GLOBAL) + if (flags & MONO_DL_GLOBAL && !(flags & MONO_DL_LOCAL)) lflags |= RTLD_GLOBAL; + else + lflags |= RTLD_LOCAL; #else lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL; #endif diff --git a/src/mono/mono/utils/mono-dl.c b/src/mono/mono/utils/mono-dl.c index 8b4aedd179ac9..32fc1daed7dbc 100644 --- a/src/mono/mono/utils/mono-dl.c +++ b/src/mono/mono/utils/mono-dl.c @@ -21,6 +21,9 @@ #include #include #include +#if defined(ENABLE_NETCORE) && defined(TARGET_ANDROID) +#include +#endif // Contains LIBC_SO definition #ifdef HAVE_GNU_LIB_NAMES_H @@ -168,6 +171,37 @@ fix_libc_name (const char *name) } #endif +/** + * mono_dl_open_self: + * \param error_msg pointer for error message on failure + * + * Returns a handle to the main program, on android x86 it's not possible to + * call dl_open(null), it returns a null handle, so this function returns RTLD_DEFAULT + * handle in this platform. + */ +MonoDl* +mono_dl_open_self (char **error_msg) +{ +#if defined(ENABLE_NETCORE) && defined(TARGET_ANDROID) + MonoDl *module; + if (error_msg) + *error_msg = NULL; + module = (MonoDl *) g_malloc (sizeof (MonoDl)); + if (!module) { + if (error_msg) + *error_msg = g_strdup ("Out of memory"); + return NULL; + } + mono_refcount_init (module, NULL); + module->handle = RTLD_DEFAULT; + module->dl_fallback = NULL; + module->full_name = NULL; + return module; +#else + return mono_dl_open (NULL, MONO_DL_LAZY, error_msg); +#endif +} + /** * mono_dl_open: * \param name name of file containing shared module diff --git a/src/mono/mono/utils/mono-dl.h b/src/mono/mono/utils/mono-dl.h index 6236d98b1e59b..6efee6feabfd5 100644 --- a/src/mono/mono/utils/mono-dl.h +++ b/src/mono/mono/utils/mono-dl.h @@ -43,6 +43,8 @@ char* mono_dl_build_path (const char *directory, const char *name, void ** MonoDl* mono_dl_open_runtime_lib (const char *lib_name, int flags, char **error_msg); +MonoDl* mono_dl_open_self (char **error_msg); + //Platform API for mono_dl const char* mono_dl_get_so_prefix (void); diff --git a/src/mono/mono/utils/mono-sigcontext.h b/src/mono/mono/utils/mono-sigcontext.h index be0fbce43189d..9a73dff7c520c 100644 --- a/src/mono/mono/utils/mono-sigcontext.h +++ b/src/mono/mono/utils/mono-sigcontext.h @@ -324,6 +324,9 @@ typedef struct ucontext { #endif #if defined(__linux__) + +/* don't rely on glibc to include this for us, musl won't */ +#include typedef ucontext_t os_ucontext; #ifdef __mono_ppc64__ diff --git a/src/mono/mono/utils/mono-state.c b/src/mono/mono/utils/mono-state.c index 717c88cfb07a9..7333818f3a2a7 100644 --- a/src/mono/mono/utils/mono-state.c +++ b/src/mono/mono/utils/mono-state.c @@ -1202,22 +1202,6 @@ mono_crash_dump (const char *jsonFile, MonoStackHash *hashes) return; } -#endif // DISABLE_CRASH_REPORTING - -static volatile int32_t dump_status; - -gboolean -mono_dump_start (void) -{ - return (mono_atomic_xchg_i32(&dump_status, 1) == 0); // return true if we started the dump -} - -gboolean -mono_dump_complete (void) -{ - return (mono_atomic_xchg_i32(&dump_status, 0) == 1); // return true if we completed the dump -} - static char *saved_failfast_msg; /** @@ -1237,3 +1221,19 @@ mono_crash_get_failfast_msg (void) { return saved_failfast_msg; } + +#endif // DISABLE_CRASH_REPORTING + +static volatile int32_t dump_status; + +gboolean +mono_dump_start (void) +{ + return (mono_atomic_xchg_i32(&dump_status, 1) == 0); // return true if we started the dump +} + +gboolean +mono_dump_complete (void) +{ + return (mono_atomic_xchg_i32(&dump_status, 0) == 1); // return true if we completed the dump +} diff --git a/src/mono/mono/utils/mono-threads-posix.c b/src/mono/mono/utils/mono-threads-posix.c index 61d31fdeaae2b..c3ddb64d56523 100644 --- a/src/mono/mono/utils/mono-threads-posix.c +++ b/src/mono/mono/utils/mono-threads-posix.c @@ -308,6 +308,15 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) pthread_setname_np (tid, "%s", (void*)n); } #elif defined (HAVE_PTHREAD_SETNAME_NP) +#if defined (__linux__) + /* Ignore requests to set the main thread name because it causes the + * value returned by Process.ProcessName to change. + */ + MonoNativeThreadId main_thread_tid; + if (mono_native_thread_id_main_thread_known (&main_thread_tid) && + mono_native_thread_id_equals (tid, main_thread_tid)) + return; +#endif if (!name) { pthread_setname_np (tid, ""); } else { diff --git a/src/mono/mono/utils/mono-threads.c b/src/mono/mono/utils/mono-threads.c index a4cec2c3be1a0..8fb5deefd8608 100644 --- a/src/mono/mono/utils/mono-threads.c +++ b/src/mono/mono/utils/mono-threads.c @@ -442,6 +442,53 @@ thread_handle_destroy (gpointer data) g_free (thread_handle); } +static gboolean native_thread_id_main_thread_known; +static MonoNativeThreadId native_thread_id_main_thread; + +/** + * mono_native_thread_id_main_thread_known: + * + * If the main thread of the process has interacted with Mono (in the sense + * that it has a MonoThreadInfo associated with it), return \c TRUE and write + * its MonoNativeThreadId to \c main_thread_tid. + * + * Otherwise return \c FALSE. + */ +gboolean +mono_native_thread_id_main_thread_known (MonoNativeThreadId *main_thread_tid) +{ + if (!native_thread_id_main_thread_known) + return FALSE; + g_assert (main_thread_tid); + *main_thread_tid = native_thread_id_main_thread; + return TRUE; +} + +/* + * Saves the MonoNativeThreadId (on Linux pthread_t) of the current thread if + * it is the main thread. + * + * The main thread is (on Linux) the one whose OS thread id (on Linux pid_t) is + * equal to the process id. + * + * We have to do this at thread registration time because in embedding + * scenarios we can't count on the main thread to be the one that calls + * mono_jit_init, or other runtime initialization functions. + */ +static void +native_thread_set_main_thread (void) +{ + if (native_thread_id_main_thread_known) + return; +#if defined(__linux__) + if (mono_native_thread_os_id_get () == (guint64)getpid ()) { + native_thread_id_main_thread = mono_native_thread_id_get (); + mono_memory_barrier (); + native_thread_id_main_thread_known = TRUE; + } +#endif +} + static gboolean register_thread (MonoThreadInfo *info) { @@ -451,6 +498,7 @@ register_thread (MonoThreadInfo *info) info->small_id = mono_thread_info_register_small_id (); mono_thread_info_set_tid (info, mono_native_thread_id_get ()); + native_thread_set_main_thread (); info->handle = g_new0 (MonoThreadHandle, 1); mono_refcount_init (info->handle, thread_handle_destroy); diff --git a/src/mono/mono/utils/mono-threads.h b/src/mono/mono/utils/mono-threads.h index a949b42f659a8..c47a33d977446 100644 --- a/src/mono/mono/utils/mono-threads.h +++ b/src/mono/mono/utils/mono-threads.h @@ -643,6 +643,9 @@ void mono_threads_coop_end_global_suspend (void); MONO_API MonoNativeThreadId mono_native_thread_id_get (void); +gboolean +mono_native_thread_id_main_thread_known (MonoNativeThreadId *main_thread_tid); + /* * This does _not_ return the same value as mono_native_thread_id_get, except on Windows. * On POSIX, mono_native_thread_id_get returns the value from pthread_self, which is then diff --git a/src/mono/msbuild/AndroidAppBuilder/Templates/CMakeLists-android.txt b/src/mono/msbuild/AndroidAppBuilder/Templates/CMakeLists-android.txt deleted file mode 100644 index 619d576de7e19..0000000000000 --- a/src/mono/msbuild/AndroidAppBuilder/Templates/CMakeLists-android.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(runtime-android) - -add_library( - runtime-android - SHARED - runtime-android.c) - -include_directories("%MonoInclude%") - -target_link_libraries( - runtime-android - %NativeLibrariesToLink% - libz.so - log) diff --git a/src/mono/msbuild/AndroidAppBuilder/Templates/MonoRunner.java b/src/mono/msbuild/AndroidAppBuilder/Templates/MonoRunner.java deleted file mode 100644 index 2323f83d46914..0000000000000 --- a/src/mono/msbuild/AndroidAppBuilder/Templates/MonoRunner.java +++ /dev/null @@ -1,96 +0,0 @@ -// 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. - -package net.dot; - -import android.app.Instrumentation; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.app.Activity; -import android.os.Bundle; -import android.os.Environment; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class MonoRunner extends Instrumentation -{ - static MonoRunner inst; - - static { - System.loadLibrary("runtime-android"); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - start(); - } - - @Override - public void onStart() { - super.onStart(); - - MonoRunner.inst = this; - Context context = getContext(); - AssetManager am = context.getAssets(); - String filesDir = context.getFilesDir().getAbsolutePath(); - String cacheDir = context.getCacheDir().getAbsolutePath(); - String docsDir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(); - - copyAssetDir(am, "", filesDir); - - int retcode = initRuntime(filesDir, cacheDir, docsDir); - runOnMainSync(new Runnable() { - public void run() { - Bundle result = new Bundle(); - result.putInt("return-code", retcode); - // Xharness cli expects "test-results-path" with test results - result.putString("test-results-path", docsDir + "/testResults.xml"); - finish(retcode, result); - } - }); - } - - static void copyAssetDir(AssetManager am, String path, String outpath) { - try { - String[] res = am.list(path); - for (int i = 0; i < res.length; ++i) { - String fromFile = res[i]; - String toFile = outpath + "/" + res[i]; - try { - InputStream fromStream = am.open(fromFile); - Log.w("DOTNET", "\tCOPYING " + fromFile + " to " + toFile); - copy(fromStream, new FileOutputStream(toFile)); - } catch (FileNotFoundException e) { - new File(toFile).mkdirs(); - copyAssetDir(am, fromFile, toFile); - continue; - } - } - } - catch (Exception e) { - Log.w("DOTNET", "EXCEPTION", e); - } - } - - static void copy(InputStream in, OutputStream out) throws IOException { - byte[] buff = new byte [1024]; - for (int len = in.read(buff); len != -1; len = in.read(buff)) - out.write(buff, 0, len); - in.close(); - out.close(); - } - - native int initRuntime(String libsDir, String cacheDir, String docsDir); -} diff --git a/src/mono/msbuild/AppleAppBuilder/AotCompiler.cs b/src/mono/msbuild/AppleAppBuilder/AotCompiler.cs deleted file mode 100644 index 5a5b8f9ae8b55..0000000000000 --- a/src/mono/msbuild/AppleAppBuilder/AotCompiler.cs +++ /dev/null @@ -1,152 +0,0 @@ -// 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.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading.Tasks; - -internal class AotCompiler -{ - /// - /// Precompile all assemblies in parallel - /// - public static void PrecompileLibraries( - string crossCompiler, - string arch, - bool parallel, - string binDir, - string[] libsToPrecompile, - IDictionary envVariables, - bool optimize, - bool useLlvm, - string? llvmPath) - { - Parallel.ForEach(libsToPrecompile, - new ParallelOptions { MaxDegreeOfParallelism = parallel ? Environment.ProcessorCount : 1 }, - lib => PrecompileLibrary(crossCompiler, arch, binDir, lib, envVariables, optimize, useLlvm, llvmPath)); - } - - private static void PrecompileLibrary( - string crossCompiler, - string arch, - string binDir, - string libToPrecompile, - IDictionary envVariables, - bool optimize, - bool useLlvm, - string? llvmPath) - { - Utils.LogInfo($"[AOT] {libToPrecompile}"); - - var crossArgs = new StringBuilder(); - crossArgs - .Append(" -O=gsharedvt") - .Append(" -O=-float32") - .Append(useLlvm ? " --llvm" : " --nollvm") - .Append(" --debug"); - - string libName = Path.GetFileNameWithoutExtension(libToPrecompile); - var aotArgs = new StringBuilder(); - aotArgs - .Append("mtriple=").Append(arch).Append("-ios,") - .Append("static,") - .Append("asmonly,") - .Append("direct-icalls,") - .Append("nodebug,") - .Append("dwarfdebug,") - .Append("outfile=").Append(Path.Combine(binDir, libName + ".dll.s,")) - .Append("msym-dir=").Append(Path.Combine(binDir, "Msym,")) - .Append("data-outfile=").Append(Path.Combine(binDir, libName + ".aotdata,")) - // TODO: enable direct-pinvokes (to get rid of -force_loads) - //.Append("direct-pinvoke,") - .Append("full,") - .Append("mattr=+crc,"); // enable System.Runtime.Intrinsics.Arm (Crc32 and ArmBase for now) - - if (useLlvm) - { - aotArgs - .Append("llvm-path=").Append(llvmPath).Append(',') - .Append("llvm-outfile=").Append(Path.Combine(binDir, libName + ".dll-llvm.o,")); - // it has -llvm.o suffix because we need both LLVM and non-LLVM bits for every assembly - // most of the stuff from non-llvm .o will be linked out. - } - - // TODO: enable Interpreter - - crossArgs - .Append(" --aot=").Append(aotArgs).Append(" ") - .Append(libToPrecompile); - - Utils.RunProcess(crossCompiler, crossArgs.ToString(), envVariables, binDir); - - var clangArgs = new StringBuilder(); - if (optimize) - { - clangArgs.Append(" -Os"); - } - clangArgs - .Append(" -isysroot ").Append(Xcode.Sysroot) - .Append(" -miphoneos-version-min=10.1") - .Append(" -arch ").Append(arch) - .Append(" -c ").Append(Path.Combine(binDir, libName)).Append(".dll.s") - .Append(" -o ").Append(Path.Combine(binDir, libName)).Append(".dll.o"); - - Utils.RunProcess("clang", clangArgs.ToString(), workingDir: binDir); - } - - public static void GenerateLinkAllFile(string[] objFiles, string outputFile) - { - // Generates 'modules.m' in order to register all managed libraries - // - // - // extern void *mono_aot_module_Lib1_info; - // extern void *mono_aot_module_Lib2_info; - // ... - // - // void mono_ios_register_modules (void) - // { - // mono_aot_register_module (mono_aot_module_Lib1_info); - // mono_aot_register_module (mono_aot_module_Lib2_info); - // ... - // } - - Utils.LogInfo("Generating 'modules.m'..."); - - var lsDecl = new StringBuilder(); - lsDecl - .AppendLine("#include ") - .AppendLine("#include ") - .AppendLine() - .AppendLine("#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR") - .AppendLine(); - - var lsUsage = new StringBuilder(); - lsUsage - .AppendLine("void mono_ios_register_modules (void)") - .AppendLine("{"); - foreach (string objFile in objFiles) - { - string symbol = "mono_aot_module_" + - Path.GetFileName(objFile) - .Replace(".dll.o", "") - .Replace(".", "_") - .Replace("-", "_") + "_info"; - - lsDecl.Append("extern void *").Append(symbol).Append(';').AppendLine(); - lsUsage.Append("\tmono_aot_register_module (").Append(symbol).Append(");").AppendLine(); - } - lsDecl - .AppendLine() - .Append(lsUsage) - .AppendLine("}") - .AppendLine() - .AppendLine("#endif") - .AppendLine(); - - File.WriteAllText(outputFile, lsDecl.ToString()); - Utils.LogInfo($"Saved to {outputFile}."); - } -} diff --git a/src/mono/msbuild/Directory.Build.props b/src/mono/msbuild/Directory.Build.props new file mode 100644 index 0000000000000..c3f2519a25b0c --- /dev/null +++ b/src/mono/msbuild/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + $(NetCoreAppCurrent) + $([MSBuild]::NormalizeDirectory('$(BaseOutputPath)', '$(TargetFramework)-$(MonoConfiguration)')) + enable + + diff --git a/src/mono/msvc/build-init.vcxproj b/src/mono/msvc/build-init.vcxproj index 8d15e191ac40d..8b36028ea476c 100644 --- a/src/mono/msvc/build-init.vcxproj +++ b/src/mono/msvc/build-init.vcxproj @@ -142,6 +142,7 @@ <_EnableDefines Condition="'$(MONO_ENABLE_LLVM)' == 'true'">$(_EnableDefines);ENABLE_LLVM;ENABLE_LLVM_RUNTIME <_EnableDefines Condition="'$(MONO_ENABLE_NETCORE)' == 'true'">$(_EnableDefines);ENABLE_NETCORE + <_EnableDefines Condition="'$(MONO_ENABLE_PERFTRACING)' == 'true'">$(_EnableDefines);ENABLE_PERFTRACING <_HaveDefines Condition="'$(MONO_ENABLE_BTLS)' == 'true'">$(_HaveDefines);HAVE_BTLS <_EnableDefines>$(_EnableDefines.Trim(';')) <_HaveDefines>$(_HaveDefines.Trim(';')) diff --git a/src/mono/msvc/libeventpipe.targets b/src/mono/msvc/libeventpipe.targets new file mode 100644 index 0000000000000..9758f292b376c --- /dev/null +++ b/src/mono/msvc/libeventpipe.targets @@ -0,0 +1,149 @@ + + + + false + true + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + $(ExcludeEventPipeFromBuild) + CompileAsC + + + + diff --git a/src/mono/msvc/libeventpipe.targets.filters b/src/mono/msvc/libeventpipe.targets.filters new file mode 100644 index 0000000000000..1bb9dcffc7bc3 --- /dev/null +++ b/src/mono/msvc/libeventpipe.targets.filters @@ -0,0 +1,172 @@ + + + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Source Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + Header Files$(MonoRuntimeFilterSubFolder)\eventpipe + + + + + {D6D64FF2-7951-44D8-B965-4593893CEF35} + + + {B372B1CF-F13A-43B8-97E0-DF7A9563D4AE} + + + diff --git a/src/mono/msvc/libmono-dynamic.vcxproj b/src/mono/msvc/libmono-dynamic.vcxproj index 3b1fab1c678a2..cd120b7cfb16f 100644 --- a/src/mono/msvc/libmono-dynamic.vcxproj +++ b/src/mono/msvc/libmono-dynamic.vcxproj @@ -94,10 +94,9 @@ - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) Disabled - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);%(AdditionalIncludeDirectories) - WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);_DEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);$(SHIM_GLOBALIZATION_DEFINES);_DEBUG;%(PreprocessorDefinitions) 4996;4018;4244;%(DisableSpecificWarnings) Level3 @@ -121,10 +120,9 @@ X64 - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) Disabled - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);%(AdditionalIncludeDirectories) - WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);WIN64;_DEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);$(SHIM_GLOBALIZATION_DEFINES);WIN64;_DEBUG;%(PreprocessorDefinitions) 4996;4018;4244;%(DisableSpecificWarnings) Level3 @@ -145,10 +143,9 @@ - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) true - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);%(AdditionalIncludeDirectories) - WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);NDEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);$(SHIM_GLOBALIZATION_DEFINES);NDEBUG;%(PreprocessorDefinitions) true Level3 true @@ -174,10 +171,9 @@ X64 - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) true - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);%(AdditionalIncludeDirectories) - WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);WIN64;NDEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(MONO_LLVM_DEFAULT_INCLUDE_DIR);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);MONO_DLL_EXPORT;LLVM_API_VERSION=$(MONO_LLVM_DEFAULT_API_VERSION);$(SHIM_GLOBALIZATION_DEFINES);WIN64;NDEBUG;%(PreprocessorDefinitions) true Level3 true diff --git a/src/mono/msvc/libmonoruntime-common.targets b/src/mono/msvc/libmonoruntime-common.targets index 3e6f62e64d155..316efc8a4fc23 100644 --- a/src/mono/msvc/libmonoruntime-common.targets +++ b/src/mono/msvc/libmonoruntime-common.targets @@ -36,6 +36,7 @@ + diff --git a/src/mono/msvc/libmonoruntime-common.targets.filters b/src/mono/msvc/libmonoruntime-common.targets.filters index d614b6bcc49f7..fb4a4e3c84060 100644 --- a/src/mono/msvc/libmonoruntime-common.targets.filters +++ b/src/mono/msvc/libmonoruntime-common.targets.filters @@ -97,6 +97,9 @@ Source Files$(MonoRuntimeFilterSubFolder)\common + + Source Files$(MonoRuntimeFilterSubFolder)\common + Source Files$(MonoRuntimeFilterSubFolder)\common diff --git a/src/mono/msvc/libmonoruntime.targets b/src/mono/msvc/libmonoruntime.targets index ba371e200fef9..ef506c56f4555 100644 --- a/src/mono/msvc/libmonoruntime.targets +++ b/src/mono/msvc/libmonoruntime.targets @@ -1,6 +1,8 @@ + + diff --git a/src/mono/msvc/libmonoruntime.targets.filters b/src/mono/msvc/libmonoruntime.targets.filters index 870a2b19f6e21..6add73fc2df6d 100644 --- a/src/mono/msvc/libmonoruntime.targets.filters +++ b/src/mono/msvc/libmonoruntime.targets.filters @@ -1,6 +1,8 @@  + + diff --git a/src/mono/msvc/libmonoruntime.vcxproj b/src/mono/msvc/libmonoruntime.vcxproj index 4c009edd82391..2541712d4817e 100644 --- a/src/mono/msvc/libmonoruntime.vcxproj +++ b/src/mono/msvc/libmonoruntime.vcxproj @@ -97,8 +97,8 @@ Level3 Disabled - WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);_DEBUG;%(PreprocessorDefinitions) - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);$(SHIM_GLOBALIZATION_DEFINES);_DEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) $(IntDir)$(TargetName).pdb ProgramDatabase @@ -111,8 +111,8 @@ Level3 Disabled - WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);WIN64;_DEBUG;%(PreprocessorDefinitions) - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);$(SHIM_GLOBALIZATION_DEFINES);WIN64;_DEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) $(IntDir)$(TargetName).pdb ProgramDatabase @@ -125,8 +125,8 @@ Level3 true - WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);NDEBUG;%(PreprocessorDefinitions) - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);$(SHIM_GLOBALIZATION_DEFINES);NDEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) $(IntDir)$(TargetName).pdb true @@ -141,8 +141,8 @@ Level3 true - WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);WIN64;NDEBUG;%(PreprocessorDefinitions) - $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;WIN32_LEAN_AND_MEAN;_LIB;$(GC_DEFINES);$(SHIM_GLOBALIZATION_DEFINES);WIN64;NDEBUG;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(SHIM_GLOBALIZATION_INCLUDE_DIR);%(AdditionalIncludeDirectories) $(IntDir)$(TargetName).pdb true diff --git a/src/mono/msvc/mono.props b/src/mono/msvc/mono.props index e71f2cc330d6d..dbfed0b19f4a2 100644 --- a/src/mono/msvc/mono.props +++ b/src/mono/msvc/mono.props @@ -28,8 +28,11 @@ false + false true - false + + false + true .. @@ -45,6 +48,9 @@ $(MONO_LIBGC_INCLUDE_DIR) $(MONO_EGLIB_SOURCE_DIR) 610 + $(top_srcdir)/../libraries/Native/Unix/System.Globalization.Native + $(top_srcdir)/../libraries/Native/Unix/Common + $(SHIM_GLOBALIZATION_COMMON);$(SHIM_GLOBALIZATION) $(MONO_DIR)/external/llvm-project/llvm/include @@ -58,6 +64,7 @@ HAVE_SGEN_GC;HAVE_MOVING_COLLECTOR;HAVE_WRITE_BARRIERS;HAVE_CONC_GC_AS_DEFAULT $(SGEN_DEFINES) + TARGET_WINDOWS;PALEXPORT=extern "C" __declspec(dllexport) libgcmonosgen.lib -sgen $(MONO_BUILD_DIR_PREFIX)sgen/ @@ -120,6 +127,9 @@ $(MONO_ENABLE_NETCORE) + + $(MONO_ENABLE_PERFTRACING) + HAVE_CONFIG_H diff --git a/src/mono/msvc/mono.winconfig.targets b/src/mono/msvc/mono.winconfig.targets index d8e39ca7ad2dc..62e92339ee266 100644 --- a/src/mono/msvc/mono.winconfig.targets +++ b/src/mono/msvc/mono.winconfig.targets @@ -124,7 +124,8 @@ "ENABLE_LLVM_RUNTIME", "ENABLE_HYBRID_SUSPEND", "ENABLE_COOP_SUSPEND", - "ENABLE_NETCORE" }; + "ENABLE_NETCORE", + "ENABLE_PERFTRACING" }; var enableFeatures = GetConfigFeatures(path, ".*#define.*ENABLE_.*1"); if (enableDefines != null) diff --git a/src/mono/msvc/shimglobalization.targets b/src/mono/msvc/shimglobalization.targets new file mode 100644 index 0000000000000..19bc337ba6c28 --- /dev/null +++ b/src/mono/msvc/shimglobalization.targets @@ -0,0 +1,51 @@ + + + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + CompileAsCpp + + + + + + + + + + + + + + + + + + + diff --git a/src/mono/msvc/shimglobalization.targets.filters b/src/mono/msvc/shimglobalization.targets.filters new file mode 100644 index 0000000000000..106d7b8717996 --- /dev/null +++ b/src/mono/msvc/shimglobalization.targets.filters @@ -0,0 +1,87 @@ + + + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Source Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + Header Files$(MonoRuntimeFilterSubFolder)\shimglobalization + + + + + + + diff --git a/src/mono/netcore/System.Private.CoreLib/src/LinkerDescriptor/System.Private.CoreLib.xml b/src/mono/netcore/System.Private.CoreLib/src/LinkerDescriptor/System.Private.CoreLib.xml index 57d8454b006e4..3489337befd19 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/LinkerDescriptor/System.Private.CoreLib.xml +++ b/src/mono/netcore/System.Private.CoreLib/src/LinkerDescriptor/System.Private.CoreLib.xml @@ -386,6 +386,9 @@ + + + diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Array.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Array.Mono.cs index 908a3baa8e761..e04efea520a93 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Array.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Array.Mono.cs @@ -9,13 +9,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { public partial class Array @@ -61,7 +54,7 @@ public static unsafe void Clear(Array array, int index, int length) int lowerBound = array.GetLowerBound(0); int elementSize = array.GetElementSize(); - nuint numComponents = (nuint)Unsafe.As(array).Count; + nuint numComponents = (nuint)(nint)Unsafe.As(array).Count; int offset = index - lowerBound; diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Attribute.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Attribute.Mono.cs index fc6c82a6dcc5f..c362e7792c1f6 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Attribute.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Attribute.Mono.cs @@ -12,7 +12,8 @@ public partial class Attribute { if (attributeType == null) throw new ArgumentNullException(nameof(attributeType)); - if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute) && attributeType != typeof(CustomAttribute)) + if (!attributeType.IsSubclassOf(typeof(Attribute)) && !attributeType.IsInterface + && attributeType != typeof(Attribute) && attributeType != typeof(CustomAttribute)) throw new ArgumentException(SR.Argument_MustHaveAttributeBaseClass + " " + attributeType.FullName); object[] attrs = CustomAttribute.GetCustomAttributes(element, attributeType, inherit); diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Buffer.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Buffer.Mono.cs index b4772965b6ad3..6f04b9742a55a 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Buffer.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Buffer.Mono.cs @@ -4,13 +4,6 @@ using System.Runtime.CompilerServices; -#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types -#if TARGET_64BIT -using nuint = System.UInt64; -#else -using nuint = System.UInt32; -#endif - namespace System { public partial class Buffer diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/GC.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/GC.Mono.cs index 945356c17dec5..b7ac9cfaf4cdf 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/GC.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/GC.Mono.cs @@ -113,7 +113,7 @@ public static int GetGeneration(WeakReference wo) { object? obj = wo.Target; if (obj == null) - throw new ArgumentException(); + throw new ArgumentException(null, nameof(wo)); return GetGeneration(obj); } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Mono.cs index 911499ea842e3..3d7b5ca4866f2 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Mono.cs @@ -6,14 +6,18 @@ namespace System.Globalization { internal static partial class GlobalizationMode { - internal static bool Invariant { get; } = GetGlobalizationInvariantMode(); + private static bool GetInvariantSwitchValue() => + GetSwitchValue("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); - private static bool GetInvariantSwitchValue() + private static bool GetSwitchValue(string envVariable) { - string? val = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); - if (val != null) - return bool.IsTrueStringIgnoreCase(val) || val.Equals("1"); - return false; + bool ret = false; + string? switchValue = Environment.GetEnvironmentVariable(envVariable); + if (switchValue != null) + { + ret = bool.IsTrueStringIgnoreCase(switchValue) || switchValue.Equals("1"); + } + return ret; } } } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.Mono.cs index e3ca7ce617366..70d7e7e3dc41f 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.Mono.cs @@ -8,6 +8,7 @@ namespace System.Globalization { internal partial class GlobalizationMode { + internal static bool Invariant { get; } = GetGlobalizationInvariantMode(); internal static bool UseNls => false; private static bool GetGlobalizationInvariantMode() diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.Mono.cs index 5aaa143170376..abf2a603c2126 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.Mono.cs @@ -6,11 +6,9 @@ namespace System.Globalization { internal partial class GlobalizationMode { - internal static bool UseNls => true; - - private static bool GetGlobalizationInvariantMode() - { - return GetInvariantSwitchValue(); - } + internal static bool Invariant { get; } = GetInvariantSwitchValue(); + internal static bool UseNls { get; } = !Invariant && + (GetSwitchValue("DOTNET_SYSTEM_GLOBALIZATION_USENLS") || + Interop.Globalization.LoadICU() == 0); } } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs index e21888056a3fa..76c1e4e8b529c 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs @@ -551,7 +551,7 @@ internal static bool IsDefined(ICustomAttributeProvider obj, Type attributeType, { if (attributeType == null) throw new ArgumentNullException(nameof(attributeType)); - if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) + if (!attributeType.IsSubclassOf(typeof(Attribute)) && !attributeType.IsInterface && attributeType != typeof(Attribute)) throw new ArgumentException(SR.Argument_MustHaveAttributeBaseClass + " " + attributeType.FullName); AttributeUsageAttribute? usage = null; diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.Mono.cs index 8f40153db0f3d..53faf4ad11b76 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.Mono.cs @@ -325,7 +325,7 @@ public override Module Module public override string ToString() { - return "ConstructorBuilder ['" + type.Name + "']"; + return "Name: " + Name; } internal void fixup() diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs index 0c9f12ad193aa..5f6e79e580c33 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs @@ -154,7 +154,7 @@ private FieldBuilder DefineDataImpl(string name, int size, FieldAttributes attri { if (name == null) throw new ArgumentNullException(nameof(name)); - if (name == string.Empty) + if (name.Length == 0) throw new ArgumentException("name cannot be empty", nameof(name)); if (global_type_created != null) throw new InvalidOperationException("global fields already created"); diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs index 00bcc90d59bf8..4ee8768fcb03a 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.Mono.cs @@ -261,7 +261,7 @@ public void AddInterfaceImplementation(Type interfaceType) if (interfaceType == null) throw new ArgumentNullException(nameof(interfaceType)); if (interfaceType.IsByRef) - throw new ArgumentException(nameof(interfaceType)); + throw new ArgumentException(SR.Argument_CannotGetTypeTokenForByRef); check_not_created(); if (interfaces != null) @@ -479,7 +479,7 @@ public ConstructorBuilder DefineDefaultConstructor(MethodAttributes attributes) if (IsInterface) throw new InvalidOperationException(); if ((attributes & (MethodAttributes.Static | MethodAttributes.Virtual)) > 0) - throw new ArgumentException(nameof(attributes)); + throw new ArgumentException(SR.Arg_NoStaticVirtual); if (parent != null) parent_type = parent; @@ -1515,7 +1515,7 @@ public EventBuilder DefineEvent(string name, EventAttributes attributes, Type ev { check_name(nameof(name), name); if (eventtype == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(eventtype)); check_not_created(); if (eventtype.IsByRef) throw new ArgumentException(SR.Argument_CannotGetTypeTokenForByRef); @@ -1597,7 +1597,7 @@ public void SetParent(Type? parent) else { if (parent.IsInterface) - throw new ArgumentException(nameof(parent)); + throw new ArgumentException(SR.Argument_CannotSetParentToInterface); this.parent = parent; } this.parent = ResolveUserType(this.parent); @@ -1878,7 +1878,7 @@ public static FieldInfo GetField(Type type, FieldInfo field) throw new ArgumentException("The specified field must be declared on a generic type definition.", nameof(field)); if (field.DeclaringType != type.GetGenericTypeDefinition()) - throw new ArgumentException("field declaring type is not the generic type definition of type", "method"); + throw new ArgumentException("field declaring type is not the generic type definition of type", nameof(field)); FieldInfo res = type.GetField(field); if (res == null) diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 5d110fefdaebb..d4efac98e0a4e 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -197,7 +197,7 @@ Type GetType(string className, bool throwOnError, bool ignoreCase) { if (className == null) throw new ArgumentNullException(nameof(className)); - if (className == string.Empty) + if (className.Length == 0) throw new ArgumentException("Type name can't be empty"); return assembly.InternalGetType(this, className, throwOnError, ignoreCase); } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs index 5dcda6d90fed6..7c80ba8fb5c6b 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs @@ -8,8 +8,10 @@ public partial class RuntimeHelpers { public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle) { - if (array == null || fldHandle.Value == IntPtr.Zero) - throw new ArgumentNullException(); + if (array == null) + throw new ArgumentNullException(nameof(array)); + if (fldHandle.Value == IntPtr.Zero) + throw new ArgumentNullException(nameof(fldHandle)); InitializeArray(array, fldHandle.Value); } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs index 0fea7764808c2..4a35247b1c137 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs @@ -7,6 +7,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using Internal.Runtime.CompilerServices; namespace System.Runtime.Loader { @@ -129,7 +130,13 @@ public void StartProfileOptimization(string? profile) // Invoked by Mono to resolve requests to load satellite assemblies. private static Assembly? MonoResolveUsingResolveSatelliteAssembly(IntPtr gchALC, string assemblyName) { - return ResolveSatelliteAssembly(gchALC, new AssemblyName(assemblyName)); + AssemblyLoadContext context; + // This check exists because the function can be called early in startup, before the default ALC is initialized + if (gchALC == IntPtr.Zero) + context = Default; + else + context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchALC).Target)!; + return context.ResolveSatelliteAssembly(new AssemblyName(assemblyName)); } private static AssemblyLoadContext GetAssemblyLoadContext(IntPtr gchManagedAssemblyLoadContext) @@ -155,15 +162,13 @@ private static void MonoResolveUnmanagedDllUsingEvent(string unmanagedDllName, A dll = context.GetResolvedUnmanagedDll(assembly, unmanagedDllName); } - #region Copied from AssemblyLoadContext.CoreCLR.cs, modified until our AssemblyBuilder implementation is functional private static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) { return asm == null ? null : asm is RuntimeAssembly rtAssembly ? rtAssembly : - //asm is System.Reflection.Emit.AssemblyBuilder ab ? ab.InternalAssembly : + asm is System.Reflection.Emit.AssemblyBuilder ab ? Unsafe.As(ab) : // Mono AssemblyBuilder is also a RuntimeAssembly, see AssemblyBuilder.Mono.cs null; } - #endregion } } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 9628d4956bcf0..71ff174e23d24 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -873,7 +873,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) protected override PropertyInfo? GetPropertyImpl( string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers) { - if (name == null) throw new ArgumentNullException(); + if (name == null) throw new ArgumentNullException(nameof(name)); ListBuilder candidates = GetPropertyCandidates(name, bindingAttr, types, false); @@ -911,7 +911,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) { - if (name == null) throw new ArgumentNullException(); + if (name == null) throw new ArgumentNullException(nameof(name)); bool ignoreCase; MemberListType listType; @@ -978,7 +978,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) public override Type? GetInterface(string fullname, bool ignoreCase) { - if (fullname == null) throw new ArgumentNullException(); + if (fullname == null) throw new ArgumentNullException(nameof(fullname)); BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic; @@ -1031,7 +1031,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) public override Type? GetNestedType(string fullname, BindingFlags bindingAttr) { - if (fullname == null) throw new ArgumentNullException(); + if (fullname == null) throw new ArgumentNullException(nameof(fullname)); bool ignoreCase; bindingAttr &= ~BindingFlags.Static; @@ -1059,7 +1059,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) { - if (name == null) throw new ArgumentNullException(); + if (name == null) throw new ArgumentNullException(nameof(name)); ListBuilder methods = default; ListBuilder constructors = default; diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index 7df75e09b9178..90a36a0230f5c 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -289,7 +289,7 @@ internal static bool IsTypeDefinition(RuntimeType type) if (typeName == null) throw new ArgumentNullException(nameof(typeName)); - if (typeName == string.Empty) + if (typeName.Length == 0) if (throwOnError) throw new TypeLoadException("A null or zero length string does not represent a valid Type."); else diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Threading/ThreadPool.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Threading/ThreadPool.Mono.cs index 023574d218002..ae757df4df433 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Threading/ThreadPool.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Threading/ThreadPool.Mono.cs @@ -8,11 +8,7 @@ namespace System.Threading { public static partial class ThreadPool { - private static void EnsureInitialized() - { - ThreadPoolGlobals.threadPoolInitialized = true; - ThreadPoolGlobals.enableWorkerTracking = false; - } + private static bool GetEnableWorkerTracking() => false; internal static void ReportThreadStatus(bool isWorking) { @@ -46,4 +42,4 @@ public static bool BindHandle(SafeHandle osHandle) private static long PendingUnmanagedWorkItemCount => 0; } -} \ No newline at end of file +} diff --git a/src/mono/netcore/gen-xunit-runner/Program.cs b/src/mono/netcore/gen-xunit-runner/Program.cs index a73bbecdfd528..1bd127cef1f11 100644 --- a/src/mono/netcore/gen-xunit-runner/Program.cs +++ b/src/mono/netcore/gen-xunit-runner/Program.cs @@ -283,7 +283,6 @@ static int Main (string[] args) args = args.Where (s => s != String.Empty).Concat (extra_args).ToArray (); // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir -// File.Copy ($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true); File.Copy ($"{sdkdir}/TestUtilities.dll", AppContext.BaseDirectory, true); File.Copy ($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true); diff --git a/src/mono/netcore/sample/Android/Makefile b/src/mono/netcore/sample/Android/Makefile index b069bb1fb27e9..5ce28d98d9486 100644 --- a/src/mono/netcore/sample/Android/Makefile +++ b/src/mono/netcore/sample/Android/Makefile @@ -1,21 +1,18 @@ -MONO_CONFIG=Debug +MONO_CONFIG=Release MONO_ARCH=arm64 DOTNET := ../../../../.././dotnet.sh -#export ANDROID_NDK_ROOT=/path/to/android/ndk -#export ANDROID_SDK_ROOT=/path/to/android/sdk +all: runtimepack run -all: runtimepack bundle - -bundle: clean - $(DOTNET) build -c $(MONO_CONFIG) Program.csproj - $(DOTNET) msbuild /t:BuildAppBundle /p:Configuration=$(MONO_CONFIG) /p:TargetArchitecture=$(MONO_ARCH) - -deploy-launch: bundle - $(DOTNET) msbuild /t:ReinstallAndLaunch +appbuilder: + $(DOTNET) build -c Release ../../../../../tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.csproj runtimepack: - ../../../../.././build.sh -c $(MONO_CONFIG) -os Android -arch $(MONO_ARCH) -subset Mono+Libs /p:DisableCrossgen=true + ../../../../.././build.sh Mono+Libs -os Android -arch $(MONO_ARCH) -c $(MONO_CONFIG) + +run: clean appbuilder + $(DOTNET) publish -c $(MONO_CONFIG) -r android-$(MONO_ARCH) \ + /p:Platform=$(MONO_ARCH) /p:DeployAndRun=true clean: rm -rf bin diff --git a/src/mono/netcore/sample/Android/Program.csproj b/src/mono/netcore/sample/Android/Program.csproj index 51a153db7cbe2..6f452e61dfede 100644 --- a/src/mono/netcore/sample/Android/Program.csproj +++ b/src/mono/netcore/sample/Android/Program.csproj @@ -2,70 +2,69 @@ Exe bin + Portable $(NetCoreAppCurrent) - x64 - $(ArtifactsDir)bin\lib-runtime-packs\runtimes\android-$(TargetArchitecture) - $(MSBuildThisFileDirectory)\bin\bundle + $(ArtifactsBinDir)lib-runtime-packs\$(NetCoreAppCurrent)-Android-$(Configuration)-$(TargetArchitecture)\runtimes\android-$(TargetArchitecture) + $(ArtifactsBinDir)AndroidAppBuilder\$(Configuration)\$(NetCoreAppCurrent) + false + true + <_TrimmerDefaultAction>link - - + + + + + $(ArtifactsDir)bin\lib-runtime-packs\$(NetCoreAppCurrent)-Android-$(Configuration)-$(Platform) + + + - + - + + - arm64-v8a - armeabi - x86_64 - $(TargetArchitecture) + arm64-v8a + armeabi-v7a + x86_64 + $(Platform) + $(MSBuildThisFileDirectory)$(PublishDir)\apk + False + True + $(ANDROID_SDK_ROOT)\platform-tools\adb - - - - - - - - - - - - - + - + + + + + StripDebugSymbols="$(StripDebugSymbols)" + SourceDir="$(MSBuildThisFileDirectory)$(PublishDir)" + OutputDir="$(ApkDir)"> - - - - - $(ANDROID_SDK_ROOT)\platform-tools\adb - - - - - - + + + + + + + + diff --git a/src/mono/netcore/sample/iOS/Makefile b/src/mono/netcore/sample/iOS/Makefile index 31a7e9340f5f6..36dec2bc18dab 100644 --- a/src/mono/netcore/sample/iOS/Makefile +++ b/src/mono/netcore/sample/iOS/Makefile @@ -1,24 +1,21 @@ MONO_CONFIG=Debug -MONO_ARCH=arm64 +MONO_ARCH=x64 DOTNET := ../../../../.././dotnet.sh USE_LLVM=True -# usage example: -# 'make all MONO_ARCH=x64 MONO_CONFIG=Release' to build the app for simulator -all: runtimepack bundle +all: runtimepack run -program: - $(DOTNET) build -c $(MONO_CONFIG) Program.csproj - -bundle: clean program - $(DOTNET) msbuild /t:BuildAppBundle /p:Configuration=$(MONO_CONFIG) /p:TargetArchitecture=$(MONO_ARCH) \ - /p:UseLlvm=$(USE_LLVM) - -deploy-sim: - $(DOTNET) msbuild /t:IosDeployToSimulator /p:Configuration=$(MONO_CONFIG) /p:TargetArchitecture=$(MONO_ARCH) +TOOLS_DIR=../../../../../tools-local/tasks/mobile.tasks +appbuilder: + $(DOTNET) build -c Release $(TOOLS_DIR)/AotCompilerTask/MonoAOTCompiler.csproj + $(DOTNET) build -c Release $(TOOLS_DIR)/AppleAppBuilder/AppleAppBuilder.csproj runtimepack: - ../../../../.././build.sh -c $(MONO_CONFIG) -os iOS -arch $(MONO_ARCH) -subset Mono+Libs /p:DisableCrossgen=true + ../../../../.././build.sh Mono+Libs -os iOS -arch $(MONO_ARCH) -c $(MONO_CONFIG) + +run: clean appbuilder + $(DOTNET) publish -c $(MONO_CONFIG) /p:TargetArchitecture=$(MONO_ARCH) \ + /p:UseLLVM=$(USE_LLVM) /p:UseAotForSimulator=true clean: rm -rf bin diff --git a/src/mono/netcore/sample/iOS/Program.cs b/src/mono/netcore/sample/iOS/Program.cs index 0de20347bd314..2b43cf7f52742 100644 --- a/src/mono/netcore/sample/iOS/Program.cs +++ b/src/mono/netcore/sample/iOS/Program.cs @@ -49,5 +49,6 @@ public static async Task Main(string[] args) } Console.WriteLine("Done!"); + await Task.Delay(-1); } } \ No newline at end of file diff --git a/src/mono/netcore/sample/iOS/Program.csproj b/src/mono/netcore/sample/iOS/Program.csproj index 908aad01ea612..f08d1806b4f4c 100644 --- a/src/mono/netcore/sample/iOS/Program.csproj +++ b/src/mono/netcore/sample/iOS/Program.csproj @@ -2,68 +2,85 @@ Exe bin + Portable $(NetCoreAppCurrent) - x64 - $(ArtifactsDir)bin\lib-runtime-packs\runtimes\ios-$(TargetArchitecture) - $(ArtifactsDir)bin\mono\iOS.$(TargetArchitecture).$(Configuration) - $(MSBuildThisFileDirectory)\bin\bundle + iOS + $(ArtifactsBinDir)lib-runtime-packs\$(NetCoreAppCurrent)-iOS-$(Configuration)-$(TargetArchitecture)\runtimes\ios-$(TargetArchitecture) + false + ios-$(TargetArchitecture) + true + <_TrimmerDefaultAction>link + True - - + + + + + $(ArtifactsDir)bin\lib-runtime-packs\$(NetCoreAppCurrent)-iOS-$(Configuration)-$(TargetArchitecture) + + + - + + + + - + - arm64 - x64 + $(MSBuildThisFileDirectory)$(PublishDir)\app + iPhone 11 + + + - - - - + + + @(MonoAOTCompilerDefaultAotArguments, ';') + @(MonoAOTCompilerDefaultProcessArguments, ';') + - - - - - - - + + + + + OutputDirectory="$(AppDir)" + Optimized="$(Optimized)" + UseAotForSimulator="$(UseAotForSimulator)" + AppDir="$(MSBuildThisFileDirectory)$(PublishDir)"> + - - - - iPhone 11 - - - - - - - + + + + + diff --git a/src/mono/netcore/sample/wasm/Makefile b/src/mono/netcore/sample/wasm/Makefile new file mode 100644 index 0000000000000..aed078c63ebf1 --- /dev/null +++ b/src/mono/netcore/sample/wasm/Makefile @@ -0,0 +1,19 @@ +TOP=../../../../.. + +DOTNET_Q_ARGS=--nologo -v:q -consoleloggerparameters:NoSummary + +CONFIG?=Release + +all: build + +build: + $(TOP)/.dotnet/dotnet build $(DOTNET_Q_ARGS) /p:TargetArchitecture=wasm /p:TargetOS=Browser /p:Configuration=$(CONFIG) WasmSample.csproj + +clean: + rm -rf bin + +run: + cd bin/$(CONFIG)/publish && ~/.jsvu/v8 --expose_wasm runtime.js -- --enable-gc --run WasmSample.dll + +runtimepack: + EMSDK_PATH=$(abspath $(TOP)/src/mono/wasm/emsdk) $(TOP)/build.sh -c $(CONFIG) -os Browser -arch wasm -subset Mono+Libs diff --git a/src/mono/netcore/sample/wasm/Program.cs b/src/mono/netcore/sample/wasm/Program.cs new file mode 100644 index 0000000000000..58a6f578393e5 --- /dev/null +++ b/src/mono/netcore/sample/wasm/Program.cs @@ -0,0 +1,12 @@ +// -*- indent-tabs-mode: nil -*- +// 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; + +public class Test +{ + public static void Main (String[] args) { + Console.WriteLine ("Hello, World!"); + } +} diff --git a/src/mono/netcore/sample/wasm/WasmSample.csproj b/src/mono/netcore/sample/wasm/WasmSample.csproj new file mode 100644 index 0000000000000..1bf65d18fbea7 --- /dev/null +++ b/src/mono/netcore/sample/wasm/WasmSample.csproj @@ -0,0 +1,40 @@ + + + Exe + bin + false + $(NetCoreAppCurrent) + wasm + Browser + $(ArtifactsDir)bin\lib-runtime-packs\$(NetCoreAppCurrent)-$(TargetOS)-$(Configuration)-$(TargetArchitecture)\runtimes\browser-wasm + $(MSBuildThisFileDirectory)\obj\$(Configuration)\wasm + $(MSBuildThisFileDirectory)\bin\$(Configuration)\publish + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mono/wasm/.gitignore b/src/mono/wasm/.gitignore new file mode 100644 index 0000000000000..88ea00659140d --- /dev/null +++ b/src/mono/wasm/.gitignore @@ -0,0 +1 @@ +/emsdk_env.sh diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile new file mode 100644 index 0000000000000..412ec94a18578 --- /dev/null +++ b/src/mono/wasm/Makefile @@ -0,0 +1,102 @@ +TOP=$(realpath $(CURDIR)/../../..) +-include Make.config + +# +# These variables are set by wasm.targets +# +EMSDK_PATH?=emsdk +CONFIG?=Release +BINDIR?=$(TOP)/artifacts/bin +OBJDIR?=$(TOP)/artifacts/obj +PINVOKE_TABLE?=$(TOP)/artifacts/obj/mono/Browser.wasm.$(CONFIG)/wasm/pinvoke-table.h +MONO_BIN_DIR?=$(BINDIR)/mono/Browser.wasm.$(CONFIG) +SYS_NATIVE_DIR?=$(OBJDIR)/native/net5.0-Browser-$(CONFIG)-wasm/System.Native +BUILDS_BIN_DIR?=$(BINDIR)/native/net5.0-Browser-$(CONFIG)-wasm/wasm/runtimes + +all: build-native + +# +# EMSCRIPTEN SETUP +# +# If EMSDK_PATH is not set by the caller, download and setup a local emsdk install. +# + +EMSCRIPTEN_VERSION=1.39.11 +EMSDK_LOCAL_PATH=emsdk +EMCC=source $(CURDIR)/emsdk_env.sh && emcc + +.stamp-wasm-install-and-select-$(EMSCRIPTEN_VERSION): + rm -rf $(EMSDK_LOCAL_PATH) + git clone https://github.com/emscripten-core/emsdk.git $(EMSDK_LOCAL_PATH) + cd $(EMSDK_LOCAL_PATH) && git checkout $(EMSCRIPTEN_VERSION) + cd $(EMSDK_LOCAL_PATH) && ./emsdk install $(EMSCRIPTEN_VERSION) + cd $(EMSDK_LOCAL_PATH) && ./emsdk activate --embedded $(EMSCRIPTEN_VERSION) + touch $@ + +ifeq ($(EMSDK_PATH),emsdk) +provision-wasm: .stamp-wasm-install-and-select-$(EMSCRIPTEN_VERSION) +else +provision-wasm: +endif + +# emsdk_env.sh calls emsdk construct_env which is a bit slow so make a copy +emsdk_env.sh: | provision-wasm + cd $(EMSDK_PATH) && ./emsdk construct_env $(CURDIR)/emsdk_env.sh + +MONO_OBJ_DIR=$(OBJDIR)/mono/Browser.wasm.$(CONFIG) +MONO_INCLUDE_DIR=$(MONO_BIN_DIR)/include/mono-2.0 +BUILDS_OBJ_DIR=$(MONO_OBJ_DIR)/wasm/runtimes +MONO_LIBS = \ + $(MONO_BIN_DIR)/{libmono-ee-interp.a,libmonosgen-2.0.a,libmono-ilgen.a,libmono-icall-table.a} \ + ${SYS_NATIVE_DIR}/libSystem.Native.a + +EMCC_FLAGS=--profiling-funcs -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN=1 -s ALIASING_FUNCTION_POINTERS=0 -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'FS_createPath', 'FS_createDataFile', 'cwrap', 'setValue', 'getValue', 'UTF8ToString', 'addFunction']" -s "EXPORTED_FUNCTIONS=['_putchar']" --source-map-base http://example.com -s WASM_OBJECT_FILES=0 -s FORCE_FILESYSTEM=1 -s USE_ZLIB=1 +EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 +EMCC_RELEASE_FLAGS=-Oz --llvm-opts 2 --llvm-lto 1 -DENABLE_NETCORE=1 + +# +# Interpreter builds +# + +# $(1) - name +# $(2) - runtime dir +# $(3) - EMCC_FLAGS +# $(4) - libs +define InterpBuildTemplate + +$(BUILDS_BIN_DIR)/$(1)/: + mkdir -p $$@ + +$(BUILDS_OBJ_DIR)/$(1)/: + mkdir -p $$@ + +$(BUILDS_BIN_DIR)/$(1)/dotnet.js: $(BUILDS_OBJ_DIR)/$(1)/driver.o $(BUILDS_OBJ_DIR)/$(1)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js $(5) | $(BUILDS_BIN_DIR)/$(1)/ emsdk_env.sh + $(EMCC) $(EMCC_FLAGS) $(3) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js $(BUILDS_OBJ_DIR)/$(1)/driver.o $(BUILDS_OBJ_DIR)/$(1)/corebindings.o $(4) -o $(BUILDS_BIN_DIR)/$(1)/dotnet.js + +$(BUILDS_OBJ_DIR)/$(1)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR)/$(1)/ + if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi + +$(BUILDS_OBJ_DIR)/$(1)/driver.o: runtime/driver.c runtime/corebindings.c $(BUILDS_OBJ_DIR)/$(1)/pinvoke-table.h $(5) | $(BUILDS_OBJ_DIR)/$(1)/ emsdk_env.sh + $(EMCC) $(EMCC_FLAGS) $(3) -Oz -DCORE_BINDINGS -I$(BUILDS_OBJ_DIR)/$(1) -I$(MONO_INCLUDE_DIR) runtime/driver.c -c -o $$@ + +$(BUILDS_OBJ_DIR)/$(1)/corebindings.o: runtime/corebindings.c | $(BUILDS_OBJ_DIR)/$(1)/ emsdk_env.sh + $(EMCC) $(3) -Oz -I$(MONO_INCLUDE_DIR) runtime/corebindings.c -c -o $$@ + +build-native: $(BUILDS_BIN_DIR)/$(1)/dotnet.js + +build-interp-$(1): $(BUILDS_BIN_DIR)/$(1)/dotnet.js + +endef + +$(eval $(call InterpBuildTemplate,debug,,$(EMCC_DEBUG_FLAGS),$(MONO_LIBS))) +$(eval $(call InterpBuildTemplate,release,,$(EMCC_RELEASE_FLAGS),$(MONO_LIBS))) + +build: + EMSDK_PATH=$(PWD)/wasm/emsdk ../../../.dotnet/dotnet build /p:TargetArchitecture=wasm /p:TargetOS=Browser /p:Configuration=$(CONFIG) + +clean-emsdk: + $(RM) -rf $(EMSDK_LOCAL_PATH) + +clean: + $(RM) -rf $(BUILDS_BIN_DIR) $(BUILDS_OBJ_DIR) + $(RM) emsdk_env.sh diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js new file mode 100644 index 0000000000000..10e4fa6ff4816 --- /dev/null +++ b/src/mono/wasm/runtime-test.js @@ -0,0 +1,339 @@ +// -*- mode: js; js-indent-level: 4; -*- +// +// Run runtime tests under a JS shell or a browser +// + +//glue code to deal with the differences between chrome, ch, d8, jsc and sm. +var is_browser = typeof window != "undefined"; + +if (is_browser) { + // We expect to be run by tests/runtime/run.js which passes in the arguments using http parameters + var url = new URL (decodeURI (window.location)); + arguments = []; + for (var v of url.searchParams) { + if (v [0] == "arg") { + console.log ("URL ARG: " + v [0] + "=" + v [1]); + arguments.push (v [1]); + } + } +} + +if (is_browser || typeof print === "undefined") + print = console.log; + +// JavaScript core does not have a console defined +if (typeof console === "undefined") { + var Console = function () { + this.log = function(msg){ print(msg) }; + }; + console = new Console(); +} + +if (typeof console !== "undefined") { + if (!console.debug) + console.debug = console.log; + if (!console.trace) + console.trace = console.log; + if (!console.warn) + console.warn = console.log; +} + +if (typeof crypto == 'undefined') { + // /dev/random doesn't work on js shells, so define our own + // See library_fs.js:createDefaultDevices () + var crypto = { + getRandomValues: function (buffer) { + buffer[0] = (Math.random()*256)|0; + } + } +} + +try { + if (typeof arguments == "undefined") + arguments = WScript.Arguments; + load = WScript.LoadScriptFile; + read = WScript.LoadBinaryFile; +} catch (e) { +} + +try { + if (typeof arguments == "undefined") { + if (typeof scriptArgs !== "undefined") + arguments = scriptArgs; + } +} catch (e) { +} +//end of all the nice shell glue code. + +// set up a global variable to be accessed in App.init +var testArguments = arguments; + +function test_exit (exit_code) { + if (is_browser) { + // Notify the puppeteer script + Module.exit_code = exit_code; + print ("WASM EXIT " + exit_code); + } else { + Module.wasm_exit (exit_code); + } +} + +function fail_exec (reason) { + print (reason); + test_exit (1); +} + +function inspect_object (o) { + var r = ""; + for(var p in o) { + var t = typeof o[p]; + r += "'" + p + "' => '" + t + "', "; + } + return r; +} + +// Preprocess arguments +var args = testArguments; +print("Arguments: " + testArguments); +profilers = []; +setenv = {}; +runtime_args = []; +enable_gc = false; +enable_zoneinfo = false; +while (true) { + if (args [0].startsWith ("--profile=")) { + var arg = args [0].substring ("--profile=".length); + + profilers.push (arg); + + args = args.slice (1); + } else if (args [0].startsWith ("--setenv=")) { + var arg = args [0].substring ("--setenv=".length); + var parts = arg.split ('='); + if (parts.length != 2) + fail_exec ("Error: malformed argument: '" + args [0]); + setenv [parts [0]] = parts [1]; + args = args.slice (1); + } else if (args [0].startsWith ("--runtime-arg=")) { + var arg = args [0].substring ("--runtime-arg=".length); + runtime_args.push (arg); + args = args.slice (1); + } else if (args [0] == "--enable-gc") { + enable_gc = true; + args = args.slice (1); + } else if (args [0] == "--enable-zoneinfo") { + enable_zoneinfo = true; + args = args.slice (1); + } else { + break; + } +} +testArguments = args; + +if (typeof window == "undefined") + load ("mono-config.js"); + +var Module = { + mainScriptUrlOrBlob: "dotnet.js", + + print: function(x) { print ("WASM: " + x) }, + printErr: function(x) { print ("WASM-ERR: " + x) }, + + onAbort: function(x) { + print ("ABORT: " + x); + var err = new Error(); + print ("Stacktrace: \n"); + print (err.stack); + test_exit (1); + }, + + onRuntimeInitialized: function () { + // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. + var wasm_setenv = Module.cwrap ('mono_wasm_setenv', 'void', ['string', 'string']); + for (var variable in setenv) { + MONO.mono_wasm_setenv (variable, setenv [variable]); + } + + if (enable_gc) { + var f = Module.cwrap ('mono_wasm_enable_on_demand_gc', 'void', []); + f (); + } + if (enable_zoneinfo) { + // Load the zoneinfo data into the VFS rooted at /zoneinfo + FS.mkdir("zoneinfo"); + Module['FS_createPath']('/', 'zoneinfo', true, true); + Module['FS_createPath']('/zoneinfo', 'Indian', true, true); + Module['FS_createPath']('/zoneinfo', 'Atlantic', true, true); + Module['FS_createPath']('/zoneinfo', 'US', true, true); + Module['FS_createPath']('/zoneinfo', 'Brazil', true, true); + Module['FS_createPath']('/zoneinfo', 'Pacific', true, true); + Module['FS_createPath']('/zoneinfo', 'Arctic', true, true); + Module['FS_createPath']('/zoneinfo', 'America', true, true); + Module['FS_createPath']('/zoneinfo/America', 'Indiana', true, true); + Module['FS_createPath']('/zoneinfo/America', 'Argentina', true, true); + Module['FS_createPath']('/zoneinfo/America', 'Kentucky', true, true); + Module['FS_createPath']('/zoneinfo/America', 'North_Dakota', true, true); + Module['FS_createPath']('/zoneinfo', 'Australia', true, true); + Module['FS_createPath']('/zoneinfo', 'Etc', true, true); + Module['FS_createPath']('/zoneinfo', 'Asia', true, true); + Module['FS_createPath']('/zoneinfo', 'Antarctica', true, true); + Module['FS_createPath']('/zoneinfo', 'Europe', true, true); + Module['FS_createPath']('/zoneinfo', 'Mexico', true, true); + Module['FS_createPath']('/zoneinfo', 'Africa', true, true); + Module['FS_createPath']('/zoneinfo', 'Chile', true, true); + Module['FS_createPath']('/zoneinfo', 'Canada', true, true); + var zoneInfoData = read ('zoneinfo.data', 'binary'); + var metadata = JSON.parse(read ("mono-webassembly-zoneinfo-fs-smd.js.metadata", 'utf-8')); + var files = metadata.files; + for (var i = 0; i < files.length; ++i) { + var byteArray = zoneInfoData.subarray(files[i].start, files[i].end); + var stream = FS.open(files[i].filename, 'w+'); + FS.write(stream, byteArray, 0, byteArray.length, 0); + FS.close(stream); + } + } + MONO.mono_load_runtime_and_bcl ( + config.vfs_prefix, + config.deploy_prefix, + config.enable_debugging, + config.file_list, + function () { + App.init (); + }, + function (asset) + { + if (typeof window != 'undefined') { + return fetch (asset, { credentials: 'same-origin' }); + } else { + // The default mono_load_runtime_and_bcl defaults to using + // fetch to load the assets. It also provides a way to set a + // fetch promise callback. + // Here we wrap the file read in a promise and fake a fetch response + // structure. + return new Promise((resolve, reject) => { + var response = { ok: true, url: asset, + arrayBuffer: function() { + return new Promise((resolve2, reject2) => { + resolve2(new Uint8Array (read (asset, 'binary'))); + } + )} + } + resolve(response) + }) + } + } + ); + }, +}; + +if (typeof window == "undefined") + load ("dotnet.js"); + +const IGNORE_PARAM_COUNT = -1; + +var App = { + init: function () { + + var assembly_load = Module.cwrap ('mono_wasm_assembly_load', 'number', ['string']) + var find_class = Module.cwrap ('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string']) + var find_method = Module.cwrap ('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number']) + var runtime_invoke = Module.cwrap ('mono_wasm_invoke_method', 'number', ['number', 'number', 'number', 'number']); + var string_from_js = Module.cwrap ('mono_wasm_string_from_js', 'number', ['string']); + var assembly_get_entry_point = Module.cwrap ('mono_wasm_assembly_get_entry_point', 'number', ['number']); + var string_get_utf8 = Module.cwrap ('mono_wasm_string_get_utf8', 'string', ['number']); + var string_array_new = Module.cwrap ('mono_wasm_string_array_new', 'number', ['number']); + var obj_array_set = Module.cwrap ('mono_wasm_obj_array_set', 'void', ['number', 'number', 'number']); + var exit = Module.cwrap ('mono_wasm_exit', 'void', ['number']); + var wasm_setenv = Module.cwrap ('mono_wasm_setenv', 'void', ['string', 'string']); + var wasm_set_main_args = Module.cwrap ('mono_wasm_set_main_args', 'void', ['number', 'number']); + var wasm_strdup = Module.cwrap ('mono_wasm_strdup', 'number', ['string']); + var unbox_int = Module.cwrap ('mono_unbox_int', 'number', ['number']); + + Module.wasm_exit = Module.cwrap ('mono_wasm_exit', 'void', ['number']); + + Module.print("Initializing....."); + + for (var i = 0; i < profilers.length; ++i) { + var init = Module.cwrap ('mono_wasm_load_profiler_' + profilers [i], 'void', ['string']) + + init (""); + } + + if (args[0] == "--regression") { + var exec_regression = Module.cwrap ('mono_wasm_exec_regression', 'number', ['number', 'string']) + + var res = 0; + try { + res = exec_regression (10, args[1]); + Module.print ("REGRESSION RESULT: " + res); + } catch (e) { + Module.print ("ABORT: " + e); + print (e.stack); + res = 1; + } + + if (res) + fail_exec ("REGRESSION TEST FAILED"); + + return; + } + + if (runtime_args.length > 0) + MONO.mono_wasm_set_runtime_options (runtime_args); + + if (args[0] == "--run") { + // Run an exe + if (args.length == 1) + fail_exec ("Error: Missing main executable argument."); + main_assembly = assembly_load (args[1]); + if (main_assembly == 0) + fail_exec ("Error: Unable to load main executable '" + args[1] + "'"); + main_method = assembly_get_entry_point (main_assembly); + if (main_method == 0) + fail_exec ("Error: Main (string[]) method not found."); + + var app_args = string_array_new (args.length - 2); + for (var i = 2; i < args.length; ++i) { + obj_array_set (app_args, i - 2, string_from_js (args [i])); + } + + var main_argc = args.length - 2 + 1; + var main_argv = Module._malloc (main_argc * 4); + aindex = 0; + Module.setValue (main_argv + (aindex * 4), wasm_strdup (args [1]), "i32") + aindex += 1; + for (var i = 2; i < args.length; ++i) { + Module.setValue (main_argv + (aindex * 4), wasm_strdup (args [i]), "i32"); + aindex += 1; + } + wasm_set_main_args (main_argc, main_argv); + + try { + var invoke_args = Module._malloc (4); + Module.setValue (invoke_args, app_args, "i32"); + var eh_exc = Module._malloc (4); + Module.setValue (eh_exc, 0, "i32"); + var res = runtime_invoke (main_method, 0, invoke_args, eh_exc); + var eh_res = Module.getValue (eh_exc, "i32"); + if (eh_res != 0) { + print ("Exception:" + string_get_utf8 (res)); + test_exit (1); + } + var exit_code = unbox_int (res); + if (exit_code != 0) + test_exit (exit_code); + } catch (ex) { + print ("JS exception: " + ex); + print (ex.stack); + test_exit (1); + } + + if (is_browser) + test_exit (0); + + return; + } else { + fail_exec ("Unhanded argument: " + args [0]); + } + }, +}; diff --git a/src/mono/wasm/runtime/binding_support.js b/src/mono/wasm/runtime/binding_support.js new file mode 100644 index 0000000000000..c97e327373e60 --- /dev/null +++ b/src/mono/wasm/runtime/binding_support.js @@ -0,0 +1,1276 @@ +// 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. + +var BindingSupportLib = { + $BINDING__postset: 'BINDING.export_functions (Module);', + $BINDING: { + BINDING_ASM: "[System.Runtime.InteropServices.JavaScript]System.Runtime.InteropServices.JavaScript.Runtime", + mono_wasm_object_registry: [], + mono_wasm_ref_counter: 0, + mono_wasm_free_list: [], + mono_wasm_marshal_enum_as_int: false, + mono_bindings_init: function (binding_asm) { + this.BINDING_ASM = binding_asm; + }, + + export_functions: function (module) { + module ["mono_bindings_init"] = BINDING.mono_bindings_init.bind(BINDING); + module ["mono_method_invoke"] = BINDING.call_method.bind(BINDING); + module ["mono_method_get_call_signature"] = BINDING.mono_method_get_call_signature.bind(BINDING); + module ["mono_method_resolve"] = BINDING.resolve_method_fqn.bind(BINDING); + module ["mono_bind_static_method"] = BINDING.bind_static_method.bind(BINDING); + module ["mono_call_static_method"] = BINDING.call_static_method.bind(BINDING); + module ["mono_bind_assembly_entry_point"] = BINDING.bind_assembly_entry_point.bind(BINDING); + module ["mono_call_assembly_entry_point"] = BINDING.call_assembly_entry_point.bind(BINDING); + }, + + bindings_lazy_init: function () { + if (this.init) + return; + + this.assembly_load = Module.cwrap ('mono_wasm_assembly_load', 'number', ['string']); + this.find_class = Module.cwrap ('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string']); + this.find_method = Module.cwrap ('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number']); + this.invoke_method = Module.cwrap ('mono_wasm_invoke_method', 'number', ['number', 'number', 'number', 'number']); + this.mono_string_get_utf8 = Module.cwrap ('mono_wasm_string_get_utf8', 'number', ['number']); + this.js_string_to_mono_string = Module.cwrap ('mono_wasm_string_from_js', 'number', ['string']); + this.mono_get_obj_type = Module.cwrap ('mono_wasm_get_obj_type', 'number', ['number']); + this.mono_unbox_int = Module.cwrap ('mono_unbox_int', 'number', ['number']); + this.mono_unbox_float = Module.cwrap ('mono_wasm_unbox_float', 'number', ['number']); + this.mono_array_length = Module.cwrap ('mono_wasm_array_length', 'number', ['number']); + this.mono_array_get = Module.cwrap ('mono_wasm_array_get', 'number', ['number', 'number']); + this.mono_obj_array_new = Module.cwrap ('mono_wasm_obj_array_new', 'number', ['number']); + this.mono_obj_array_set = Module.cwrap ('mono_wasm_obj_array_set', 'void', ['number', 'number', 'number']); + this.mono_unbox_enum = Module.cwrap ('mono_wasm_unbox_enum', 'number', ['number']); + this.assembly_get_entry_point = Module.cwrap ('mono_wasm_assembly_get_entry_point', 'number', ['number']); + + // receives a byteoffset into allocated Heap with a size. + this.mono_typed_array_new = Module.cwrap ('mono_wasm_typed_array_new', 'number', ['number','number','number','number']); + + var binding_fqn_asm = this.BINDING_ASM.substring(this.BINDING_ASM.indexOf ("[") + 1, this.BINDING_ASM.indexOf ("]")).trim(); + var binding_fqn_class = this.BINDING_ASM.substring (this.BINDING_ASM.indexOf ("]") + 1).trim(); + + this.binding_module = this.assembly_load (binding_fqn_asm); + if (!this.binding_module) + throw "Can't find bindings module assembly: " + binding_fqn_asm; + + if (binding_fqn_class !== null && typeof binding_fqn_class !== "undefined") + { + var namespace = "System.Runtime.InteropServices.JavaScript"; + var classname = binding_fqn_class.length > 0 ? binding_fqn_class : "Runtime"; + if (binding_fqn_class.indexOf(".") != -1) { + var idx = binding_fqn_class.lastIndexOf("."); + namespace = binding_fqn_class.substring (0, idx); + classname = binding_fqn_class.substring (idx + 1); + } + } + + var wasm_runtime_class = this.find_class (this.binding_module, namespace, classname) + if (!wasm_runtime_class) + throw "Can't find " + binding_fqn_class + " class"; + + var get_method = function(method_name) { + var res = BINDING.find_method (wasm_runtime_class, method_name, -1) + if (!res) + throw "Can't find method " + namespace + "." + classname + ":" + method_name; + return res; + } + this.bind_js_obj = get_method ("BindJSObject"); + this.bind_core_clr_obj = get_method ("BindCoreCLRObject"); + this.bind_existing_obj = get_method ("BindExistingObject"); + this.unbind_js_obj = get_method ("UnBindJSObject"); + this.unbind_js_obj_and_free = get_method ("UnBindJSObjectAndFree"); + this.unbind_raw_obj_and_free = get_method ("UnBindRawJSObjectAndFree"); + this.get_js_id = get_method ("GetJSObjectId"); + this.get_raw_mono_obj = get_method ("GetDotNetObject"); + + this.box_js_int = get_method ("BoxInt"); + this.box_js_double = get_method ("BoxDouble"); + this.box_js_bool = get_method ("BoxBool"); + this.is_simple_array = get_method ("IsSimpleArray"); + this.get_core_type = get_method ("GetCoreType"); + this.setup_js_cont = get_method ("SetupJSContinuation"); + + this.create_tcs = get_method ("CreateTaskSource"); + this.set_tcs_result = get_method ("SetTaskSourceResult"); + this.set_tcs_failure = get_method ("SetTaskSourceFailure"); + this.tcs_get_task_and_bind = get_method ("GetTaskAndBind"); + this.get_call_sig = get_method ("GetCallSignature"); + + this.object_to_string = get_method ("ObjectToString"); + this.get_date_value = get_method ("GetDateValue"); + this.create_date_time = get_method ("CreateDateTime"); + this.create_uri = get_method ("CreateUri"); + + this.init = true; + }, + + get_js_obj: function (js_handle) { + if (js_handle > 0) + return this.mono_wasm_require_handle(js_handle); + return null; + }, + + conv_string: function (mono_obj) { + return MONO.string_decoder.copy (mono_obj); + }, + + is_nested_array: function (ele) { + return this.call_method (this.is_simple_array, null, "mi", [ ele ]); + }, + + mono_array_to_js_array: function (mono_array) { + if (mono_array == 0) + return null; + + var res = []; + var len = this.mono_array_length (mono_array); + for (var i = 0; i < len; ++i) + { + var ele = this.mono_array_get (mono_array, i); + if (this.is_nested_array(ele)) + res.push(this.mono_array_to_js_array(ele)); + else + res.push (this.unbox_mono_obj (ele)); + } + + return res; + }, + + js_array_to_mono_array: function (js_array) { + var mono_array = this.mono_obj_array_new (js_array.length); + for (var i = 0; i < js_array.length; ++i) { + this.mono_obj_array_set (mono_array, i, this.js_to_mono_obj (js_array [i])); + } + return mono_array; + }, + + unbox_mono_obj: function (mono_obj) { + if (mono_obj == 0) + return undefined; + var type = this.mono_get_obj_type (mono_obj); + //See MARSHAL_TYPE_ defines in driver.c + switch (type) { + case 1: // int + return this.mono_unbox_int (mono_obj); + case 2: // float + return this.mono_unbox_float (mono_obj); + case 3: //string + return this.conv_string (mono_obj); + case 4: //vts + throw new Error ("no idea on how to unbox value types"); + case 5: { // delegate + var obj = this.extract_js_obj (mono_obj); + return function () { + return BINDING.invoke_delegate (obj, arguments); + }; + } + case 6: {// Task + + if (typeof Promise === "undefined" || typeof Promise.resolve === "undefined") + throw new Error ("Promises are not supported thus C# Tasks can not work in this context."); + + var obj = this.extract_js_obj (mono_obj); + var cont_obj = null; + var promise = new Promise (function (resolve, reject) { + cont_obj = { + resolve: resolve, + reject: reject + }; + }); + + this.call_method (this.setup_js_cont, null, "mo", [ mono_obj, cont_obj ]); + obj.__mono_js_cont__ = cont_obj.__mono_gchandle__; + cont_obj.__mono_js_task__ = obj.__mono_gchandle__; + return promise; + } + + case 7: // ref type + return this.extract_js_obj (mono_obj); + + case 8: // bool + return this.mono_unbox_int (mono_obj) != 0; + + case 9: // enum + + if(this.mono_wasm_marshal_enum_as_int) + { + return this.mono_unbox_enum (mono_obj); + } + else + { + enumValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]); + } + + return enumValue; + + + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + { + throw new Error ("Marshalling of primitive arrays are not supported. Use the corresponding TypedArray instead."); + } + case 20: // clr .NET DateTime + var dateValue = this.call_method(this.get_date_value, null, "md", [ mono_obj ]); + return new Date(dateValue); + case 21: // clr .NET DateTimeOffset + var dateoffsetValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]); + return dateoffsetValue; + case 22: // clr .NET Uri + var uriValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]); + return uriValue; + default: + throw new Error ("no idea on how to unbox object kind " + type); + } + }, + + create_task_completion_source: function () { + return this.call_method (this.create_tcs, null, "i", [ -1 ]); + }, + + set_task_result: function (tcs, result) { + tcs.is_mono_tcs_result_set = true; + this.call_method (this.set_tcs_result, null, "oo", [ tcs, result ]); + if (tcs.is_mono_tcs_task_bound) + this.free_task_completion_source(tcs); + }, + + set_task_failure: function (tcs, reason) { + tcs.is_mono_tcs_result_set = true; + this.call_method (this.set_tcs_failure, null, "os", [ tcs, reason.toString () ]); + if (tcs.is_mono_tcs_task_bound) + this.free_task_completion_source(tcs); + }, + + // https://github.com/Planeshifter/emscripten-examples/blob/master/01_PassingArrays/sum_post.js + js_typedarray_to_heap: function(typedArray){ + var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT; + var ptr = Module._malloc(numBytes); + var heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes); + heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, numBytes)); + return heapBytes; + }, + js_to_mono_obj: function (js_obj) { + this.bindings_lazy_init (); + + // determines if the javascript object is a Promise or Promise like which can happen + // when using an external Promise library. The javascript object should be marshalled + // as managed Task objects. + // + // Example is when Bluebird is included in a web page using a script tag, it overwrites the + // global Promise object by default with its own version of Promise. + function isThenable() { + // When using an external Promise library the Promise.resolve may not be sufficient + // to identify the object as a Promise. + return Promise.resolve(js_obj) === js_obj || + ((typeof js_obj === "object" || typeof js_obj === "function") && typeof js_obj.then === "function") + } + + switch (true) { + case js_obj === null: + case typeof js_obj === "undefined": + return 0; + case typeof js_obj === "number": + if (parseInt(js_obj) == js_obj) + return this.call_method (this.box_js_int, null, "im", [ js_obj ]); + return this.call_method (this.box_js_double, null, "dm", [ js_obj ]); + case typeof js_obj === "string": + return this.js_string_to_mono_string (js_obj); + case typeof js_obj === "boolean": + return this.call_method (this.box_js_bool, null, "im", [ js_obj ]); + case isThenable() === true: + var the_task = this.try_extract_mono_obj (js_obj); + if (the_task) + return the_task; + var tcs = this.create_task_completion_source (); + js_obj.then (function (result) { + BINDING.set_task_result (tcs, result); + }, function (reason) { + BINDING.set_task_failure (tcs, reason); + }) + return this.get_task_and_bind (tcs, js_obj); + case js_obj.constructor.name === "Date": + // We may need to take into account the TimeZone Offset + return this.call_method(this.create_date_time, null, "dm", [ js_obj.getTime() ]); + default: + return this.extract_mono_obj (js_obj); + } + }, + js_to_mono_uri: function (js_obj) { + this.bindings_lazy_init (); + + switch (true) { + case js_obj === null: + case typeof js_obj === "undefined": + return 0; + case typeof js_obj === "string": + return this.call_method(this.create_uri, null, "sm", [ js_obj ]) + default: + return this.extract_mono_obj (js_obj); + } + }, + js_typed_array_to_array : function (js_obj) { + + // JavaScript typed arrays are array-like objects and provide a mechanism for accessing + // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays + // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object) + // is an object representing a chunk of data; it has no format to speak of, and offers no + // mechanism for accessing its contents. In order to access the memory contained in a buffer, + // you need to use a view. A view provides a context — that is, a data type, starting offset, + // and number of elements — that turns the data into an actual typed array. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays + if (!!(js_obj.buffer instanceof ArrayBuffer && js_obj.BYTES_PER_ELEMENT)) + { + var arrayType = 0; + if (js_obj instanceof Int8Array) + arrayType = 11; + if (js_obj instanceof Uint8Array) + arrayType = 12; + if (js_obj instanceof Uint8ClampedArray) + arrayType = 12; + if (js_obj instanceof Int16Array) + arrayType = 13; + if (js_obj instanceof Uint16Array) + arrayType = 14; + if (js_obj instanceof Int32Array) + arrayType = 15; + if (js_obj instanceof Uint32Array) + arrayType = 16; + if (js_obj instanceof Float32Array) + arrayType = 17; + if (js_obj instanceof Float64Array) + arrayType = 18; + + var heapBytes = this.js_typedarray_to_heap(js_obj); + var bufferArray = this.mono_typed_array_new(heapBytes.byteOffset, js_obj.length, js_obj.BYTES_PER_ELEMENT, arrayType); + Module._free(heapBytes.byteOffset); + return bufferArray; + } + else { + throw new Error("Object '" + js_obj + "' is not a typed array"); + } + + + }, + // Copy the existing typed array to the heap pointed to by the pinned array address + // typed array memory -> copy to heap -> address of managed pinned array + typedarray_copy_to : function (typed_array, pinned_array, begin, end, bytes_per_element) { + + // JavaScript typed arrays are array-like objects and provide a mechanism for accessing + // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays + // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object) + // is an object representing a chunk of data; it has no format to speak of, and offers no + // mechanism for accessing its contents. In order to access the memory contained in a buffer, + // you need to use a view. A view provides a context — that is, a data type, starting offset, + // and number of elements — that turns the data into an actual typed array. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays + if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT)) + { + // Some sanity checks of what is being asked of us + // lets play it safe and throw an error here instead of assuming to much. + // Better safe than sorry later + if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT) + throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'"); + + // how much space we have to work with + var num_of_bytes = (end - begin) * bytes_per_element; + // how much typed buffer space are we talking about + var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT; + // only use what is needed. + if (num_of_bytes > view_bytes) + num_of_bytes = view_bytes; + + // offset index into the view + var offset = begin * bytes_per_element; + + // Create a view over the heap pointed to by the pinned array address + var heapBytes = new Uint8Array(Module.HEAPU8.buffer, pinned_array + offset, num_of_bytes); + // Copy the bytes of the typed array to the heap. + heapBytes.set(new Uint8Array(typed_array.buffer, typed_array.byteOffset, num_of_bytes)); + + return num_of_bytes; + } + else { + throw new Error("Object '" + typed_array + "' is not a typed array"); + } + + }, + // Copy the pinned array address from pinned_array allocated on the heap to the typed array. + // adress of managed pinned array -> copy from heap -> typed array memory + typedarray_copy_from : function (typed_array, pinned_array, begin, end, bytes_per_element) { + + // JavaScript typed arrays are array-like objects and provide a mechanism for accessing + // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays + // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object) + // is an object representing a chunk of data; it has no format to speak of, and offers no + // mechanism for accessing its contents. In order to access the memory contained in a buffer, + // you need to use a view. A view provides a context — that is, a data type, starting offset, + // and number of elements — that turns the data into an actual typed array. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays + if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT)) + { + // Some sanity checks of what is being asked of us + // lets play it safe and throw an error here instead of assuming to much. + // Better safe than sorry later + if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT) + throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'"); + + // how much space we have to work with + var num_of_bytes = (end - begin) * bytes_per_element; + // how much typed buffer space are we talking about + var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT; + // only use what is needed. + if (num_of_bytes > view_bytes) + num_of_bytes = view_bytes; + + // Create a new view for mapping + var typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes); + // offset index into the view + var offset = begin * bytes_per_element; + // Set view bytes to value from HEAPU8 + typedarrayBytes.set(Module.HEAPU8.subarray(pinned_array + offset, pinned_array + offset + num_of_bytes)); + return num_of_bytes; + } + else { + throw new Error("Object '" + typed_array + "' is not a typed array"); + } + + }, + // Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array. + // adress of managed pinned array -> copy from heap -> typed array memory + typed_array_from : function (pinned_array, begin, end, bytes_per_element, type) { + + // typed array + var newTypedArray = 0; + + switch (type) + { + case 5: + newTypedArray = new Int8Array(end - begin); + break; + case 6: + newTypedArray = new Uint8Array(end - begin); + break; + case 7: + newTypedArray = new Int16Array(end - begin); + break; + case 8: + newTypedArray = new Uint16Array(end - begin); + break; + case 9: + newTypedArray = new Int32Array(end - begin); + break; + case 10: + newTypedArray = new Uint32Array(end - begin); + break; + case 13: + newTypedArray = new Float32Array(end - begin); + break; + case 14: + newTypedArray = new Float64Array(end - begin); + break; + case 15: // This is a special case because the typed array is also byte[] + newTypedArray = new Uint8ClampedArray(end - begin); + break; + } + + this.typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element); + return newTypedArray; + }, + js_to_mono_enum: function (method, parmIdx, js_obj) { + this.bindings_lazy_init (); + + if (js_obj === null || typeof js_obj === "undefined") + return 0; + + var monoObj = this.js_to_mono_obj(js_obj); + // Check enum contract + var monoEnum = this.call_method(this.object_to_enum, null, "iimm", [ method, parmIdx, monoObj ]) + // return the unboxed enum value. + return this.mono_unbox_enum(monoEnum); + }, + wasm_binding_obj_new: function (js_obj_id, type) + { + return this.call_method (this.bind_js_obj, null, "io", [js_obj_id, type]); + }, + wasm_bind_existing: function (mono_obj, js_id) + { + return this.call_method (this.bind_existing_obj, null, "mi", [mono_obj, js_id]); + }, + + wasm_bind_core_clr_obj: function (js_id, gc_handle) + { + return this.call_method (this.bind_core_clr_obj, null, "ii", [js_id, gc_handle]); + }, + + wasm_unbind_js_obj: function (js_obj_id) + { + this.call_method (this.unbind_js_obj, null, "i", [js_obj_id]); + }, + + wasm_unbind_js_obj_and_free: function (js_obj_id) + { + this.call_method (this.unbind_js_obj_and_free, null, "i", [js_obj_id]); + }, + + wasm_get_js_id: function (mono_obj) + { + return this.call_method (this.get_js_id, null, "m", [mono_obj]); + }, + + wasm_get_raw_obj: function (gchandle) + { + return this.call_method (this.get_raw_mono_obj, null, "im", [gchandle]); + }, + + try_extract_mono_obj:function (js_obj) { + if (js_obj === null || typeof js_obj === "undefined" || typeof js_obj.__mono_gchandle__ === "undefined") + return 0; + return this.wasm_get_raw_obj (js_obj.__mono_gchandle__); + }, + + mono_method_get_call_signature: function(method) { + this.bindings_lazy_init (); + + return this.call_method (this.get_call_sig, null, "i", [ method ]); + }, + + get_task_and_bind: function (tcs, js_obj) { + var gc_handle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++; + var task_gchandle = this.call_method (this.tcs_get_task_and_bind, null, "oi", [ tcs, gc_handle + 1 ]); + js_obj.__mono_gchandle__ = task_gchandle; + this.mono_wasm_object_registry[gc_handle] = js_obj; + this.free_task_completion_source(tcs); + tcs.is_mono_tcs_task_bound = true; + js_obj.__mono_bound_tcs__ = tcs.__mono_gchandle__; + tcs.__mono_bound_task__ = js_obj.__mono_gchandle__; + return this.wasm_get_raw_obj (js_obj.__mono_gchandle__); + }, + + free_task_completion_source: function (tcs) { + if (tcs.is_mono_tcs_result_set) + { + this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_gchandle__ ]); + } + if (tcs.__mono_bound_task__) + { + this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_bound_task__ ]); + } + }, + + extract_mono_obj: function (js_obj) { + + if (js_obj === null || typeof js_obj === "undefined") + return 0; + + if (!js_obj.is_mono_bridged_obj) { + var gc_handle = this.mono_wasm_register_obj(js_obj); + return this.wasm_get_raw_obj (gc_handle); + } + + + return this.wasm_get_raw_obj (js_obj.__mono_gchandle__); + }, + + extract_js_obj: function (mono_obj) { + if (mono_obj == 0) + return null; + + var js_id = this.wasm_get_js_id (mono_obj); + if (js_id > 0) + return this.mono_wasm_require_handle(js_id); + + var gcHandle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++; + var js_obj = { + __mono_gchandle__: this.wasm_bind_existing(mono_obj, gcHandle + 1), + is_mono_bridged_obj: true + }; + + this.mono_wasm_object_registry[gcHandle] = js_obj; + return js_obj; + }, + + /* + args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values: + + i: int32 + j: int32 - Enum with underlying type of int32 + l: int64 + k: int64 - Enum with underlying type of int64 + f: float + d: double + s: string + o: js object will be converted to a C# object (this will box numbers/bool/promises) + m: raw mono object. Don't use it unless you know what you're doing + + additionally you can append 'm' to args_marshal beyond `args.length` if you don't want the return value marshaled + */ + call_method: function (method, this_arg, args_marshal, args) { + this.bindings_lazy_init (); + + // Allocate memory for error + var has_args = args !== null && typeof args !== "undefined" && args.length > 0; + var has_args_marshal = args_marshal !== null && typeof args_marshal !== "undefined" && args_marshal.length > 0; + + if (has_args_marshal && (!has_args || args.length > args_marshal.length)) + throw Error("Parameter count mismatch."); + + var args_start = null; + var buffer = null; + var exception_out = null; + + // check if the method signature needs argument mashalling + if (has_args_marshal && has_args) { + var i; + + var converters = this.converters; + if (!converters) { + converters = new Map (); + converters.set ('m', { steps: [{ }], size: 0}); + converters.set ('s', { steps: [{ convert: this.js_string_to_mono_string.bind (this)}], size: 0}); + converters.set ('o', { steps: [{ convert: this.js_to_mono_obj.bind (this)}], size: 0}); + converters.set ('u', { steps: [{ convert: this.js_to_mono_uri.bind (this)}], size: 0}); + converters.set ('k', { steps: [{ convert: this.js_to_mono_enum.bind (this), indirect: 'i64'}], size: 8}); + converters.set ('j', { steps: [{ convert: this.js_to_mono_enum.bind (this), indirect: 'i32'}], size: 8}); + converters.set ('i', { steps: [{ indirect: 'i32'}], size: 8}); + converters.set ('l', { steps: [{ indirect: 'i64'}], size: 8}); + converters.set ('f', { steps: [{ indirect: 'float'}], size: 8}); + converters.set ('d', { steps: [{ indirect: 'double'}], size: 8}); + this.converters = converters; + } + + var converter = converters.get (args_marshal); + if (!converter) { + var steps = []; + var size = 0; + + for (i = 0; i < args_marshal.length; ++i) { + var conv = this.converters.get (args_marshal[i]); + if (!conv) + throw Error ("Unknown parameter type " + type); + + steps.push (conv.steps[0]); + size += conv.size; + } + converter = { steps: steps, size: size }; + converters.set (args_marshal, converter); + } + + // assume at least 8 byte alignment from malloc + buffer = Module._malloc (converter.size + (args.length * 4) + 4); + var indirect_start = buffer; // buffer + buffer % 8 + exception_out = indirect_start + converter.size; + args_start = exception_out + 4; + + var slot = args_start; + var indirect_value = indirect_start; + for (i = 0; i < args.length; ++i) { + var handler = converter.steps[i]; + var obj = handler.convert ? handler.convert (args[i], method, i) : args[i]; + + if (handler.indirect) { + Module.setValue (indirect_value, obj, handler.indirect); + obj = indirect_value; + indirect_value += 8; + } + + Module.setValue (slot, obj, "*"); + slot += 4; + } + } else { + // only marshal the exception + exception_out = buffer = Module._malloc (4); + } + + Module.setValue (exception_out, 0, "*"); + + var res = this.invoke_method (method, this_arg, args_start, exception_out); + var eh_res = Module.getValue (exception_out, "*"); + + Module._free (buffer); + + if (eh_res != 0) { + var msg = this.conv_string (res); + throw new Error (msg); //the convention is that invoke_method ToString () any outgoing exception + } + + if (has_args_marshal && has_args) { + if (args_marshal.length >= args.length && args_marshal [args.length] === "m") + return res; + } + + return this.unbox_mono_obj (res); + }, + + invoke_delegate: function (delegate_obj, js_args) { + this.bindings_lazy_init (); + + if (!this.delegate_dynamic_invoke) { + if (!this.corlib) + this.corlib = this.assembly_load ("mscorlib"); + if (!this.delegate_class) + this.delegate_class = this.find_class (this.corlib, "System", "Delegate"); + if (!this.delegate_class) + { + throw new Error("System.Delegate class can not be resolved."); + } + this.delegate_dynamic_invoke = this.find_method (this.delegate_class, "DynamicInvoke", -1); + } + var mono_args = this.js_array_to_mono_array (js_args); + if (!this.delegate_dynamic_invoke) + throw new Error("System.Delegate.DynamicInvoke method can not be resolved."); + // Note: the single 'm' passed here is causing problems with AOT. Changed to "mo" again. + // This may need more analysis if causes problems again. + return this.call_method (this.delegate_dynamic_invoke, this.extract_mono_obj (delegate_obj), "mo", [ mono_args ]); + }, + + resolve_method_fqn: function (fqn) { + var assembly = fqn.substring(fqn.indexOf ("[") + 1, fqn.indexOf ("]")).trim(); + fqn = fqn.substring (fqn.indexOf ("]") + 1).trim(); + + var methodname = fqn.substring(fqn.indexOf (":") + 1); + fqn = fqn.substring (0, fqn.indexOf (":")).trim (); + + var namespace = ""; + var classname = fqn; + if (fqn.indexOf(".") != -1) { + var idx = fqn.lastIndexOf("."); + namespace = fqn.substring (0, idx); + classname = fqn.substring (idx + 1); + } + + var asm = this.assembly_load (assembly); + if (!asm) + throw new Error ("Could not find assembly: " + assembly); + + var klass = this.find_class(asm, namespace, classname); + if (!klass) + throw new Error ("Could not find class: " + namespace + ":" +classname); + + var method = this.find_method (klass, methodname, -1); + if (!method) + throw new Error ("Could not find method: " + methodname); + return method; + }, + + call_static_method: function (fqn, args, signature) { + this.bindings_lazy_init (); + + var method = this.resolve_method_fqn (fqn); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return this.call_method (method, null, signature, args); + }, + + bind_static_method: function (fqn, signature) { + this.bindings_lazy_init (); + + var method = this.resolve_method_fqn (fqn); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return function() { + return BINDING.call_method (method, null, signature, arguments); + }; + }, + bind_assembly_entry_point: function (assembly) { + this.bindings_lazy_init (); + + var asm = this.assembly_load (assembly); + if (!asm) + throw new Error ("Could not find assembly: " + assembly); + + var method = this.assembly_get_entry_point(asm); + if (!method) + throw new Error ("Could not find entry point for assembly: " + assembly); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return function() { + return BINDING.call_method (method, null, signature, arguments); + }; + }, + call_assembly_entry_point: function (assembly, args, signature) { + this.bindings_lazy_init (); + + var asm = this.assembly_load (assembly); + if (!asm) + throw new Error ("Could not find assembly: " + assembly); + + var method = this.assembly_get_entry_point(asm); + if (!method) + throw new Error ("Could not find entry point for assembly: " + assembly); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return this.call_method (method, null, signature, args); + }, + wasm_get_core_type: function (obj) + { + return this.call_method (this.get_core_type, null, "so", [ "WebAssembly.Core."+obj.constructor.name ]); + }, + get_wasm_type: function(obj) { + var coreType = obj[Symbol.for("wasm type")]; + if (typeof coreType === "undefined") { + coreType = this.wasm_get_core_type(obj); + if (typeof coreType !== "undefined") { + obj.constructor.prototype[Symbol.for("wasm type")] = coreType; + } + } + return coreType; + }, + // Object wrapping helper functions to handle reference handles that will + // be used in managed code. + mono_wasm_register_obj: function(obj) { + + var gc_handle = undefined; + if (obj !== null && typeof obj !== "undefined") + { + gc_handle = obj.__mono_gchandle__; + + if (typeof gc_handle === "undefined") { + var handle = this.mono_wasm_free_list.length ? + this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++; + obj.__mono_jshandle__ = handle; + // Obtain the JS -> C# type mapping. + var wasm_type = this.get_wasm_type(obj); + gc_handle = obj.__mono_gchandle__ = this.wasm_binding_obj_new(handle + 1, wasm_type); + this.mono_wasm_object_registry[handle] = obj; + + } + } + return gc_handle; + }, + mono_wasm_require_handle: function(handle) { + if (handle > 0) + return this.mono_wasm_object_registry[handle - 1]; + return null; + }, + mono_wasm_unregister_obj: function(js_id) { + var obj = this.mono_wasm_object_registry[js_id - 1]; + if (typeof obj !== "undefined" && obj !== null) { + // if this is the global object then do not + // unregister it. + if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj) + return obj; + + var gc_handle = obj.__mono_gchandle__; + if (typeof gc_handle !== "undefined") { + this.wasm_unbind_js_obj_and_free(js_id); + + obj.__mono_gchandle__ = undefined; + obj.__mono_jshandle__ = undefined; + + this.mono_wasm_object_registry[js_id - 1] = undefined; + this.mono_wasm_free_list.push(js_id - 1); + } + } + return obj; + }, + mono_wasm_free_handle: function(handle) { + this.mono_wasm_unregister_obj(handle); + }, + mono_wasm_free_raw_object: function(js_id) { + var obj = this.mono_wasm_object_registry[js_id - 1]; + if (typeof obj !== "undefined" && obj !== null) { + // if this is the global object then do not + // unregister it. + if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj) + return obj; + + var gc_handle = obj.__mono_gchandle__; + if (typeof gc_handle !== "undefined") { + + obj.__mono_gchandle__ = undefined; + obj.__mono_jshandle__ = undefined; + + this.mono_wasm_object_registry[js_id - 1] = undefined; + this.mono_wasm_free_list.push(js_id - 1); + } + } + return obj; + }, + mono_wasm_get_global: function() { + function testGlobal(obj) { + obj['___mono_wasm_global___'] = obj; + var success = typeof ___mono_wasm_global___ === 'object' && obj['___mono_wasm_global___'] === obj; + if (!success) { + delete obj['___mono_wasm_global___']; + } + return success; + } + if (typeof ___mono_wasm_global___ === 'object') { + return ___mono_wasm_global___; + } + if (typeof global === 'object' && testGlobal(global)) { + ___mono_wasm_global___ = global; + } else if (typeof window === 'object' && testGlobal(window)) { + ___mono_wasm_global___ = window; + } else if (testGlobal((function(){return Function;})()('return this')())) { + + ___mono_wasm_global___ = (function(){return Function;})()('return this')(); + + } + if (typeof ___mono_wasm_global___ === 'object') { + return ___mono_wasm_global___; + } + throw Error('Unable to get mono wasm global object.'); + }, + + }, + + mono_wasm_invoke_js_with_args: function(js_handle, method_name, args, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.get_js_obj (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var js_name = BINDING.conv_string (method_name); + if (!js_name) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid method name object '" + method_name + "'"); + } + + var js_args = BINDING.mono_array_to_js_array(args); + + var res; + try { + var m = obj [js_name]; + if (typeof m === "undefined") + throw new Error("Method: '" + js_name + "' not found for: '" + Object.prototype.toString.call(obj) + "'"); + var res = m.apply (obj, js_args); + return BINDING.js_to_mono_obj (res); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_get_object_property: function(js_handle, property_name, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.mono_wasm_require_handle (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var js_name = BINDING.conv_string (property_name); + if (!js_name) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'"); + } + + var res; + try { + var m = obj [js_name]; + if (m === Object(m) && obj.__is_mono_proxied__) + m.__is_mono_proxied__ = true; + + return BINDING.js_to_mono_obj (m); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || typeof res === "undefined") + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_set_object_property: function (js_handle, property_name, value, createIfNotExist, hasOwnProperty, is_exception) { + + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var property = BINDING.conv_string (property_name); + if (!property) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid property name object '" + property_name + "'"); + } + + var result = false; + + var js_value = BINDING.unbox_mono_obj(value); + + if (createIfNotExist) { + requireObject[property] = js_value; + result = true; + } + else { + result = false; + if (!createIfNotExist) + { + if (!requireObject.hasOwnProperty(property)) + return false; + } + if (hasOwnProperty === true) { + if (requireObject.hasOwnProperty(property)) { + requireObject[property] = js_value; + result = true; + } + } + else { + requireObject[property] = js_value; + result = true; + } + + } + return BINDING.call_method (BINDING.box_js_bool, null, "im", [ result ]); + }, + mono_wasm_get_by_index: function(js_handle, property_index, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.mono_wasm_require_handle (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + try { + var m = obj [property_index]; + return BINDING.js_to_mono_obj (m); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || typeof res === "undefined") + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_set_by_index: function(js_handle, property_index, value, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.mono_wasm_require_handle (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var js_value = BINDING.unbox_mono_obj(value); + + try { + obj [property_index] = js_value; + return true; + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || typeof res === "undefined") + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_get_global_object: function(global_name, is_exception) { + BINDING.bindings_lazy_init (); + + var js_name = BINDING.conv_string (global_name); + + var globalObj = undefined; + + if (!js_name) { + globalObj = BINDING.mono_wasm_get_global(); + } + else { + globalObj = BINDING.mono_wasm_get_global()[js_name]; + } + + if (globalObj === null || typeof globalObj === undefined) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found."); + } + + return BINDING.js_to_mono_obj (globalObj); + }, + mono_wasm_release_handle: function(js_handle, is_exception) { + BINDING.bindings_lazy_init (); + + BINDING.mono_wasm_free_handle(js_handle); + }, + mono_wasm_release_object: function(js_handle, is_exception) { + BINDING.bindings_lazy_init (); + + BINDING.mono_wasm_free_raw_object(js_handle); + }, + mono_wasm_bind_core_object: function(js_handle, gc_handle, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle ); + requireObject.__mono_gchandle__ = gc_handle; + return gc_handle; + }, + mono_wasm_bind_host_object: function(js_handle, gc_handle, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle ); + requireObject.__mono_gchandle__ = gc_handle; + return gc_handle; + }, + mono_wasm_new: function (core_name, args, is_exception) { + BINDING.bindings_lazy_init (); + + var js_name = BINDING.conv_string (core_name); + + if (!js_name) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Core object '" + js_name + "' not found."); + } + + var coreObj = BINDING.mono_wasm_get_global()[js_name]; + + if (coreObj === null || typeof coreObj === "undefined") { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("JavaScript host object '" + js_name + "' not found."); + } + + var js_args = BINDING.mono_array_to_js_array(args); + + try { + + // This is all experimental !!!!!! + var allocator = function(constructor, js_args) { + // Not sure if we should be checking for anything here + var argsList = new Array(); + argsList[0] = constructor; + if (js_args) + argsList = argsList.concat(js_args); + var obj = new (constructor.bind.apply(constructor, argsList )); + return obj; + }; + + var res = allocator(coreObj, js_args); + var gc_handle = BINDING.mono_wasm_free_list.length ? BINDING.mono_wasm_free_list.pop() : BINDING.mono_wasm_ref_counter++; + BINDING.mono_wasm_object_registry[gc_handle] = res; + return BINDING.js_to_mono_obj (gc_handle + 1); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "Error allocating object."; + return BINDING.js_string_to_mono_string (res); + } + + }, + mono_wasm_new_object: function(object_handle_or_function, args, is_exception) { + BINDING.bindings_lazy_init (); + + if (!object_handle_or_function) { + return BINDING.js_to_mono_obj ({}); + } + else { + + var requireObject; + if (typeof object_handle_or_function === 'function') + requireObject = object_handle_or_function; + else + requireObject = BINDING.mono_wasm_require_handle (object_handle_or_function); + + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + object_handle_or_function + "'"); + } + + var js_args = BINDING.mono_array_to_js_array(args); + + try { + + // This is all experimental !!!!!! + var allocator = function(constructor, js_args) { + // Not sure if we should be checking for anything here + var argsList = new Array(); + argsList[0] = constructor; + if (js_args) + argsList = argsList.concat(js_args); + var obj = new (constructor.bind.apply(constructor, argsList )); + return obj; + }; + + var res = allocator(requireObject, js_args); + return BINDING.extract_mono_obj (res); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "Error allocating object."; + return BINDING.js_string_to_mono_string (res); + } + } + + }, + mono_wasm_typed_array_to_array: function(js_handle, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + return BINDING.js_typed_array_to_array(requireObject); + }, + mono_wasm_typed_array_copy_to: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var res = BINDING.typedarray_copy_to(requireObject, pinned_array, begin, end, bytes_per_element); + return BINDING.js_to_mono_obj (res) + }, + mono_wasm_typed_array_from: function(pinned_array, begin, end, bytes_per_element, type, is_exception) { + BINDING.bindings_lazy_init (); + var res = BINDING.typed_array_from(pinned_array, begin, end, bytes_per_element, type); + return BINDING.js_to_mono_obj (res) + }, + mono_wasm_typed_array_copy_from: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var res = BINDING.typedarray_copy_from(requireObject, pinned_array, begin, end, bytes_per_element); + return BINDING.js_to_mono_obj (res) + }, + + +}; + +autoAddDeps(BindingSupportLib, '$BINDING') +mergeInto(LibraryManager.library, BindingSupportLib) diff --git a/src/mono/wasm/runtime/corebindings.c b/src/mono/wasm/runtime/corebindings.c new file mode 100644 index 0000000000000..4b78715bc0b21 --- /dev/null +++ b/src/mono/wasm/runtime/corebindings.c @@ -0,0 +1,179 @@ +// 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. +#include +#include +#include +#include +#include +#include + +#include + +//JS funcs +extern MonoObject* mono_wasm_invoke_js_with_args (int js_handle, MonoString *method, MonoArray *args, int *is_exception); +extern MonoObject* mono_wasm_get_object_property (int js_handle, MonoString *propertyName, int *is_exception); +extern MonoObject* mono_wasm_get_by_index (int js_handle, int property_index, int *is_exception); +extern MonoObject* mono_wasm_set_object_property (int js_handle, MonoString *propertyName, MonoObject *value, int createIfNotExist, int hasOwnProperty, int *is_exception); +extern MonoObject* mono_wasm_set_by_index (int js_handle, int property_index, MonoObject *value, int *is_exception); +extern MonoObject* mono_wasm_get_global_object (MonoString *global_name, int *is_exception); +extern void* mono_wasm_release_handle (int js_handle, int *is_exception); +extern void* mono_wasm_release_object (int js_handle, int *is_exception); +extern MonoObject* mono_wasm_new_object (int js_handle, MonoArray *args, int *is_exception); +extern MonoObject* mono_wasm_new (MonoString *core_name, MonoArray *args, int *is_exception); +extern int mono_wasm_bind_core_object (int js_handle, int gc_handle, int *is_exception); +extern int mono_wasm_bind_host_object (int js_handle, int gc_handle, int *is_exception); +extern MonoObject* mono_wasm_typed_array_to_array (int js_handle, int *is_exception); +extern MonoObject* mono_wasm_typed_array_copy_to (int js_handle, int ptr, int begin, int end, int bytes_per_element, int *is_exception); +extern MonoObject* mono_wasm_typed_array_from (int ptr, int begin, int end, int bytes_per_element, int type, int *is_exception); +extern MonoObject* mono_wasm_typed_array_copy_from (int js_handle, int ptr, int begin, int end, int bytes_per_element, int *is_exception); + +// Compiles a JavaScript function from the function data passed. +// Note: code snippet is not a function definition. Instead it must create and return a function instance. +EM_JS(MonoObject*, compile_function, (int snippet_ptr, int len, int *is_exception), { + try { + var data = MONO.string_decoder.decode (snippet_ptr, snippet_ptr + len); + var wrapper = '(function () { ' + data + ' })'; + var funcFactory = eval(wrapper); + var func = funcFactory(); + if (typeof func !== 'function') { + throw new Error('Code must return an instance of a JavaScript function. ' + + 'Please use `return` statement to return a function.'); + } + setValue (is_exception, 0, "i32"); + return BINDING.js_to_mono_obj (func); + } + catch (e) + { + res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "unknown exception"; + return BINDING.js_to_mono_obj (res); + } +}); + +static MonoObject* +mono_wasm_compile_function (MonoString *str, int *is_exception) +{ + if (str == NULL) + return NULL; + //char *native_val = mono_string_to_utf8 (str); + mono_unichar2 *native_val = mono_string_chars (str); + int native_len = mono_string_length (str) * 2; + + MonoObject* native_res = compile_function((int)native_val, native_len, is_exception); + mono_free (native_val); + if (native_res == NULL) + return NULL; + return native_res; +} + +void core_initialize_internals () +{ + mono_add_internal_call ("Interop/Runtime::InvokeJSWithArgs", mono_wasm_invoke_js_with_args); + mono_add_internal_call ("Interop/Runtime::GetObjectProperty", mono_wasm_get_object_property); + mono_add_internal_call ("Interop/Runtime::GetByIndex", mono_wasm_get_by_index); + mono_add_internal_call ("Interop/Runtime::SetObjectProperty", mono_wasm_set_object_property); + mono_add_internal_call ("Interop/Runtime::SetByIndex", mono_wasm_set_by_index); + mono_add_internal_call ("Interop/Runtime::GetGlobalObject", mono_wasm_get_global_object); + mono_add_internal_call ("Interop/Runtime::ReleaseHandle", mono_wasm_release_handle); + mono_add_internal_call ("Interop/Runtime::ReleaseObject", mono_wasm_release_object); + mono_add_internal_call ("Interop/Runtime::NewObjectJS", mono_wasm_new_object); + mono_add_internal_call ("Interop/Runtime::BindCoreObject", mono_wasm_bind_core_object); + mono_add_internal_call ("Interop/Runtime::BindHostObject", mono_wasm_bind_host_object); + mono_add_internal_call ("Interop/Runtime::New", mono_wasm_new); + mono_add_internal_call ("Interop/Runtime::TypedArrayToArray", mono_wasm_typed_array_to_array); + mono_add_internal_call ("Interop/Runtime::TypedArrayCopyTo", mono_wasm_typed_array_copy_to); + mono_add_internal_call ("Interop/Runtime::TypedArrayFrom", mono_wasm_typed_array_from); + mono_add_internal_call ("Interop/Runtime::TypedArrayCopyFrom", mono_wasm_typed_array_copy_from); + mono_add_internal_call ("Interop/Runtime::CompileFunction", mono_wasm_compile_function); + +} + +// Int8Array | int8_t | byte or SByte (signed byte) +// Uint8Array | uint8_t | byte or Byte (unsigned byte) +// Uint8ClampedArray| uint8_t | byte or Byte (unsigned byte) +// Int16Array | int16_t | short (signed short) +// Uint16Array | uint16_t | ushort (unsigned short) +// Int32Array | int32_t | int (signed integer) +// Uint32Array | uint32_t | uint (unsigned integer) +// Float32Array | float | float +// Float64Array | double | double +// typed array marshalling +#define MARSHAL_ARRAY_BYTE 11 +#define MARSHAL_ARRAY_UBYTE 12 +#define MARSHAL_ARRAY_SHORT 13 +#define MARSHAL_ARRAY_USHORT 14 +#define MARSHAL_ARRAY_INT 15 +#define MARSHAL_ARRAY_UINT 16 +#define MARSHAL_ARRAY_FLOAT 17 +#define MARSHAL_ARRAY_DOUBLE 18 + +EMSCRIPTEN_KEEPALIVE MonoArray* +mono_wasm_typed_array_new (char *arr, int length, int size, int type) +{ + MonoClass *typeClass = mono_get_byte_class(); // default is Byte + switch (type) { + case MARSHAL_ARRAY_BYTE: + typeClass = mono_get_sbyte_class(); + break; + case MARSHAL_ARRAY_SHORT: + typeClass = mono_get_int16_class(); + break; + case MARSHAL_ARRAY_USHORT: + typeClass = mono_get_uint16_class(); + break; + case MARSHAL_ARRAY_INT: + typeClass = mono_get_int32_class(); + break; + case MARSHAL_ARRAY_UINT: + typeClass = mono_get_uint32_class(); + break; + case MARSHAL_ARRAY_FLOAT: + typeClass = mono_get_single_class(); + break; + case MARSHAL_ARRAY_DOUBLE: + typeClass = mono_get_double_class(); + break; + } + + MonoArray *buffer; + + buffer = mono_array_new (mono_get_root_domain(), typeClass, length); + memcpy(mono_array_addr_with_size(buffer, sizeof(char), 0), arr, length * size); + + return buffer; +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_unbox_enum (MonoObject *obj) +{ + if (!obj) + return 0; + + MonoType *type = mono_class_get_type (mono_object_get_class(obj)); + + void *ptr = mono_object_unbox (obj); + switch (mono_type_get_type(mono_type_get_underlying_type (type))) { + case MONO_TYPE_I1: + case MONO_TYPE_U1: + return *(unsigned char*)ptr; + case MONO_TYPE_I2: + return *(short*)ptr; + case MONO_TYPE_U2: + return *(unsigned short*)ptr; + case MONO_TYPE_I4: + return *(int*)ptr; + case MONO_TYPE_U4: + return *(unsigned int*)ptr; + // WASM doesn't support returning longs to JS + // case MONO_TYPE_I8: + // case MONO_TYPE_U8: + default: + printf ("Invalid type %d to mono_unbox_enum\n", mono_type_get_type(mono_type_get_underlying_type (type))); + return 0; + } +} + + diff --git a/src/mono/wasm/runtime/dotnet_support.js b/src/mono/wasm/runtime/dotnet_support.js new file mode 100644 index 0000000000000..e2db502123e4a --- /dev/null +++ b/src/mono/wasm/runtime/dotnet_support.js @@ -0,0 +1,96 @@ +// 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. + +var DotNetSupportLib = { + $DOTNET: { + _dotnet_get_global: function() { + function testGlobal(obj) { + obj['___dotnet_global___'] = obj; + var success = typeof ___dotnet_global___ === 'object' && obj['___dotnet_global___'] === obj; + if (!success) { + delete obj['___dotnet_global___']; + } + return success; + } + if (typeof ___dotnet_global___ === 'object') { + return ___dotnet_global___; + } + if (typeof global === 'object' && testGlobal(global)) { + ___dotnet_global___ = global; + } else if (typeof window === 'object' && testGlobal(window)) { + ___dotnet_global___ = window; + } + if (typeof ___dotnet_global___ === 'object') { + return ___dotnet_global___; + } + throw Error('unable to get DotNet global object.'); + }, + conv_string: function (mono_obj) { + return MONO.string_decoder.copy (mono_obj); + } + }, + mono_wasm_invoke_js_marshalled: function(exceptionMessage, asyncHandleLongPtr, functionName, argsJson) { + + var mono_string = DOTNET._dotnet_get_global()._mono_string_cached + || (DOTNET._dotnet_get_global()._mono_string_cached = Module.cwrap('mono_wasm_string_from_js', 'number', ['string'])); + + try { + // Passing a .NET long into JS via Emscripten is tricky. The method here is to pass + // as pointer to the long, then combine two reads from the HEAPU32 array. + // Even though JS numbers can't represent the full range of a .NET long, it's OK + // because we'll never exceed Number.MAX_SAFE_INTEGER (2^53 - 1) in this case. + //var u32Index = $1 >> 2; + var u32Index = asyncHandleLongPtr >> 2; + var asyncHandleJsNumber = Module.HEAPU32[u32Index + 1]*4294967296 + Module.HEAPU32[u32Index]; + + // var funcNameJsString = UTF8ToString (functionName); + // var argsJsonJsString = argsJson && UTF8ToString (argsJson); + var funcNameJsString = DOTNET.conv_string(functionName); + var argsJsonJsString = argsJson && DOTNET.conv_string (argsJson); + + var dotNetExports = DOTNET._dotnet_get_global().DotNet; + if (!dotNetExports) { + throw new Error('The Microsoft.JSInterop.js library is not loaded.'); + } + + if (asyncHandleJsNumber) { + dotNetExports.jsCallDispatcher.beginInvokeJSFromDotNet(asyncHandleJsNumber, funcNameJsString, argsJsonJsString); + return 0; + } else { + var resultJson = dotNetExports.jsCallDispatcher.invokeJSFromDotNet(funcNameJsString, argsJsonJsString); + return resultJson === null ? 0 : mono_string(resultJson); + } + } catch (ex) { + var exceptionJsString = ex.message + '\n' + ex.stack; + var exceptionSystemString = mono_string(exceptionJsString); + setValue (exceptionMessage, exceptionSystemString, 'i32'); // *exceptionMessage = exceptionSystemString; + return 0; + } + }, + mono_wasm_invoke_js_unmarshalled: function(exceptionMessage, funcName, arg0, arg1, arg2) { + try { + // Get the function you're trying to invoke + var funcNameJsString = DOTNET.conv_string(funcName); + var dotNetExports = DOTNET._dotnet_get_global().DotNet; + if (!dotNetExports) { + throw new Error('The Microsoft.JSInterop.js library is not loaded.'); + } + var funcInstance = dotNetExports.jsCallDispatcher.findJSFunction(funcNameJsString); + + return funcInstance.call(null, arg0, arg1, arg2); + } catch (ex) { + var exceptionJsString = ex.message + '\n' + ex.stack; + var mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']); // TODO: Cache + var exceptionSystemString = mono_string(exceptionJsString); + setValue (exceptionMessage, exceptionSystemString, 'i32'); // *exceptionMessage = exceptionSystemString; + return 0; + } + } + + +}; + +autoAddDeps(DotNetSupportLib, '$DOTNET') +mergeInto(LibraryManager.library, DotNetSupportLib) + diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c new file mode 100644 index 0000000000000..c55ecba5a4c87 --- /dev/null +++ b/src/mono/wasm/runtime/driver.c @@ -0,0 +1,759 @@ +// 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. +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pinvoke-table.h" + +#ifdef CORE_BINDINGS +void core_initialize_internals (); +#endif + +// Blazor specific custom routines - see dotnet_support.js for backing code +extern void* mono_wasm_invoke_js_marshalled (MonoString **exceptionMessage, void *asyncHandleLongPtr, MonoString *funcName, MonoString *argsJson); +extern void* mono_wasm_invoke_js_unmarshalled (MonoString **exceptionMessage, MonoString *funcName, void* arg0, void* arg1, void* arg2); + +void mono_wasm_enable_debugging (int); + +void mono_ee_interp_init (const char *opts); +void mono_marshal_ilgen_init (void); +void mono_method_builder_ilgen_init (void); +void mono_sgen_mono_ilgen_init (void); +void mono_icall_table_init (void); +void mono_aot_register_module (void **aot_info); +char *monoeg_g_getenv(const char *variable); +int monoeg_g_setenv(const char *variable, const char *value, int overwrite); +void mono_free (void*); +int32_t mini_parse_debug_option (const char *option); + +static MonoClass* datetime_class; +static MonoClass* datetimeoffset_class; +static MonoClass* uri_class; + +int mono_wasm_enable_gc; + +/* Not part of public headers */ +#define MONO_ICALL_TABLE_CALLBACKS_VERSION 2 + +typedef struct { + int version; + void* (*lookup) (MonoMethod *method, char *classname, char *methodname, char *sigstart, int32_t *uses_handles); + const char* (*lookup_icall_symbol) (void* func); +} MonoIcallTableCallbacks; + +void +mono_install_icall_table_callbacks (const MonoIcallTableCallbacks *cb); + +int mono_regression_test_step (int verbose_level, char *image, char *method_name); +void mono_trace_init (void); + +#define g_new(type, size) ((type *) malloc (sizeof (type) * (size))) +#define g_new0(type, size) ((type *) calloc (sizeof (type), (size))) + +static MonoDomain *root_domain; + +static MonoString* +mono_wasm_invoke_js (MonoString *str, int *is_exception) +{ + if (str == NULL) + return NULL; + + mono_unichar2 *native_val = mono_string_chars (str); + int native_len = mono_string_length (str) * 2; + + mono_unichar2 *native_res = (mono_unichar2*)EM_ASM_INT ({ + var str = MONO.string_decoder.decode ($0, $0 + $1); + try { + var res = eval (str); + if (res === null || res == undefined) + return 0; + res = res.toString (); + setValue ($2, 0, "i32"); + } catch (e) { + res = e.toString (); + setValue ($2, 1, "i32"); + if (res === null || res === undefined) + res = "unknown exception"; + } + var buff = Module._malloc((res.length + 1) * 2); + stringToUTF16 (res, buff, (res.length + 1) * 2); + return buff; + }, (int)native_val, native_len, is_exception); + + if (native_res == NULL) + return NULL; + + MonoString *res = mono_string_from_utf16 (native_res); + free (native_res); + return res; +} + +static void +wasm_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data) +{ + if (fatal) { + EM_ASM( + var err = new Error(); + console.log ("Stacktrace: \n"); + console.log (err.stack); + ); + + fprintf (stderr, "%s\n", message); + fflush (stderr); + + abort (); + } else { + fprintf (stdout, "L: %s\n", message); + } +} + +#ifdef DRIVER_GEN +#include "driver-gen.c" +#endif + +typedef struct WasmAssembly_ WasmAssembly; + +struct WasmAssembly_ { + MonoBundledAssembly assembly; + WasmAssembly *next; +}; + +static WasmAssembly *assemblies; +static int assembly_count; + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_add_assembly (const char *name, const unsigned char *data, unsigned int size) +{ + int len = strlen (name); + if (!strcasecmp (".pdb", &name [len - 4])) { + char *new_name = strdup (name); + //FIXME handle debugging assemblies with .exe extension + strcpy (&new_name [len - 3], "dll"); + mono_register_symfile_for_assembly (new_name, data, size); + return; + } + WasmAssembly *entry = g_new0 (WasmAssembly, 1); + entry->assembly.name = strdup (name); + entry->assembly.data = data; + entry->assembly.size = size; + entry->next = assemblies; + assemblies = entry; + ++assembly_count; +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_setenv (const char *name, const char *value) +{ + monoeg_g_setenv (strdup (name), strdup (value), 1); +} + +#ifdef ENABLE_NETCORE +static void *sysglobal_native_handle; +#endif + +static void* +wasm_dl_load (const char *name, int flags, char **err, void *user_data) +{ + for (int i = 0; i < sizeof (pinvoke_tables) / sizeof (void*); ++i) { + if (!strcmp (name, pinvoke_names [i])) + return pinvoke_tables [i]; + } + +#ifdef ENABLE_NETCORE + if (!strcmp (name, "System.Globalization.Native")) + return sysglobal_native_handle; +#endif + +#if WASM_SUPPORTS_DLOPEN + return dlopen(name, flags); +#endif + + return NULL; +} + +static mono_bool +wasm_dl_is_pinvoke_tables (void* handle) +{ + for (int i = 0; i < sizeof (pinvoke_tables) / sizeof (void*); ++i) { + if (pinvoke_tables [i] == handle) { + return 1; + } + } + return 0; +} + +static void* +wasm_dl_symbol (void *handle, const char *name, char **err, void *user_data) +{ +#ifdef ENABLE_NETCORE + if (handle == sysglobal_native_handle) + assert (0); +#endif + +#if WASM_SUPPORTS_DLOPEN + if (!wasm_dl_is_pinvoke_tables (handle)) { + return dlsym (handle, name); + } +#endif + + PinvokeImport *table = (PinvokeImport*)handle; + for (int i = 0; table [i].name; ++i) { + if (!strcmp (table [i].name, name)) + return table [i].func; + } + return NULL; +} + +#ifdef ENABLE_NETCORE +/* Missing System.Native symbols */ +int SystemNative_CloseNetworkChangeListenerSocket (int a) { return 0; } +int SystemNative_CreateNetworkChangeListenerSocket (int a) { return 0; } +void SystemNative_ReadEvents (int a,int b) {} +int SystemNative_SchedGetAffinity (int a,int b) { return 0; } +int SystemNative_SchedSetAffinity (int a,int b) { return 0; } +#endif + +#if !defined(ENABLE_AOT) || defined(EE_MODE_LLVMONLY_INTERP) +#define NEED_INTERP 1 +#ifndef LINK_ICALLS +// FIXME: llvm+interp mode needs this to call icalls +#define NEED_NORMAL_ICALL_TABLES 1 +#endif +#endif + +#ifdef LINK_ICALLS + +#include "icall-table.h" + +static int +compare_int (const void *k1, const void *k2) +{ + return *(int*)k1 - *(int*)k2; +} + +static void* +icall_table_lookup (MonoMethod *method, char *classname, char *methodname, char *sigstart, int32_t *uses_handles) +{ + uint32_t token = mono_method_get_token (method); + assert (token); + assert ((token & MONO_TOKEN_METHOD_DEF) == MONO_TOKEN_METHOD_DEF); + uint32_t token_idx = token - MONO_TOKEN_METHOD_DEF; + + int *indexes = NULL; + int indexes_size = 0; + uint8_t *handles = NULL; + void **funcs = NULL; + + *uses_handles = 0; + + const char *image_name = mono_image_get_name (mono_class_get_image (mono_method_get_class (method))); + +#ifdef ICALL_TABLE_mscorlib + if (!strcmp (image_name, "mscorlib") || !strcmp (image_name, "System.Private.CoreLib")) { + indexes = mscorlib_icall_indexes; + indexes_size = sizeof (mscorlib_icall_indexes) / 4; + handles = mscorlib_icall_handles; + funcs = mscorlib_icall_funcs; + assert (sizeof (mscorlib_icall_indexes [0]) == 4); + } +#ifdef ICALL_TABLE_System + if (!strcmp (image_name, "System")) { + indexes = System_icall_indexes; + indexes_size = sizeof (System_icall_indexes) / 4; + handles = System_icall_handles; + funcs = System_icall_funcs; + } +#endif + assert (indexes); + + void *p = bsearch (&token_idx, indexes, indexes_size, 4, compare_int); + if (!p) { + return NULL; + printf ("wasm: Unable to lookup icall: %s\n", mono_method_get_name (method)); + exit (1); + } + + uint32_t idx = (int*)p - indexes; + *uses_handles = handles [idx]; + + //printf ("ICALL: %s %x %d %d\n", methodname, token, idx, (int)(funcs [idx])); + + return funcs [idx]; +#endif +} + +static const char* +icall_table_lookup_symbol (void *func) +{ + assert (0); + return NULL; +} + +#endif + +void mono_initialize_internals () +{ + mono_add_internal_call ("WebAssembly.Runtime::InvokeJS", mono_wasm_invoke_js); + // TODO: what happens when two types in different assemblies have the same FQN? + + // Blazor specific custom routines - see dotnet_support.js for backing code + mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSMarshalled", mono_wasm_invoke_js_marshalled); + mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSUnmarshalled", mono_wasm_invoke_js_unmarshalled); + +#ifdef CORE_BINDINGS + core_initialize_internals(); +#endif + +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_load_runtime (const char *managed_path, int enable_debugging) +{ + const char *interp_opts = ""; + + monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 0); + monoeg_g_setenv ("MONO_LOG_MASK", "gc", 0); +#ifdef ENABLE_NETCORE + monoeg_g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", 0); +#endif + + mini_parse_debug_option ("top-runtime-invoke-unhandled"); + + mono_dl_fallback_register (wasm_dl_load, wasm_dl_symbol, NULL, NULL); + +#ifdef ENABLE_AOT + // Defined in driver-gen.c + register_aot_modules (); +#ifdef EE_MODE_LLVMONLY_INTERP + mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY_INTERP); +#else + mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY); +#endif +#else + mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_LLVMONLY); + if (enable_debugging) { + // Disable optimizations which interfere with debugging + interp_opts = "-all"; + mono_wasm_enable_debugging (enable_debugging); + } +#endif + +#ifdef LINK_ICALLS + /* Link in our own linked icall table */ + static const MonoIcallTableCallbacks mono_icall_table_callbacks = + { + MONO_ICALL_TABLE_CALLBACKS_VERSION, + icall_table_lookup, + icall_table_lookup_symbol + }; + mono_install_icall_table_callbacks (&mono_icall_table_callbacks); +#endif + +#ifdef NEED_NORMAL_ICALL_TABLES + mono_icall_table_init (); +#endif +#ifdef NEED_INTERP + mono_ee_interp_init (interp_opts); + mono_marshal_ilgen_init (); + mono_method_builder_ilgen_init (); + mono_sgen_mono_ilgen_init (); +#endif + + if (assembly_count) { + MonoBundledAssembly **bundle_array = g_new0 (MonoBundledAssembly*, assembly_count + 1); + WasmAssembly *cur = assemblies; + int i = 0; + while (cur) { + bundle_array [i] = &cur->assembly; + cur = cur->next; + ++i; + } + mono_register_bundled_assemblies ((const MonoBundledAssembly **)bundle_array); + } + + mono_trace_init (); + mono_trace_set_log_handler (wasm_logger, NULL); + root_domain = mono_jit_init_version ("mono", "v4.0.30319"); + + mono_initialize_internals(); + + mono_thread_set_main (mono_thread_current ()); +} + +EMSCRIPTEN_KEEPALIVE MonoAssembly* +mono_wasm_assembly_load (const char *name) +{ + MonoImageOpenStatus status; + MonoAssemblyName* aname = mono_assembly_name_new (name); + if (!name) + return NULL; + + MonoAssembly *res = mono_assembly_load (aname, NULL, &status); + mono_assembly_name_free (aname); + + return res; +} + +EMSCRIPTEN_KEEPALIVE MonoClass* +mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name) +{ + return mono_class_from_name (mono_assembly_get_image (assembly), namespace, name); +} + +EMSCRIPTEN_KEEPALIVE MonoMethod* +mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments) +{ + return mono_class_get_method_from_name (klass, name, arguments); +} + +EMSCRIPTEN_KEEPALIVE MonoObject* +mono_wasm_invoke_method (MonoMethod *method, MonoObject *this_arg, void *params[], MonoObject **out_exc) +{ + MonoObject *exc = NULL; + MonoObject *res; + + if (out_exc) + *out_exc = NULL; + res = mono_runtime_invoke (method, this_arg, params, &exc); + if (exc) { + if (out_exc) + *out_exc = exc; + + MonoObject *exc2 = NULL; + res = (MonoObject*)mono_object_to_string (exc, &exc2); + if (exc2) + res = (MonoObject*) mono_string_new (root_domain, "Exception Double Fault"); + return res; + } + + MonoMethodSignature *sig = mono_method_signature (method); + MonoType *type = mono_signature_get_return_type (sig); + // If the method return type is void return null + // This gets around a memory access crash when the result return a value when + // a void method is invoked. + if (mono_type_get_type (type) == MONO_TYPE_VOID) + return NULL; + + return res; +} + +EMSCRIPTEN_KEEPALIVE MonoMethod* +mono_wasm_assembly_get_entry_point (MonoAssembly *assembly) +{ + MonoImage *image; + MonoMethod *method; + + image = mono_assembly_get_image (assembly); + uint32_t entry = mono_image_get_entry_point (image); + if (!entry) + return NULL; + + return mono_get_method (image, entry, NULL); +} + +EMSCRIPTEN_KEEPALIVE char * +mono_wasm_string_get_utf8 (MonoString *str) +{ + return mono_string_to_utf8 (str); //XXX JS is responsible for freeing this +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_string_convert (MonoString *str) +{ + if (str == NULL) + return; + + mono_unichar2 *native_val = mono_string_chars (str); + int native_len = mono_string_length (str) * 2; + + EM_ASM ({ + MONO.string_decoder.decode($0, $0 + $1, true); + }, (int)native_val, native_len); +} + +EMSCRIPTEN_KEEPALIVE MonoString * +mono_wasm_string_from_js (const char *str) +{ + if (str) + return mono_string_new (root_domain, str); + else + return NULL; +} + +static int +class_is_task (MonoClass *klass) +{ + if (!strcmp ("System.Threading.Tasks", mono_class_get_namespace (klass)) && + (!strcmp ("Task", mono_class_get_name (klass)) || !strcmp ("Task`1", mono_class_get_name (klass)))) + return 1; + + return 0; +} + +MonoClass* mono_get_uri_class(MonoException** exc) +{ + MonoAssembly* assembly = mono_wasm_assembly_load ("System"); + if (!assembly) + return NULL; + MonoClass* klass = mono_wasm_assembly_find_class(assembly, "System", "Uri"); + return klass; +} + +#define MARSHAL_TYPE_INT 1 +#define MARSHAL_TYPE_FP 2 +#define MARSHAL_TYPE_STRING 3 +#define MARSHAL_TYPE_VT 4 +#define MARSHAL_TYPE_DELEGATE 5 +#define MARSHAL_TYPE_TASK 6 +#define MARSHAL_TYPE_OBJECT 7 +#define MARSHAL_TYPE_BOOL 8 +#define MARSHAL_TYPE_ENUM 9 +#define MARSHAL_TYPE_DATE 20 +#define MARSHAL_TYPE_DATEOFFSET 21 +#define MARSHAL_TYPE_URI 22 + +// typed array marshalling +#define MARSHAL_ARRAY_BYTE 11 +#define MARSHAL_ARRAY_UBYTE 12 +#define MARSHAL_ARRAY_SHORT 13 +#define MARSHAL_ARRAY_USHORT 14 +#define MARSHAL_ARRAY_INT 15 +#define MARSHAL_ARRAY_UINT 16 +#define MARSHAL_ARRAY_FLOAT 17 +#define MARSHAL_ARRAY_DOUBLE 18 + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_get_obj_type (MonoObject *obj) +{ + if (!obj) + return 0; + + if (!datetime_class) + datetime_class = mono_class_from_name (mono_get_corlib(), "System", "DateTime"); + if (!datetimeoffset_class) + datetimeoffset_class = mono_class_from_name (mono_get_corlib(), "System", "DateTimeOffset"); + if (!uri_class) { + MonoException** exc = NULL; + uri_class = mono_get_uri_class(exc); + } + + MonoClass *klass = mono_object_get_class (obj); + MonoType *type = mono_class_get_type (klass); + + switch (mono_type_get_type (type)) { + // case MONO_TYPE_CHAR: prob should be done not as a number? + case MONO_TYPE_BOOLEAN: + return MARSHAL_TYPE_BOOL; + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_I: // IntPtr + return MARSHAL_TYPE_INT; + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return MARSHAL_TYPE_FP; + case MONO_TYPE_STRING: + return MARSHAL_TYPE_STRING; + case MONO_TYPE_SZARRAY: { // simple zero based one-dim-array + MonoClass *eklass = mono_class_get_element_class(klass); + MonoType *etype = mono_class_get_type (eklass); + + switch (mono_type_get_type (etype)) { + case MONO_TYPE_U1: + return MARSHAL_ARRAY_UBYTE; + case MONO_TYPE_I1: + return MARSHAL_ARRAY_BYTE; + case MONO_TYPE_U2: + return MARSHAL_ARRAY_USHORT; + case MONO_TYPE_I2: + return MARSHAL_ARRAY_SHORT; + case MONO_TYPE_U4: + return MARSHAL_ARRAY_UINT; + case MONO_TYPE_I4: + return MARSHAL_ARRAY_INT; + case MONO_TYPE_R4: + return MARSHAL_ARRAY_FLOAT; + case MONO_TYPE_R8: + return MARSHAL_ARRAY_DOUBLE; + default: + return MARSHAL_TYPE_OBJECT; + } + } + default: + if (klass == datetime_class) + return MARSHAL_TYPE_DATE; + if (klass == datetimeoffset_class) + return MARSHAL_TYPE_DATEOFFSET; + if (uri_class && mono_class_is_assignable_from(uri_class, klass)) + return MARSHAL_TYPE_URI; + if (mono_class_is_enum (klass)) + return MARSHAL_TYPE_ENUM; + if (!mono_type_is_reference (type)) //vt + return MARSHAL_TYPE_VT; + if (mono_class_is_delegate (klass)) + return MARSHAL_TYPE_DELEGATE; + if (class_is_task(klass)) + return MARSHAL_TYPE_TASK; + + return MARSHAL_TYPE_OBJECT; + } +} + +EMSCRIPTEN_KEEPALIVE int +mono_unbox_int (MonoObject *obj) +{ + if (!obj) + return 0; + MonoType *type = mono_class_get_type (mono_object_get_class(obj)); + + void *ptr = mono_object_unbox (obj); + switch (mono_type_get_type (type)) { + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: + return *(signed char*)ptr; + case MONO_TYPE_U1: + return *(unsigned char*)ptr; + case MONO_TYPE_I2: + return *(short*)ptr; + case MONO_TYPE_U2: + return *(unsigned short*)ptr; + case MONO_TYPE_I4: + case MONO_TYPE_I: + return *(int*)ptr; + case MONO_TYPE_U4: + return *(unsigned int*)ptr; + // WASM doesn't support returning longs to JS + // case MONO_TYPE_I8: + // case MONO_TYPE_U8: + default: + printf ("Invalid type %d to mono_unbox_int\n", mono_type_get_type (type)); + return 0; + } +} + +EMSCRIPTEN_KEEPALIVE double +mono_wasm_unbox_float (MonoObject *obj) +{ + if (!obj) + return 0; + MonoType *type = mono_class_get_type (mono_object_get_class(obj)); + + void *ptr = mono_object_unbox (obj); + switch (mono_type_get_type (type)) { + case MONO_TYPE_R4: + return *(float*)ptr; + case MONO_TYPE_R8: + return *(double*)ptr; + default: + printf ("Invalid type %d to mono_wasm_unbox_float\n", mono_type_get_type (type)); + return 0; + } +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_array_length (MonoArray *array) +{ + return mono_array_length (array); +} + +EMSCRIPTEN_KEEPALIVE MonoObject* +mono_wasm_array_get (MonoArray *array, int idx) +{ + return mono_array_get (array, MonoObject*, idx); +} + +EMSCRIPTEN_KEEPALIVE MonoArray* +mono_wasm_obj_array_new (int size) +{ + return mono_array_new (root_domain, mono_get_object_class (), size); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_obj_array_set (MonoArray *array, int idx, MonoObject *obj) +{ + mono_array_setref (array, idx, obj); +} + +EMSCRIPTEN_KEEPALIVE MonoArray* +mono_wasm_string_array_new (int size) +{ + return mono_array_new (root_domain, mono_get_string_class (), size); +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_exec_regression (int verbose_level, char *image) +{ + return mono_regression_test_step (verbose_level, image, NULL) ? 0 : 1; +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_exit (int exit_code) +{ + exit (exit_code); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_set_main_args (int argc, char* argv[]) +{ + mono_runtime_set_main_args (argc, argv); +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_strdup (const char *s) +{ + return (int)strdup (s); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_parse_runtime_options (int argc, char* argv[]) +{ + mono_jit_parse_options (argc, argv); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_enable_on_demand_gc (void) +{ + mono_wasm_enable_gc = 1; +} + +// Returns the local timezone default is UTC. +EM_JS(size_t, mono_wasm_timezone_get_local_name, (), +{ + var res = "UTC"; + try { + res = Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch(e) {} + + var buff = Module._malloc((res.length + 1) * 2); + stringToUTF16 (res, buff, (res.length + 1) * 2); + return buff; +}) + +void +mono_timezone_get_local_name (MonoString **result) +{ + // WASM returns back an int pointer to a string UTF16 buffer. + // We then cast to `mono_unichar2*`. Returning `mono_unichar2*` from the JavaScript call will + // result in cast warnings from the compiler. + mono_unichar2 *tzd_local_name = (mono_unichar2*)mono_wasm_timezone_get_local_name (); + *result = mono_string_from_utf16 (tzd_local_name); + free (tzd_local_name); +} diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js new file mode 100644 index 0000000000000..61e6234949d50 --- /dev/null +++ b/src/mono/wasm/runtime/library_mono.js @@ -0,0 +1,1000 @@ +// 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. + +var MonoSupportLib = { + $MONO__postset: 'MONO.export_functions (Module);', + $MONO: { + pump_count: 0, + timeout_queue: [], + _vt_stack: [], + mono_wasm_runtime_is_ready : false, + mono_wasm_ignore_pdb_load_errors: true, + pump_message: function () { + if (!this.mono_background_exec) + this.mono_background_exec = Module.cwrap ("mono_background_exec", null); + while (MONO.timeout_queue.length > 0) { + --MONO.pump_count; + MONO.timeout_queue.shift()(); + } + while (MONO.pump_count > 0) { + --MONO.pump_count; + this.mono_background_exec (); + } + }, + + export_functions: function (module) { + module ["pump_message"] = MONO.pump_message; + module ["mono_load_runtime_and_bcl"] = MONO.mono_load_runtime_and_bcl; + }, + + mono_text_decoder: undefined, + string_decoder: { + copy: function (mono_string) { + if (mono_string == 0) + return null; + + if (!this.mono_wasm_string_convert) + this.mono_wasm_string_convert = Module.cwrap ("mono_wasm_string_convert", null, ['number']); + + this.mono_wasm_string_convert (mono_string); + var result = this.result; + this.result = undefined; + return result; + }, + decode: function (start, end, save) { + if (!MONO.mono_text_decoder) { + MONO.mono_text_decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; + } + + var str = ""; + if (MONO.mono_text_decoder) { + // When threading is enabled, TextDecoder does not accept a view of a + // SharedArrayBuffer, we must make a copy of the array first. + var subArray = typeof SharedArrayBuffer !== 'undefined' && Module.HEAPU8.buffer instanceof SharedArrayBuffer + ? Module.HEAPU8.slice(start, end) + : Module.HEAPU8.subarray(start, end); + + str = MONO.mono_text_decoder.decode(subArray); + } else { + for (var i = 0; i < end - start; i+=2) { + var char = Module.getValue (start + i, 'i16'); + str += String.fromCharCode (char); + } + } + if (save) + this.result = str; + + return str; + }, + }, + + mono_wasm_get_call_stack: function() { + if (!this.mono_wasm_current_bp_id) + this.mono_wasm_current_bp_id = Module.cwrap ("mono_wasm_current_bp_id", 'number'); + if (!this.mono_wasm_enum_frames) + this.mono_wasm_enum_frames = Module.cwrap ("mono_wasm_enum_frames", null); + + var bp_id = this.mono_wasm_current_bp_id (); + this.active_frames = []; + this.mono_wasm_enum_frames (); + + var the_frames = this.active_frames; + this.active_frames = []; + return { + "breakpoint_id": bp_id, + "frames": the_frames, + }; + }, + + _fixup_name_value_objects: function (var_list) { + var out_list = []; + + var _fixup_value = function (value) { + if (value != null && value != undefined) { + var descr = value.description; + if (descr == null || descr == undefined) + value.description = '' + value.value; + } + return value; + }; + + var i = 0; + while (i < var_list.length) { + var o = var_list [i]; + var name = o.name; + if (name == null || name == undefined) { + i ++; + o.value = _fixup_value(o.value); + out_list.push (o); + continue; + } + + if (i + 1 < var_list.length) + o.value = _fixup_value(var_list[i + 1].value); + + out_list.push (o); + i += 2; + } + + return out_list; + }, + + _filter_automatic_properties: function (props) { + var names_found = {}; + var final_var_list = []; + + for (var i in props) { + var p = props [i]; + if (p.name in names_found) + continue; + + if (p.name.endsWith ("k__BackingField")) + p.name = p.name.replace ("k__BackingField", "") + .replace ('<', '') + .replace ('>', ''); + + names_found [p.name] = p.name; + final_var_list.push (p); + } + + return final_var_list; + }, + + mono_wasm_get_variables: function(scope, var_list) { + if (!this.mono_wasm_get_var_info) + this.mono_wasm_get_var_info = Module.cwrap ("mono_wasm_get_var_info", null, [ 'number', 'number', 'number']); + + this.var_info = []; + var numBytes = var_list.length * Int32Array.BYTES_PER_ELEMENT; + var ptr = Module._malloc(numBytes); + var heapBytes = new Int32Array(Module.HEAP32.buffer, ptr, numBytes); + for (let i=0; i') > 0) + res [i].name = name.substring (1, name.indexOf ('>')); + } + + if (this._async_method_objectId != 0) { + for (let i in res) { + if (res [i].value.isValueType != undefined && res [i].value.isValueType) + res [i].value.objectId = `dotnet:valuetype:${this._async_method_objectId}:${res [i].fieldOffset}`; + } + } + + this._post_process_details(res); + this.var_info = [] + + return res; + }, + + mono_wasm_get_object_properties: function(objId, expandValueTypes) { + if (!this.mono_wasm_get_object_properties_info) + this.mono_wasm_get_object_properties_info = Module.cwrap ("mono_wasm_get_object_properties", null, [ 'number', 'bool' ]); + + this.var_info = []; + this.mono_wasm_get_object_properties_info (objId, expandValueTypes); + + var res = MONO._filter_automatic_properties (MONO._fixup_name_value_objects (this.var_info)); + for (var i = 0; i < res.length; i++) { + if (res [i].value.isValueType != undefined && res [i].value.isValueType) + res [i].value.objectId = `dotnet:valuetype:${objId}:${res [i].fieldOffset}`; + } + + this.var_info = []; + + return res; + }, + + mono_wasm_get_array_values: function(objId) { + if (!this.mono_wasm_get_array_values_info) + this.mono_wasm_get_array_values_info = Module.cwrap ("mono_wasm_get_array_values", null, [ 'number' ]); + + this.var_info = []; + this.mono_wasm_get_array_values_info (objId); + + var res = MONO._fixup_name_value_objects (this.var_info); + for (var i = 0; i < res.length; i++) { + if (res [i].value.isValueType != undefined && res [i].value.isValueType) + res [i].value.objectId = `dotnet:array:${objId}:${i}`; + } + + this.var_info = []; + + return res; + }, + + mono_wasm_get_array_value_expanded: function(objId, idx) { + if (!this.mono_wasm_get_array_value_expanded_info) + this.mono_wasm_get_array_value_expanded_info = Module.cwrap ("mono_wasm_get_array_value_expanded", null, [ 'number', 'number' ]); + + this.var_info = []; + this.mono_wasm_get_array_value_expanded_info (objId, idx); + + var res = MONO._fixup_name_value_objects (this.var_info); + // length should be exactly one! + if (res [0].value.isValueType != undefined && res [0].value.isValueType) + res [0].value.objectId = `dotnet:array:${objId}:${idx}`; + + this.var_info = []; + + return res; + }, + + _post_process_details: function (details) { + if (details == undefined) + return {}; + + if (details.length > 0) + this._extract_and_cache_value_types(details); + + return details; + }, + + _next_value_type_id: function () { + return ++this._next_value_type_id_var; + }, + + _extract_and_cache_value_types: function (var_list) { + if (var_list == undefined || !Array.isArray (var_list) || var_list.length == 0) + return var_list; + + for (let i in var_list) { + var value = var_list [i].value; + if (value == undefined || value.type != "object") + continue; + + if (value.isValueType != true || value.expanded != true) // undefined would also give us false + continue; + + var objectId = value.objectId; + if (objectId == undefined) + objectId = `dotnet:valuetype:${this._next_value_type_id ()}`; + value.objectId = objectId; + + this._extract_and_cache_value_types (value.members); + + this._value_types_cache [objectId] = value.members; + delete value.members; + } + + return var_list; + }, + + _get_details_for_value_type: function (objectId, fetchDetailsFn) { + if (objectId in this._value_types_cache) + return this._value_types_cache[objectId]; + + this._post_process_details (fetchDetailsFn()); + if (objectId in this._value_types_cache) + return this._value_types_cache[objectId]; + + // return error + throw new Error (`Could not get details for ${objectId}`); + }, + + _is_object_id_array: function (objectId) { + // Keep this in sync with `_get_array_details` + return (objectId.startsWith ('dotnet:array:') && objectId.split (':').length == 3); + }, + + _get_array_details: function (objectId, objectIdParts) { + // Keep this in sync with `_is_object_id_array` + switch (objectIdParts.length) { + case 3: + return this._post_process_details (this.mono_wasm_get_array_values(objectIdParts[2])); + + case 4: + var arrayObjectId = objectIdParts[2]; + var arrayIdx = objectIdParts[3]; + return this._get_details_for_value_type( + objectId, () => this.mono_wasm_get_array_value_expanded(arrayObjectId, arrayIdx)); + + default: + throw new Error (`object id format not supported : ${objectId}`); + } + }, + + mono_wasm_get_details: function (objectId, args) { + var parts = objectId.split(":"); + if (parts[0] != "dotnet") + throw new Error ("Can't handle non-dotnet object ids. ObjectId: " + objectId); + + switch (parts[1]) { + case "object": + if (parts.length != 3) + throw new Error(`exception this time: Invalid object id format: ${objectId}`); + + return this._post_process_details(this.mono_wasm_get_object_properties(parts[2], false)); + + case "array": + return this._get_array_details(objectId, parts); + + case "valuetype": + if (parts.length != 3 && parts.length != 4) { + // dotnet:valuetype:vtid + // dotnet:valuetype:containerObjectId:vtId + throw new Error(`Invalid object id format: ${objectId}`); + } + + var containerObjectId = parts[2]; + return this._get_details_for_value_type(objectId, () => this.mono_wasm_get_object_properties(containerObjectId, true)); + + case "cfo_res": { + if (!(objectId in this._call_function_res_cache)) + throw new Error(`Could not find any object with id ${objectId}`); + + var real_obj = this._call_function_res_cache [objectId]; + if (args.accessorPropertiesOnly) { + // var val_accessors = JSON.stringify ([ + // { + // name: "__proto__", + // get: { type: "function", className: "Function", description: "function get __proto__ () {}", objectId: "dotnet:cfo_res:9999" }, + // set: { type: "function", className: "Function", description: "function set __proto__ () {}", objectId: "dotnet:cfo_res:8888" }, + // isOwn: false + // }], undefined, 4); + return { __value_as_json_string__: "[]" }; + } + + // behaving as if (args.ownProperties == true) + var descriptors = Object.getOwnPropertyDescriptors (real_obj); + var own_properties = []; + Object.keys (descriptors).forEach (k => { + var new_obj; + var prop_desc = descriptors [k]; + if (typeof prop_desc.value == "object") { + // convert `{value: { type='object', ... }}` + // to `{ name: 'foo', value: { type='object', ... }} + new_obj = Object.assign ({ name: k}, prop_desc); + } else { + // This is needed for values that were not added by us, + // thus are like { value: 5 } + // instead of { value: { type = 'number', value: 5 }} + // + // This can happen, for eg., when `length` gets added for arrays + // or `__proto__`. + new_obj = { + name: k, + // merge/add `type` and `description` to `d.value` + value: Object.assign ({ type: (typeof prop_desc.value), description: '' + prop_desc.value }, + prop_desc) + }; + } + + own_properties.push (new_obj); + }); + + return { __value_as_json_string__: JSON.stringify (own_properties) }; + } + + default: + throw new Error(`Unknown object id format: ${objectId}`); + } + }, + + _cache_call_function_res: function (obj) { + var id = `dotnet:cfo_res:${this._next_call_function_res_id++}`; + this._call_function_res_cache[id] = obj; + return id; + }, + + mono_wasm_release_object: function (objectId) { + if (objectId in this._cache_call_function_res) + delete this._cache_call_function_res[objectId]; + }, + + mono_wasm_call_function_on: function (request) { + var objId = request.objectId; + var proxy; + + if (objId in this._call_function_res_cache) { + proxy = this._call_function_res_cache [objId]; + } else if (!objId.startsWith ('dotnet:cfo_res:')) { + var details = this.mono_wasm_get_details(objId); + var target_is_array = this._is_object_id_array (objId); + proxy = target_is_array ? [] : {}; + + Object.keys(details).forEach(p => { + var prop = details[p]; + if (target_is_array) { + proxy.push(prop.value); + } else { + if (prop.name != undefined) + proxy [prop.name] = prop.value; + else // when can this happen?? + proxy[''+p] = prop.value; + } + }); + } + + var fn_args = request.arguments != undefined ? request.arguments.map(a => a.value) : []; + var fn_eval_str = `var fn = ${request.functionDeclaration}; fn.call (proxy, ...[${fn_args}]);`; + + var fn_res = eval (fn_eval_str); + if (request.returnByValue) + return fn_res; + + if (fn_res == undefined) + throw Error ('Function returned undefined result'); + + var fn_res_id = this._cache_call_function_res (fn_res); + if (Object.getPrototypeOf (fn_res) == Array.prototype) { + return { + type: "object", + subtype: "array", + className: "Array", + description: `Array(${fn_res.length})`, + objectId: fn_res_id + }; + } else { + return { type: "object", className: "Object", description: "Object", objectId: fn_res_id }; + } + }, + + mono_wasm_start_single_stepping: function (kind) { + console.log (">> mono_wasm_start_single_stepping " + kind); + if (!this.mono_wasm_setup_single_step) + this.mono_wasm_setup_single_step = Module.cwrap ("mono_wasm_setup_single_step", 'number', [ 'number']); + + this._next_value_type_id_var = 0; + this._value_types_cache = {}; + + return this.mono_wasm_setup_single_step (kind); + }, + + mono_wasm_runtime_ready: function () { + this.mono_wasm_runtime_is_ready = true; + // DO NOT REMOVE - magic debugger init function + console.debug ("mono_wasm_runtime_ready", "fe00e07a-5519-4dfe-b35a-f867dbaf2e28"); + + this._next_value_type_id_var = 0; + this._value_types_cache = {}; + + // FIXME: where should this go? + this._next_call_function_res_id = 0; + this._call_function_res_cache = {}; + }, + + mono_wasm_set_breakpoint: function (assembly, method_token, il_offset) { + if (!this.mono_wasm_set_bp) + this.mono_wasm_set_bp = Module.cwrap ('mono_wasm_set_breakpoint', 'number', ['string', 'number', 'number']); + + return this.mono_wasm_set_bp (assembly, method_token, il_offset) + }, + + mono_wasm_remove_breakpoint: function (breakpoint_id) { + if (!this.mono_wasm_del_bp) + this.mono_wasm_del_bp = Module.cwrap ('mono_wasm_remove_breakpoint', 'number', ['number']); + + return this.mono_wasm_del_bp (breakpoint_id); + }, + + // Set environment variable NAME to VALUE + // Should be called before mono_load_runtime_and_bcl () in most cases + mono_wasm_setenv: function (name, value) { + if (!this.wasm_setenv) + this.wasm_setenv = Module.cwrap ('mono_wasm_setenv', null, ['string', 'string']); + this.wasm_setenv (name, value); + }, + + mono_wasm_set_runtime_options: function (options) { + if (!this.wasm_parse_runtime_options) + this.wasm_parse_runtime_options = Module.cwrap ('mono_wasm_parse_runtime_options', null, ['number', 'number']); + var argv = Module._malloc (options.length * 4); + var wasm_strdup = Module.cwrap ('mono_wasm_strdup', 'number', ['string']); + aindex = 0; + for (var i = 0; i < options.length; ++i) { + Module.setValue (argv + (aindex * 4), wasm_strdup (options [i]), "i32"); + aindex += 1; + } + this.wasm_parse_runtime_options (options.length, argv); + }, + + // + // Initialize the AOT profiler with OPTIONS. + // Requires the AOT profiler to be linked into the app. + // options = { write_at: "", send_to: "" } + // should be in the format ::. + // write_at defaults to 'WebAssembly.Runtime::StopProfile'. + // send_to defaults to 'WebAssembly.Runtime::DumpAotProfileData'. + // DumpAotProfileData stores the data into Module.aot_profile_data. + // + mono_wasm_init_aot_profiler: function (options) { + if (options == null) + options = {} + if (!('write_at' in options)) + options.write_at = 'WebAssembly.Runtime::StopProfile'; + if (!('send_to' in options)) + options.send_to = 'WebAssembly.Runtime::DumpAotProfileData'; + var arg = "aot:write-at-method=" + options.write_at + ",send-to-method=" + options.send_to; + Module.ccall ('mono_wasm_load_profiler_aot', null, ['string'], [arg]); + }, + + // options = { write_at: "", send_to: "" } + // should be in the format ::. + // write_at defaults to 'WebAssembly.Runtime::StopProfile'. + // send_to defaults to 'WebAssembly.Runtime::DumpCoverageProfileData'. + // DumpCoverageProfileData stores the data into Module.coverage_profile_data. + mono_wasm_init_coverage_profiler: function (options) { + if (options == null) + options = {} + if (!('write_at' in options)) + options.write_at = 'WebAssembly.Runtime::StopProfile'; + if (!('send_to' in options)) + options.send_to = 'WebAssembly.Runtime::DumpCoverageProfileData'; + var arg = "coverage:write-at-method=" + options.write_at + ",send-to-method=" + options.send_to; + Module.ccall ('mono_wasm_load_profiler_coverage', null, ['string'], [arg]); + }, + + mono_load_runtime_and_bcl: function (vfs_prefix, deploy_prefix, enable_debugging, file_list, loaded_cb, fetch_file_cb) { + var pending = file_list.length; + var loaded_files = []; + var mono_wasm_add_assembly = Module.cwrap ('mono_wasm_add_assembly', null, ['string', 'number', 'number']); + + if (!fetch_file_cb) { + if (ENVIRONMENT_IS_NODE) { + var fs = require('fs'); + fetch_file_cb = function (asset) { + console.log("MONO_WASM: Loading... " + asset); + var binary = fs.readFileSync (asset); + var resolve_func2 = function(resolve, reject) { + resolve(new Uint8Array (binary)); + }; + + var resolve_func1 = function(resolve, reject) { + var response = { + ok: true, + url: asset, + arrayBuffer: function() { + return new Promise(resolve_func2); + } + }; + resolve(response); + }; + + return new Promise(resolve_func1); + }; + } else { + fetch_file_cb = function (asset) { + return fetch (asset, { credentials: 'same-origin' }); + } + } + } + + file_list.forEach (function(file_name) { + + var fetch_promise = fetch_file_cb (locateFile(deploy_prefix + "/" + file_name)); + + fetch_promise.then (function (response) { + if (!response.ok) { + // If it's a 404 on a .pdb, we don't want to block the app from starting up. + // We'll just skip that file and continue (though the 404 is logged in the console). + if (response.status === 404 && file_name.match(/\.pdb$/) && MONO.mono_wasm_ignore_pdb_load_errors) { + --pending; + throw "MONO-WASM: Skipping failed load for .pdb file: '" + file_name + "'"; + } + else { + throw "MONO_WASM: Failed to load file: '" + file_name + "'"; + } + } + else { + loaded_files.push (response.url); + return response ['arrayBuffer'] (); + } + }).then (function (blob) { + var asm = new Uint8Array (blob); + var memory = Module._malloc(asm.length); + var heapBytes = new Uint8Array(Module.HEAPU8.buffer, memory, asm.length); + heapBytes.set (asm); + mono_wasm_add_assembly (file_name, memory, asm.length); + + //console.log ("MONO_WASM: Loaded: " + file_name); + --pending; + if (pending == 0) { + MONO.loaded_files = loaded_files; + var load_runtime = Module.cwrap ('mono_wasm_load_runtime', null, ['string', 'number']); + + console.log ("MONO_WASM: Initializing mono runtime"); + if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) { + try { + load_runtime (vfs_prefix, enable_debugging); + } catch (ex) { + print ("MONO_WASM: load_runtime () failed: " + ex); + var err = new Error(); + print ("MONO_WASM: Stacktrace: \n"); + print (err.stack); + + var wasm_exit = Module.cwrap ('mono_wasm_exit', null, ['number']); + wasm_exit (1); + } + } else { + load_runtime (vfs_prefix, enable_debugging); + } + MONO.mono_wasm_runtime_ready (); + loaded_cb (); + } + }); + }); + }, + + mono_wasm_get_loaded_files: function() { + console.log(">>>mono_wasm_get_loaded_files"); + return this.loaded_files; + }, + + mono_wasm_clear_all_breakpoints: function() { + if (!this.mono_clear_bps) + this.mono_clear_bps = Module.cwrap ('mono_wasm_clear_all_breakpoints', null); + + this.mono_clear_bps (); + }, + + mono_wasm_add_null_var: function(className) + { + fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + if (!fixed_class_name) { + // Eg, when a @className is passed from js itself, like + // mono_wasm_add_null_var ("string") + fixed_class_name = className; + } + MONO.var_info.push ({value: { + type: "object", + className: fixed_class_name, + description: fixed_class_name, + subtype: "null" + }}); + }, + + _mono_wasm_add_string_var: function(var_value) { + if (var_value == 0) { + MONO.mono_wasm_add_null_var ("string"); + return; + } + + MONO.var_info.push({ + value: { + type: "string", + value: var_value, + } + }); + }, + + _mono_wasm_add_getter_var: function(className) { + fixed_class_name = MONO._mono_csharp_fixup_class_name (className); + var value = `${fixed_class_name} { get; }`; + MONO.var_info.push({ + value: { + type: "symbol", + value: value, + description: value + } + }); + }, + + _mono_wasm_add_array_var: function(className, objectId, length) { + fixed_class_name = MONO._mono_csharp_fixup_class_name(className); + if (objectId == 0) { + MONO.mono_wasm_add_null_var (fixed_class_name); + return; + } + + MONO.var_info.push({ + value: { + type: "object", + subtype: "array", + className: fixed_class_name, + description: `${fixed_class_name}(${length})`, + objectId: "dotnet:array:"+ objectId, + } + }); + }, + + mono_wasm_add_typed_value: function (type, str_value, value) { + var type_str = type; + if (typeof type != 'string') + type_str = Module.UTF8ToString (type); + if (typeof str_value != 'string') + str_value = Module.UTF8ToString (str_value); + + switch (type_str) { + case "bool": + MONO.var_info.push ({ + value: { + type: "boolean", + value: value != 0 + } + }); + break; + + case "char": + MONO.var_info.push ({ + value: { + type: "symbol", + value: `${value} '${String.fromCharCode (value)}'` + } + }); + break; + + case "number": + MONO.var_info.push ({ + value: { + type: "number", + value: value + } + }); + break; + + case "string": + MONO._mono_wasm_add_string_var (str_value); + break; + + case "getter": + MONO._mono_wasm_add_getter_var (str_value); + break; + + case "array": + MONO._mono_wasm_add_array_var (str_value, value.objectId, value.length); + break; + + case "pointer": { + MONO.var_info.push ({ + value: { + type: "symbol", + value: str_value, + description: str_value + } + }); + } + break; + + default: { + var msg = `'${str_value}' ${value}`; + + MONO.var_info.push ({ + value: { + type: "symbol", + value: msg, + description: msg + } + }); + break; + } + } + }, + + _mono_csharp_fixup_class_name: function(className) + { + // Fix up generic names like Foo`2 to Foo + // and nested class names like Foo/Bar to Foo.Bar + return className.replace(/\//g, '.').replace(/`\d+/g, ''); + }, + }, + + mono_wasm_add_typed_value: function (type, str_value, value) { + MONO.mono_wasm_add_typed_value (type, str_value, value); + }, + + mono_wasm_add_properties_var: function(name, field_offset) { + MONO.var_info.push({ + name: Module.UTF8ToString (name), + fieldOffset: field_offset + }); + }, + + mono_wasm_set_is_async_method: function(objectId) { + MONO._async_method_objectId = objectId; + }, + + mono_wasm_begin_value_type_var: function(className, toString) { + fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + var vt_obj = { + value: { + type: "object", + className: fixed_class_name, + description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)), + // objectId will be generated by MonoProxy + expanded: true, + isValueType: true, + members: [] + } + }; + if (MONO._vt_stack.length == 0) + MONO._old_var_info = MONO.var_info; + + MONO.var_info = vt_obj.value.members; + MONO._vt_stack.push (vt_obj); + }, + + mono_wasm_end_value_type_var: function() { + var top_vt_obj_popped = MONO._vt_stack.pop (); + top_vt_obj_popped.value.members = MONO._filter_automatic_properties ( + MONO._fixup_name_value_objects (top_vt_obj_popped.value.members)); + + if (MONO._vt_stack.length == 0) { + MONO.var_info = MONO._old_var_info; + MONO.var_info.push(top_vt_obj_popped); + } else { + var top_obj = MONO._vt_stack [MONO._vt_stack.length - 1]; + top_obj.value.members.push (top_vt_obj_popped); + MONO.var_info = top_obj.value.members; + } + }, + + mono_wasm_add_value_type_unexpanded_var: function (className, toString) { + fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + MONO.var_info.push({ + value: { + type: "object", + className: fixed_class_name, + description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)), + // objectId added when enumerating object's properties + expanded: false, + isValueType: true + } + }); + }, + + mono_wasm_add_enum_var: function(className, members, value) { + // FIXME: flags + // + + // group0: Monday:0 + // group1: Monday + // group2: 0 + var re = new RegExp (`[,]?([^,:]+):(${value}(?=,)|${value}$)`, 'g') + var members_str = Module.UTF8ToString (members); + + var match = re.exec(members_str); + var member_name = match == null ? ('' + value) : match [1]; + + fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + MONO.var_info.push({ + value: { + type: "object", + className: fixed_class_name, + description: member_name, + isEnum: true + } + }); + }, + + mono_wasm_add_array_item: function(position) { + MONO.var_info.push({ + name: `${position}` + }); + }, + + mono_wasm_add_obj_var: function(className, toString, objectId) { + if (objectId == 0) { + MONO.mono_wasm_add_null_var (className); + return; + } + + fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + MONO.var_info.push({ + value: { + type: "object", + className: fixed_class_name, + description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)), + objectId: "dotnet:object:"+ objectId, + } + }); + }, + + /* + * @className, and @targetName are in the following format: + * + * :[]: + */ + mono_wasm_add_func_var: function (className, targetName, objectId) { + if (objectId == 0) { + MONO.mono_wasm_add_null_var ( + MONO._mono_csharp_fixup_class_name (Module.UTF8ToString (className))); + return; + } + + function args_to_sig (args_str) { + var parts = args_str.split (":"); + // TODO: min length = 3? + parts = parts.map (a => MONO._mono_csharp_fixup_class_name (a)); + + // method name at the end + var method_name = parts.pop (); + + // ret type at the beginning + var ret_sig = parts [0]; + var args_sig = parts.splice (1).join (', '); + return `${ret_sig} ${method_name} (${args_sig})`; + } + + var tgt_sig; + if (targetName != 0) + tgt_sig = args_to_sig (Module.UTF8ToString (targetName)); + + var type_name = MONO._mono_csharp_fixup_class_name (Module.UTF8ToString (className)); + + if (objectId == -1) { + // Target property + MONO.var_info.push ({ + value: { + type: "symbol", + value: tgt_sig, + description: tgt_sig, + } + }); + } else { + MONO.var_info.push ({ + value: { + type: "object", + className: type_name, + description: tgt_sig, + objectId: "dotnet:object:" + objectId, + } + }); + } + }, + + mono_wasm_add_frame: function(il, method, assembly_name, method_full_name) { + var parts = Module.UTF8ToString (method_full_name).split (":", 2); + MONO.active_frames.push( { + il_pos: il, + method_token: method, + assembly_name: Module.UTF8ToString (assembly_name), + // Extract just the method name from `{class_name}:{method_name}` + method_name: parts [parts.length - 1] + }); + }, + + schedule_background_exec: function () { + ++MONO.pump_count; + if (ENVIRONMENT_IS_WEB) { + window.setTimeout (MONO.pump_message, 0); + } else if (ENVIRONMENT_IS_WORKER) { + self.setTimeout (MONO.pump_message, 0); + } else if (ENVIRONMENT_IS_NODE) { + global.setTimeout (MONO.pump_message, 0); + } + }, + + mono_set_timeout: function (timeout, id) { + if (!this.mono_set_timeout_exec) + this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", null, [ 'number' ]); + if (ENVIRONMENT_IS_WEB) { + window.setTimeout (function () { + this.mono_set_timeout_exec (id); + }, timeout); + } else if (ENVIRONMENT_IS_WORKER) { + self.setTimeout (function () { + this.mono_set_timeout_exec (id); + }, timeout); + } else if (ENVIRONMENT_IS_NODE) { + global.setTimeout (function () { + global.mono_set_timeout_exec (id); + }, timeout); + } else { + ++MONO.pump_count; + MONO.timeout_queue.push(function() { + this.mono_set_timeout_exec (id); + }) + } + }, + + mono_wasm_fire_bp: function () { + console.log ("mono_wasm_fire_bp"); + debugger; + } +}; + +autoAddDeps(MonoSupportLib, '$MONO') +mergeInto(LibraryManager.library, MonoSupportLib) diff --git a/src/mono/wasm/runtime/linker-preserves.xml b/src/mono/wasm/runtime/linker-preserves.xml new file mode 100644 index 0000000000000..2e46279b8793a --- /dev/null +++ b/src/mono/wasm/runtime/linker-preserves.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/mono/wasm/wasm.targets b/src/mono/wasm/wasm.targets new file mode 100644 index 0000000000000..0e088e5cb0751 --- /dev/null +++ b/src/mono/wasm/wasm.targets @@ -0,0 +1,41 @@ + + + + + + $(ArtifactsObjDir)wasm/pinvoke-table.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools-local/tasks/installer.tasks/CopyNupkgAndChangeVersion.cs b/tools-local/tasks/installer.tasks/CopyNupkgAndChangeVersion.cs deleted file mode 100644 index 35f7a42121402..0000000000000 --- a/tools-local/tasks/installer.tasks/CopyNupkgAndChangeVersion.cs +++ /dev/null @@ -1,149 +0,0 @@ -// 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 Microsoft.Build.Framework; -using Newtonsoft.Json.Linq; -using NuGet.Versioning; -using System; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Xml.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - public class CopyNupkgAndChangeVersion : BuildTask - { - [Required] - public string SourceFile { get; set; } - - [Required] - public string TargetFile { get; set; } - - [Required] - public string OriginalVersion { get; set; } - - [Required] - public string TargetVersion { get; set; } - - public string[] DependencyPackageIdsToChange { get; set; } - - public override bool Execute() - { - Directory.CreateDirectory(Path.GetDirectoryName(TargetFile)); - File.Copy(SourceFile, TargetFile, true); - - using (ZipArchive zip = ZipFile.Open(TargetFile, ZipArchiveMode.Update)) - { - RewriteNuspec(zip); - RewriteRuntimeJson(zip); - } - - return !Log.HasLoggedErrors; - } - - private void RewriteNuspec(ZipArchive zip) - { - foreach (var nuspec in zip.Entries.Where(e => e.FullName.EndsWith(".nuspec"))) - { - Rewrite(nuspec, s => - { - XDocument content = XDocument.Parse(s); - - RewriteNuspecPackageVersion(content); - RewriteNuspecDependencyVersions(content); - - return content.ToString(); - }); - } - } - - private void RewriteRuntimeJson(ZipArchive zip) - { - foreach (var runtimeJson in zip.Entries.Where(e => e.FullName == "runtime.json")) - { - Rewrite(runtimeJson, s => - { - JObject content = JObject.Parse(s); - - RewriteRuntimeJsonVersions(content); - - return content.ToString(); - }); - } - } - - private void RewriteNuspecPackageVersion(XDocument content) - { - XElement versionElement = content - .Element(CreateQualifiedName(content, "package")) - .Element(CreateQualifiedName(content, "metadata")) - .Element(CreateQualifiedName(content, "version")); - - if (versionElement.Value != OriginalVersion) - { - Log.LogError( - $"Original version is '{versionElement.Value}', " + - $"expected '{OriginalVersion}'"); - } - - versionElement.Value = TargetVersion; - } - - private void RewriteNuspecDependencyVersions(XDocument content) - { - foreach (var dependency in content - .Descendants(CreateQualifiedName(content, "dependency")) - .Where(x => - x.Attribute("version").Value == OriginalVersion && - DependencyPackageIdsToChange?.Contains(x.Attribute("id").Value) == true)) - { - dependency.Value = TargetVersion; - } - } - - private void RewriteRuntimeJsonVersions(JObject content) - { - var versionProperties = content - .Descendants() - .OfType() - .Where(p => - p.Value is JValue v && - v.Type == JTokenType.String); - - foreach (var p in versionProperties) - { - var range = VersionRange.Parse(p.Value.Value()); - - if (range.MinVersion.OriginalVersion == OriginalVersion) - { - var newRange = new VersionRange( - NuGetVersion.Parse(TargetVersion), - range.Float); - - p.Value = newRange.ToString(); - } - } - } - - private static XName CreateQualifiedName(XDocument doc, string name) - { - return doc.Root.GetDefaultNamespace().GetName(name); - } - - private static void Rewrite(ZipArchiveEntry entry, Func rewrite) - { - using (var stream = entry.Open()) - using (var reader = new StreamReader(stream)) - using (var writer = new StreamWriter(stream)) - { - var content = rewrite(reader.ReadToEnd()); - - stream.Position = 0; - stream.SetLength(0); - writer.Write(content); - } - } - } -} diff --git a/tools-local/tasks/installer.tasks/CreateFrameworkListFile.cs b/tools-local/tasks/installer.tasks/CreateFrameworkListFile.cs deleted file mode 100644 index 36a3dd59386c0..0000000000000 --- a/tools-local/tasks/installer.tasks/CreateFrameworkListFile.cs +++ /dev/null @@ -1,211 +0,0 @@ -// 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 Microsoft.Build.Framework; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - public class CreateFrameworkListFile : BuildTask - { - /// - /// Files to extract basic information from and include in the list. - /// - [Required] - public ITaskItem[] Files { get; set; } - - /// - /// A list of assembly names with classification info such as Profile. A - /// Profile="%(Profile)" attribute is included in the framework list for the matching Files - /// item if %(Profile) contains text. - /// - /// If *any* FileClassifications are passed: - /// - /// *Every* file that ends up listed in the framework list must have a matching - /// FileClassification. - /// - /// Additionally, every FileClassification must find exactly one File. - /// - /// This task fails if the conditions aren't met. This ensures the classification doesn't - /// become out of date when the list of files changes. - /// - /// %(Identity): Assembly name (including ".dll"). - /// %(Profile): List of profiles that apply, semicolon-delimited. - /// %(ReferencedByDefault): Empty (default) or "true"/"false". Indicates whether this file - /// should be referenced by default when the SDK uses this framework. - /// - public ITaskItem[] FileClassifications { get; set; } - - [Required] - public string TargetFile { get; set; } - - public string[] TargetFilePrefixes { get; set; } - - /// - /// Extra attributes to place on the root node. - /// - /// %(Identity): Attribute name. - /// %(Value): Attribute value. - /// - public ITaskItem[] RootAttributes { get; set; } - - public override bool Execute() - { - XAttribute[] rootAttributes = RootAttributes - ?.Select(item => new XAttribute(item.ItemSpec, item.GetMetadata("Value"))) - .ToArray(); - - var frameworkManifest = new XElement("FileList", rootAttributes); - - Dictionary fileClassLookup = FileClassifications - ?.ToDictionary( - item => item.ItemSpec, - item => item, - StringComparer.OrdinalIgnoreCase); - - var usedFileClasses = new HashSet(); - - foreach (var f in Files - .Where(IsTargetPathIncluded) - .Select(item => new - { - Item = item, - Filename = Path.GetFileName(item.ItemSpec), - TargetPath = item.GetMetadata("TargetPath"), - AssemblyName = FileUtilities.GetAssemblyName(item.ItemSpec), - FileVersion = FileUtilities.GetFileVersion(item.ItemSpec), - IsNative = item.GetMetadata("IsNative") == "true", - IsSymbolFile = item.GetMetadata("IsSymbolFile") == "true", - IsResourceFile = item.ItemSpec - .EndsWith(".resources.dll", StringComparison.OrdinalIgnoreCase) - }) - .Where(f => - !f.IsSymbolFile && - (f.Filename.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || f.IsNative)) - // Remove duplicate files this task is given. - .GroupBy(f => f.Item.ItemSpec) - .Select(g => g.First()) - // Make order stable between builds. - .OrderBy(f => f.TargetPath, StringComparer.Ordinal) - .ThenBy(f => f.Filename, StringComparer.Ordinal)) - { - string type = "Managed"; - - if (f.IsNative) - { - type = "Native"; - } - else if (f.IsResourceFile) - { - type = "Resources"; - } - - string path = Path.Combine(f.TargetPath, f.Filename).Replace('\\', '/'); - - if (path.StartsWith("runtimes/")) - { - var pathParts = path.Split('/'); - if (pathParts.Length > 1 && pathParts[1].Contains("_")) - { - // This file is a runtime file with a "rid" containing "_". This is assumed - // to mean it's a cross-targeting tool and shouldn't be deployed in a - // self-contained app. Leave it off the list. - continue; - } - } - - var element = new XElement( - "File", - new XAttribute("Type", type), - new XAttribute("Path", path)); - - if (f.IsResourceFile) - { - element.Add( - new XAttribute("Culture", Path.GetFileName(Path.GetDirectoryName(path)))); - } - - if (f.AssemblyName != null) - { - byte[] publicKeyToken = f.AssemblyName.GetPublicKeyToken(); - string publicKeyTokenHex; - - if (publicKeyToken != null) - { - publicKeyTokenHex = BitConverter.ToString(publicKeyToken) - .ToLowerInvariant() - .Replace("-", ""); - } - else - { - Log.LogError($"No public key token found for assembly {f.Item.ItemSpec}"); - publicKeyTokenHex = ""; - } - - element.Add( - new XAttribute("AssemblyName", f.AssemblyName.Name), - new XAttribute("PublicKeyToken", publicKeyTokenHex), - new XAttribute("AssemblyVersion", f.AssemblyName.Version)); - } - else if (!f.IsNative) - { - // This file isn't managed and isn't native. Leave it off the list. - continue; - } - - element.Add(new XAttribute("FileVersion", f.FileVersion)); - - if (fileClassLookup != null) - { - if (fileClassLookup.TryGetValue(f.Filename, out ITaskItem classItem)) - { - string profile = classItem.GetMetadata("Profile"); - - if (!string.IsNullOrEmpty(profile)) - { - element.Add(new XAttribute("Profile", profile)); - } - - string referencedByDefault = classItem.GetMetadata("ReferencedByDefault"); - - if (!string.IsNullOrEmpty(referencedByDefault)) - { - element.Add(new XAttribute("ReferencedByDefault", referencedByDefault)); - } - - usedFileClasses.Add(f.Filename); - } - else - { - Log.LogError($"File matches no classification: {f.Filename}"); - } - } - - frameworkManifest.Add(element); - } - - foreach (var unused in fileClassLookup - ?.Keys.Except(usedFileClasses).OrderBy(p => p) - ?? Enumerable.Empty()) - { - Log.LogError($"Classification matches no files: {unused}"); - } - - Directory.CreateDirectory(Path.GetDirectoryName(TargetFile)); - File.WriteAllText(TargetFile, frameworkManifest.ToString()); - - return !Log.HasLoggedErrors; - } - - private bool IsTargetPathIncluded(ITaskItem item) - { - return TargetFilePrefixes - ?.Any(prefix => item.GetMetadata("TargetPath")?.StartsWith(prefix) == true) ?? true; - } - } -} diff --git a/tools-local/tasks/installer.tasks/ExecWithRetries.cs b/tools-local/tasks/installer.tasks/ExecWithRetries.cs deleted file mode 100644 index 5e57c39f45819..0000000000000 --- a/tools-local/tasks/installer.tasks/ExecWithRetries.cs +++ /dev/null @@ -1,116 +0,0 @@ -// 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. - -// Initially copied from https://github.com/dotnet/buildtools/blob/6736870b84e06b75e7df32bb84d442db1b2afa10/src/Microsoft.DotNet.Build.Tasks/ExecWithRetries.cs - -using Microsoft.Build.Framework; -using Microsoft.Build.Tasks; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.DotNet.Build.Tasks -{ - /// - /// Run a command and retry if the exit code is not 0. - /// - public class ExecWithRetries : BuildTask - { - [Required] - public string Command { get; set; } - - public string WorkingDirectory { get; set; } - - public bool IgnoreStandardErrorWarningFormat { get; set; } - - public int MaxAttempts { get; set; } = 5; - - /// - /// Base, in seconds, raised to the power of the number of retries so far. - /// - public double RetryDelayBase { get; set; } = 6; - - /// - /// A constant, in seconds, added to (base^retries) to find the delay before retrying. - /// - /// The default is -1 to make the first retry instant, because ((base^0)-1) == 0. - /// - public double RetryDelayConstant { get; set; } = -1; - - /// - /// MSBuild message importance to use when logging stdout messages from the command. Default - /// is "High". - /// - public string StandardOutputImportance { get; set; } - - /// - /// MSBuild message importance to use when logging stderr messages from the command. Default - /// is "High". - /// - public string StandardErrorImportance { get; set; } - - private CancellationTokenSource _cancelTokenSource = new CancellationTokenSource(); - - private Exec _runningExec; - - public void Cancel() - { - _runningExec?.Cancel(); - _cancelTokenSource.Cancel(); - } - - public override bool Execute() - { - for (int i = 0; i < MaxAttempts; i++) - { - _runningExec = new Exec - { - BuildEngine = BuildEngine, - Command = Command, - WorkingDirectory = WorkingDirectory, - IgnoreStandardErrorWarningFormat = IgnoreStandardErrorWarningFormat, - StandardOutputImportance = StandardOutputImportance, - StandardErrorImportance = StandardErrorImportance, - LogStandardErrorAsError = false, - IgnoreExitCode = true - }; - - if (!_runningExec.Execute()) - { - Log.LogError("Child Exec task failed to execute."); - break; - } - - int exitCode = _runningExec.ExitCode; - if (exitCode == 0) - { - return true; - } - - string message = $"Exec FAILED: exit code {exitCode} (attempt {i + 1}/{MaxAttempts})"; - - if (i + 1 == MaxAttempts || _cancelTokenSource.IsCancellationRequested) - { - Log.LogError(message); - break; - } - - TimeSpan delay = TimeSpan.FromSeconds( - Math.Pow(RetryDelayBase, i) + RetryDelayConstant); - - Log.LogMessage(MessageImportance.High, $"{message} -- Retrying after {delay}..."); - - try - { - Task.Delay(delay, _cancelTokenSource.Token).Wait(); - } - catch (AggregateException e) when (e.InnerException is TaskCanceledException) - { - break; - } - } - return false; - } - } -} diff --git a/tools-local/tasks/installer.tasks/GenerateDebRepoUploadJsonFile.cs b/tools-local/tasks/installer.tasks/GenerateDebRepoUploadJsonFile.cs deleted file mode 100644 index 51e373915cb27..0000000000000 --- a/tools-local/tasks/installer.tasks/GenerateDebRepoUploadJsonFile.cs +++ /dev/null @@ -1,44 +0,0 @@ -// 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 Microsoft.Build.Framework; -using System.IO; - - -namespace Microsoft.DotNet.Build.Tasks -{ - public partial class GenerateDebRepoUploadJsonFile : BuildTask - { - private const string _debianRevisionNumber = "1"; - [Required] - public string RepoId { get; set; } - [Required] - public string UploadJsonFilename { get; set; } - [Required] - public string PackageName { get; set; } - [Required] - public string PackageVersion { get; set; } - [Required] - public string UploadUrl { get; set; } - - public override bool Execute() - { - File.Delete(UploadJsonFilename); - - using (var fileStream = File.Create(UploadJsonFilename)) - { - using (StreamWriter sw = new StreamWriter(fileStream)) - { - sw.WriteLine("{"); - sw.WriteLine($" \"name\":\"{PackageName}\","); - sw.WriteLine($" \"version\":\"{PackageVersion}-{_debianRevisionNumber}\","); - sw.WriteLine($" \"repositoryId\":\"{RepoId}\","); - sw.WriteLine($" \"sourceUrl\":\"{UploadUrl}\""); - sw.WriteLine("}"); - } - } - return !Log.HasLoggedErrors; - } - } -} \ No newline at end of file diff --git a/tools-local/tasks/installer.tasks/GenerateJsonObjectString.cs b/tools-local/tasks/installer.tasks/GenerateJsonObjectString.cs deleted file mode 100644 index 558c4b1654eee..0000000000000 --- a/tools-local/tasks/installer.tasks/GenerateJsonObjectString.cs +++ /dev/null @@ -1,145 +0,0 @@ -// 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 Microsoft.Build.Framework; -using System; -using System.IO; -using System.Linq; -using System.Text; - -namespace Microsoft.DotNet.Build.Tasks -{ - public class GenerateJsonObjectString : BuildTask - { - private static readonly string __indent1 = new string(' ', 4); - private static readonly string __indent2 = new string(' ', 8); - - /// - /// Properties to include. If multiple properties have the same name, each property value is - /// included in an array. Only specify one value metadata: the first value is used. - /// - /// %(Identity): Name of the property. - /// %(String): String value of the property. This task adds quotes around it in the JSON. - /// %(Object): Object value of the property. Create this with a nested call to this task. - /// - [Required] - public ITaskItem[] Properties { get; set; } - - /// - /// If set, also write the output JSON string to this file. - /// - public string TargetFile { get; set; } - - [Output] - public string Json { get; set; } - - public override bool Execute() - { - var result = new StringBuilder(); - result.AppendLine("{"); - - bool firstProperty = true; - - foreach (var group in Properties.GroupBy(item => item.ItemSpec)) - { - if (firstProperty) - { - firstProperty = false; - } - else - { - result.AppendLine(","); - } - - result.Append(__indent1); - result.Append("\""); - result.Append(group.Key); - result.Append("\": "); - - if (group.Count() == 1) - { - ITaskItem item = group.First(); - WriteProperty(result, item, __indent1); - } - else - { - result.AppendLine("["); - - bool firstArrayLine = true; - - foreach (ITaskItem item in group) - { - if (firstArrayLine) - { - firstArrayLine = false; - } - else - { - result.AppendLine(","); - } - - result.Append(__indent2); - WriteProperty(result, item, __indent2); - } - - result.AppendLine(); - result.Append(__indent1); - result.Append("]"); - } - } - - result.AppendLine(); - result.AppendLine("}"); - - Json = result.ToString(); - - if (!string.IsNullOrEmpty(TargetFile)) - { - Directory.CreateDirectory(Path.GetDirectoryName(TargetFile)); - File.WriteAllText(TargetFile, Json); - } - - return !Log.HasLoggedErrors; - } - - private void WriteProperty(StringBuilder result, ITaskItem item, string indent) - { - string stringValue = item.GetMetadata("String"); - string objectValue = item.GetMetadata("Object"); - - if (!string.IsNullOrEmpty(stringValue)) - { - result.Append("\""); - result.Append(stringValue); - result.Append("\""); - } - else if (!string.IsNullOrEmpty(objectValue)) - { - bool firstObjectLine = true; - - foreach (var line in objectValue.Split( - new[] {Environment.NewLine}, - StringSplitOptions.RemoveEmptyEntries)) - { - if (firstObjectLine) - { - firstObjectLine = false; - } - else - { - result.AppendLine(); - result.Append(indent); - } - - result.Append(line); - } - } - else - { - Log.LogError($"Item '{item.ItemSpec}' has no String or Object value."); - result.Append("null"); - } - } - } -} diff --git a/tools-local/tasks/installer.tasks/ProcessSharedFrameworkDeps.cs b/tools-local/tasks/installer.tasks/ProcessSharedFrameworkDeps.cs deleted file mode 100644 index 687a8c1448b75..0000000000000 --- a/tools-local/tasks/installer.tasks/ProcessSharedFrameworkDeps.cs +++ /dev/null @@ -1,83 +0,0 @@ -// 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 Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using Microsoft.Extensions.DependencyModel; -using NuGet.Common; -using NuGet.ProjectModel; -using System; -using System.IO; -using System.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - public partial class ProcessSharedFrameworkDeps : Task - { - [Required] - public string AssetsFilePath { get; set; } - - [Required] - public string DepsFilePath { get; set; } - - [Required] - public string[] PackagesToRemove { get; set; } - - [Required] - public string Runtime { get; set; } - - [Required] - public string BuildTasksAssemblyPath { get; set; } - - public override bool Execute() - { - EnsureInitialized(BuildTasksAssemblyPath); - - ExecuteCore(); - - return true; - } - - private void ExecuteCore() - { - DependencyContext context; - using (var depsStream = File.OpenRead(DepsFilePath)) - { - context = new DependencyContextJsonReader().Read(depsStream); - } - - LockFile lockFile = LockFileUtilities.GetLockFile(AssetsFilePath, NullLogger.Instance); - if (lockFile == null) - { - throw new ArgumentException($"Could not load a LockFile at '{AssetsFilePath}'.", nameof(AssetsFilePath)); - } - - var manager = new RuntimeGraphManager(); - var graph = manager.Collect(lockFile); - var expandedGraph = manager.Expand(graph, Runtime); - - var trimmedRuntimeLibraries = context.RuntimeLibraries; - - if (PackagesToRemove != null && PackagesToRemove.Any()) - { - trimmedRuntimeLibraries = RuntimeReference.RemoveReferences(context.RuntimeLibraries, PackagesToRemove); - } - - context = new DependencyContext( - context.Target, - context.CompilationOptions, - context.CompileLibraries, - trimmedRuntimeLibraries, - expandedGraph - ); - - using (var depsStream = File.Create(DepsFilePath)) - { - new DependencyContextWriter().Write(context, depsStream); - } - } - - partial void EnsureInitialized(string buildTasksAssemblyPath); - } -} diff --git a/tools-local/tasks/installer.tasks/RuntimeGraphManager.cs b/tools-local/tasks/installer.tasks/RuntimeGraphManager.cs deleted file mode 100644 index 2bedeef64b844..0000000000000 --- a/tools-local/tasks/installer.tasks/RuntimeGraphManager.cs +++ /dev/null @@ -1,65 +0,0 @@ -// 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 Microsoft.Extensions.DependencyModel; -using NuGet.Packaging; -using NuGet.ProjectModel; -using NuGet.RuntimeModel; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - internal class RuntimeGraphManager - { - private const string RuntimeJsonFileName = "runtime.json"; - - public RuntimeGraph Collect(LockFile lockFile) - { - string userPackageFolder = lockFile.PackageFolders.FirstOrDefault()?.Path; - var fallBackFolders = lockFile.PackageFolders.Skip(1).Select(f => f.Path); - var packageResolver = new FallbackPackagePathResolver(userPackageFolder, fallBackFolders); - - var graph = RuntimeGraph.Empty; - foreach (var library in lockFile.Libraries) - { - if (string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase)) - { - var runtimeJson = library.Files.FirstOrDefault(f => f == RuntimeJsonFileName); - if (runtimeJson != null) - { - var libraryPath = packageResolver.GetPackageDirectory(library.Name, library.Version); - var runtimeJsonFullName = Path.Combine(libraryPath, runtimeJson); - graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName)); - } - } - } - return graph; - } - - public IEnumerable Expand(RuntimeGraph runtimeGraph, string runtime) - { - var importers = FindImporters(runtimeGraph, runtime); - foreach (var importer in importers) - { - // ExpandRuntime return runtime itself as first item so we are skiping it - yield return new RuntimeFallbacks(importer, runtimeGraph.ExpandRuntime(importer).Skip(1)); - } - } - - private IEnumerable FindImporters(RuntimeGraph runtimeGraph, string runtime) - { - foreach (var runtimePair in runtimeGraph.Runtimes) - { - var expanded = runtimeGraph.ExpandRuntime(runtimePair.Key); - if (expanded.Contains(runtime)) - { - yield return runtimePair.Key; - } - } - } - } -} diff --git a/tools-local/tasks/installer.tasks/RuntimeReference.cs b/tools-local/tasks/installer.tasks/RuntimeReference.cs deleted file mode 100644 index ead20e864c062..0000000000000 --- a/tools-local/tasks/installer.tasks/RuntimeReference.cs +++ /dev/null @@ -1,63 +0,0 @@ -// 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 Microsoft.Extensions.DependencyModel; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - internal class RuntimeReference - { - public static List RemoveReferences(IReadOnlyList runtimeLibraries, IEnumerable packages) - { - List result = new List(); - - foreach (var runtimeLib in runtimeLibraries) - { - if (string.IsNullOrEmpty(packages.FirstOrDefault(elem => runtimeLib.Name.Equals(elem, StringComparison.OrdinalIgnoreCase)))) - { - List toRemoveDependecy = new List(); - foreach (var dependency in runtimeLib.Dependencies) - { - if (!string.IsNullOrEmpty(packages.FirstOrDefault(elem => dependency.Name.Equals(elem, StringComparison.OrdinalIgnoreCase)))) - { - toRemoveDependecy.Add(dependency); - } - } - - if (toRemoveDependecy.Count > 0) - { - List modifiedDependencies = new List(); - foreach (var dependency in runtimeLib.Dependencies) - { - if (!toRemoveDependecy.Contains(dependency)) - { - modifiedDependencies.Add(dependency); - } - } - - - result.Add(new RuntimeLibrary(runtimeLib.Type, - runtimeLib.Name, - runtimeLib.Version, - runtimeLib.Hash, - runtimeLib.RuntimeAssemblyGroups, - runtimeLib.NativeLibraryGroups, - runtimeLib.ResourceAssemblies, - modifiedDependencies, - runtimeLib.Serviceable)); - - } - else if (string.IsNullOrEmpty(packages.FirstOrDefault(elem => runtimeLib.Name.Equals(elem, StringComparison.OrdinalIgnoreCase)))) - { - result.Add(runtimeLib); - } - } - } - return result; - } - } -} diff --git a/tools-local/tasks/installer.tasks/StabilizeWixFileId.cs b/tools-local/tasks/installer.tasks/StabilizeWixFileId.cs deleted file mode 100644 index 6a76df1df2bd4..0000000000000 --- a/tools-local/tasks/installer.tasks/StabilizeWixFileId.cs +++ /dev/null @@ -1,107 +0,0 @@ -// 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 Microsoft.Build.Framework; -using System; -using System.Diagnostics; -using System.Linq; -using System.Xml.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - /// - /// In a WiX source file, replaces the Id of a File with some given string in order to stabilize - /// it. This allows external tooling such as signature validators to rely on a stable identifier - /// for certain files. - /// - public class StabilizeWixFileId : BuildTask - { - /// - /// File to read from. This is expected to be an output from heat.exe. - /// - /// Expected format: - /// - /// - /// - /// - /// - /// - /// - /// ... - /// - [Required] - public string SourceFile { get; set; } - - /// - /// File to write to. May be the same as SourceFile. - /// - [Required] - public string OutputFile { get; set; } - - /// - /// Set of files to stabilize. This matches the end of the "Source" attribute in the WiX - /// source file. If exactly one match isn't found in the WiX source file, this task fails. - /// - /// %(Identity): The file source to replace. - /// %(ReplacementId): The replacement for Id that won't change per-build. - /// - [Required] - public ITaskItem[] FileElementToStabilize { get; set; } - - public override bool Execute() - { - XDocument content = XDocument.Load(SourceFile); - - XNamespace rootNamespace = content.Root.GetDefaultNamespace(); - XName GetQualifiedName(string name) => rootNamespace.GetName(name); - - foreach (var file in FileElementToStabilize) - { - string replacement = file.GetMetadata("ReplacementId"); - - if (string.IsNullOrEmpty(replacement)) - { - Log.LogError($"{nameof(FileElementToStabilize)} {file.ItemSpec} has null/empty ReplacementId metadata."); - continue; - } - - XElement[] matchingFileElements = content.Element(GetQualifiedName("Wix")) - .Elements(GetQualifiedName("Fragment")) - .SelectMany(f => f.Elements(GetQualifiedName("ComponentGroup"))) - .SelectMany(cg => cg.Elements(GetQualifiedName("Component"))) - .SelectMany(c => c.Elements(GetQualifiedName("File"))) - .Where(f => f.Attribute("Source")?.Value - ?.EndsWith(file.ItemSpec, StringComparison.OrdinalIgnoreCase) == true) - .ToArray(); - - if (matchingFileElements.Length != 1) - { - Log.LogError( - $"Expected 1 match for '{file.ItemSpec}', found {matchingFileElements.Length}: " + - string.Join(", ", matchingFileElements.Select(e => e.ToString()))); - - continue; - } - - XAttribute nameAttribute = matchingFileElements[0].Attribute("Id"); - - if (nameAttribute is null) - { - Log.LogError($"Match has no Id attribute: {matchingFileElements[0]}"); - continue; - } - - Log.LogMessage( - $"Setting '{file.ItemSpec}' Id to '{replacement}' for File with Source " + - matchingFileElements[0].Attribute("Source").Value); - - nameAttribute.Value = replacement; - } - - content.Save(OutputFile); - - return !Log.HasLoggedErrors; - } - } -} diff --git a/tools-local/tasks/installer.tasks/ZipFileExtractToDirectory.cs b/tools-local/tasks/installer.tasks/ZipFileExtractToDirectory.cs deleted file mode 100644 index e03a860819ec3..0000000000000 --- a/tools-local/tasks/installer.tasks/ZipFileExtractToDirectory.cs +++ /dev/null @@ -1,86 +0,0 @@ -// 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 Microsoft.Build.Framework; -using System; -using System.IO; -using System.IO.Compression; - -namespace Microsoft.DotNet.Build.Tasks -{ - public sealed class ZipFileExtractToDirectory : BuildTask - { - /// - /// The path to the archive to be extracted. - /// - [Required] - public string SourceArchive { get; set; } - - /// - /// The path of the directory to extract into. - /// - [Required] - public string DestinationDirectory { get; set; } - - /// - /// Indicates if the destination directory should be overwritten if it already exists. - /// - public bool OverwriteDestination { get; set; } - - /// - /// File entries to include in the extraction. Entries are relative - /// paths inside the archive. If null or empty, all files are extracted. - /// - public ITaskItem[] Include { get; set; } - - public override bool Execute() - { - try - { - if (Directory.Exists(DestinationDirectory)) - { - if (OverwriteDestination) - { - Log.LogMessage(MessageImportance.Low, $"'{DestinationDirectory}' already exists, trying to delete before unzipping..."); - Directory.Delete(DestinationDirectory, recursive: true); - } - else - { - Log.LogWarning($"'{DestinationDirectory}' already exists. Did you forget to set '{nameof(OverwriteDestination)}' to true?"); - } - } - - Log.LogMessage(MessageImportance.High, "Decompressing '{0}' into '{1}'...", SourceArchive, DestinationDirectory); - Directory.CreateDirectory(Path.GetDirectoryName(DestinationDirectory)); - - using (ZipArchive archive = ZipFile.OpenRead(SourceArchive)) - { - if (Include?.Length > 0) - { - foreach (ITaskItem entryItem in Include) - { - ZipArchiveEntry entry = archive.GetEntry(entryItem.ItemSpec); - string destinationPath = Path.Combine(DestinationDirectory, entryItem.ItemSpec); - - Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); - entry.ExtractToFile(destinationPath, overwrite: false); - } - } - else - { - archive.ExtractToDirectory(DestinationDirectory); - } - } - } - catch (Exception e) - { - // We have 2 log calls because we want a nice error message but we also want to capture the callstack in the log. - Log.LogError("An exception has occurred while trying to decompress '{0}' into '{1}'.", SourceArchive, DestinationDirectory); - Log.LogErrorFromException(e, /*show stack=*/ true, /*show detail=*/ true, DestinationDirectory); - return false; - } - return true; - } - } -} diff --git a/tools-local/tasks/installer.tasks/ZipFileGetEntries.cs b/tools-local/tasks/installer.tasks/ZipFileGetEntries.cs deleted file mode 100644 index 56b1e3804e187..0000000000000 --- a/tools-local/tasks/installer.tasks/ZipFileGetEntries.cs +++ /dev/null @@ -1,50 +0,0 @@ -// 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 Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using System; -using System.IO.Compression; -using System.Linq; - -namespace Microsoft.DotNet.Build.Tasks -{ - public sealed class ZipFileGetEntries : BuildTask - { - /// - /// The path to the archive. - /// - [Required] - public string TargetArchive { get; set; } - - /// - /// Generated items where each ItemSpec is the relative location of a - /// file entry in the zip archive. - /// - [Output] - public ITaskItem[] Entries { get; set; } - - public override bool Execute() - { - try - { - using (ZipArchive archive = ZipFile.OpenRead(TargetArchive)) - { - Entries = archive.Entries - // Escape '%' so encoded '+' in the nupkg stays encoded through MSBuild. - .Select(e => new TaskItem(e.FullName.Replace("%", "%25"))) - .ToArray(); - } - } - catch (Exception e) - { - // We have 2 log calls because we want a nice error message but we also want to capture the callstack in the log. - Log.LogError($"An exception has occurred while trying to read entries from '{TargetArchive}'."); - Log.LogErrorFromException(e, /*show stack=*/ true, /*show detail=*/ true, TargetArchive); - return false; - } - return true; - } - } -} diff --git a/src/mono/msbuild/AndroidAppBuilder/AndroidAppBuilder.cs b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.cs similarity index 91% rename from src/mono/msbuild/AndroidAppBuilder/AndroidAppBuilder.cs rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.cs index 57e1f90aba85d..baaa1c7f18e2f 100644 --- a/src/mono/msbuild/AndroidAppBuilder/AndroidAppBuilder.cs +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.cs @@ -22,7 +22,7 @@ public class AndroidAppBuilderTask : Task public string MainLibraryFileName { get; set; } = ""!; /// - /// Target arch, can be 'x86', 'x86_64', 'armeabi', 'armeabi-v7a' or 'arm64-v8a' + /// Target arch, can be 'x86', 'x86_64', 'armeabi-v7a' or 'arm64-v8a' /// [Required] public string Abi { get; set; } = ""!; @@ -41,6 +41,8 @@ public class AndroidAppBuilderTask : Task public string? BuildToolsVersion { get; set; } + public bool StripDebugSymbols { get; set; } + [Output] public string ApkBundlePath { get; set; } = ""!; @@ -59,6 +61,7 @@ public override bool Execute() apkBuilder.MinApiLevel = MinApiLevel; apkBuilder.BuildApiLevel = BuildApiLevel; apkBuilder.BuildToolsVersion = BuildToolsVersion; + apkBuilder.StripDebugSymbols = StripDebugSymbols; (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(SourceDir, Abi, MainLibraryFileName, MonoRuntimeHeaders); return true; diff --git a/src/mono/msbuild/AndroidAppBuilder/AndroidAppBuilder.csproj b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.csproj similarity index 91% rename from src/mono/msbuild/AndroidAppBuilder/AndroidAppBuilder.csproj rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.csproj index d0ced747eb0be..179ca9aa2af4a 100644 --- a/src/mono/msbuild/AndroidAppBuilder/AndroidAppBuilder.csproj +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.csproj @@ -1,11 +1,10 @@ + $(NetCoreAppCurrent) Library - bin - $(NetCoreAppCurrent) - enable true false + enable diff --git a/src/mono/msbuild/AndroidAppBuilder/ApkBuilder.cs b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/ApkBuilder.cs similarity index 78% rename from src/mono/msbuild/AndroidAppBuilder/ApkBuilder.cs rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/ApkBuilder.cs index 715d4e70b10d4..e7fcebdd08eb1 100644 --- a/src/mono/msbuild/AndroidAppBuilder/ApkBuilder.cs +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/ApkBuilder.cs @@ -14,6 +14,7 @@ public class ApkBuilder public string? BuildApiLevel { get; set; } public string? BuildToolsVersion { get; set; } public string? OutputDir { get; set; } + public bool StripDebugSymbols { get; set; } public (string apk, string packageId) BuildApk( string sourceDir, string abi, string entryPointLib, string monoRuntimeHeaders) @@ -22,7 +23,7 @@ public class ApkBuilder throw new ArgumentException($"sourceDir='{sourceDir}' is empty or doesn't exist"); if (string.IsNullOrEmpty(abi)) - throw new ArgumentException("abi shoudln't be empty (e.g. x86, x86_64, armeabi, armeabi-v7a or arm64-v8a"); + throw new ArgumentException("abi shoudln't be empty (e.g. x86, x86_64, armeabi-v7a or arm64-v8a"); if (string.IsNullOrEmpty(entryPointLib)) throw new ArgumentException("entryPointLib shouldn't be empty"); @@ -79,17 +80,27 @@ public class ApkBuilder Directory.CreateDirectory(OutputDir); Directory.CreateDirectory(Path.Combine(OutputDir, "bin")); Directory.CreateDirectory(Path.Combine(OutputDir, "obj")); + Directory.CreateDirectory(Path.Combine(OutputDir, "assets-tozip")); Directory.CreateDirectory(Path.Combine(OutputDir, "assets")); - // Copy AppDir to OutputDir/assets (ignore native files) - Utils.DirectoryCopy(sourceDir, Path.Combine(OutputDir, "assets"), file => + var extensionsToIgnore = new List { ".so", ".a", ".gz" }; + if (StripDebugSymbols) + { + extensionsToIgnore.Add(".pdb"); + extensionsToIgnore.Add(".dbg"); + } + + // Copy AppDir to OutputDir/assets-tozip (ignore native files) + // these files then will be zipped and copied to apk/assets/assets.zip + Utils.DirectoryCopy(sourceDir, Path.Combine(OutputDir, "assets-tozip"), file => { string fileName = Path.GetFileName(file); string extension = Path.GetExtension(file); - // ignore native files, those go to lib/%abi% - if (extension == ".so" || extension == ".a") + + if (extensionsToIgnore.Contains(extension)) { - // ignore ".pdb" and ".dbg" to make APK smaller + // ignore native files, those go to lib/%abi% + // also, aapt is not happy about zip files return false; } if (fileName.StartsWith(".")) @@ -110,6 +121,10 @@ public class ApkBuilder string keytool = "keytool"; string javac = "javac"; string cmake = "cmake"; + string zip = "zip"; + + Utils.RunProcess(zip, workingDir: Path.Combine(OutputDir, "assets-tozip"), args: "-q -r ../assets/assets.zip ."); + Directory.Delete(Path.Combine(OutputDir, "assets-tozip"), true); if (!File.Exists(androidJar)) throw new ArgumentException($"API level={BuildApiLevel} is not downloaded in Android SDK"); @@ -126,13 +141,29 @@ public class ApkBuilder File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists); string runtimeAndroidSrc = Utils.GetEmbeddedResource("runtime-android.c") - .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib)); + .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib) + .Replace("%RID%", GetRid(abi))); File.WriteAllText(Path.Combine(OutputDir, "runtime-android.c"), runtimeAndroidSrc); - Utils.RunProcess(cmake, workingDir: OutputDir, - args: $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " + - $"-DANDROID_NATIVE_API_LEVEL={MinApiLevel} -B runtime-android"); - Utils.RunProcess("make", workingDir: Path.Combine(OutputDir, "runtime-android")); + string cmakeGenArgs = $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " + + $"-DANDROID_NATIVE_API_LEVEL={MinApiLevel} -B runtime-android"; + + string cmakeBuildArgs = "--build runtime-android"; + + if (StripDebugSymbols) + { + // Use "-s" to strip debug symbols, it complains it's unused but it works + cmakeGenArgs+= " -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_C_FLAGS=\"-s -Wno-unused-command-line-argument\""; + cmakeBuildArgs += " --config MinSizeRel"; + } + else + { + cmakeGenArgs += " -DCMAKE_BUILD_TYPE=Debug"; + cmakeBuildArgs += " --config Debug"; + } + + Utils.RunProcess(cmake, workingDir: OutputDir, args: cmakeGenArgs); + Utils.RunProcess(cmake, workingDir: OutputDir, args: cmakeBuildArgs); // 2. Compile Java files @@ -168,7 +199,16 @@ public class ApkBuilder Directory.CreateDirectory(Path.Combine(OutputDir, "lib", abi)); foreach (var dynamicLib in dynamicLibs) { - string destRelative = Path.Combine("lib", abi, Path.GetFileName(dynamicLib)); + string dynamicLibName = Path.GetFileName(dynamicLib); + if (dynamicLibName == "libmonosgen-2.0.so") + { + // we link mono runtime statically into libruntime-android.so + continue; + } + + // NOTE: we can run android-strip tool from NDK to shrink native binaries here even more. + + string destRelative = Path.Combine("lib", abi, dynamicLibName); File.Copy(dynamicLib, Path.Combine(OutputDir, destRelative), true); Utils.RunProcess(aapt, $"add {apkFile} {destRelative}", workingDir: OutputDir); } @@ -178,6 +218,8 @@ public class ApkBuilder string alignedApk = Path.Combine(OutputDir, "bin", $"{ProjectName}.apk"); Utils.RunProcess(zipalign, $"-v 4 {apkFile} {alignedApk}", workingDir: OutputDir); + // we don't need the unaligned one any more + File.Delete(apkFile); // 5. Generate key @@ -194,8 +236,18 @@ public class ApkBuilder Utils.RunProcess(apksigner, $"sign --min-sdk-version {MinApiLevel} --ks debug.keystore " + $"--ks-pass pass:android --key-pass pass:android {alignedApk}", workingDir: OutputDir); + Utils.LogInfo($"\nAPK size: {(new FileInfo(alignedApk).Length / 1000_000.0):0.#} Mb.\n"); + return (alignedApk, packageId); } + + private static string GetRid(string abi) => abi switch + { + "arm64-v8a" => "android-arm64", + "armeabi-v7a" => "android-arm", + "x86_64" => "android-x64", + _ => "android-" + abi + }; /// /// Scan android SDK for build tools (ignore preview versions) diff --git a/src/mono/msbuild/AndroidAppBuilder/Templates/AndroidManifest.xml b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/AndroidManifest.xml similarity index 100% rename from src/mono/msbuild/AndroidAppBuilder/Templates/AndroidManifest.xml rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/AndroidManifest.xml diff --git a/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt new file mode 100644 index 0000000000000..18727daa90605 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.10) + +project(runtime-android) + +add_library( + runtime-android + SHARED + runtime-android.c) + +include_directories("%MonoInclude%") + +target_link_libraries( + runtime-android + %NativeLibrariesToLink% + libz.so + log + "-u GlobalizationNative_LoadICU" + "-u GlobalizationNative_GetLatestJapaneseEra" + "-u GlobalizationNative_ChangeCase" + "-u GlobalizationNative_CloseSortHandle" + "-u GlobalizationNative_GetLocales" + "-u GlobalizationNative_GetLocaleInfoInt" + "-u GlobalizationNative_GetLocaleTimeFormat" + "-u GlobalizationNative_ToUnicode" + "-u GlobalizationNative_NormalizeString" + "-u GlobalizationNative_GetTimeZoneDisplayName") diff --git a/src/mono/msbuild/AndroidAppBuilder/Templates/MainActivity.java b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/MainActivity.java similarity index 100% rename from src/mono/msbuild/AndroidAppBuilder/Templates/MainActivity.java rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/MainActivity.java diff --git a/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/MonoRunner.java b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/MonoRunner.java new file mode 100644 index 0000000000000..6acedccf6ac2e --- /dev/null +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/MonoRunner.java @@ -0,0 +1,108 @@ +// 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. + +package net.dot; + +import android.app.Instrumentation; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.app.Activity; +import android.os.Environment; +import android.net.Uri; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.BufferedInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class MonoRunner extends Instrumentation +{ + static MonoRunner inst; + + static { + System.loadLibrary("runtime-android"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + start(); + } + + @Override + public void onStart() { + super.onStart(); + + MonoRunner.inst = this; + Context context = getContext(); + String filesDir = context.getFilesDir().getAbsolutePath(); + String cacheDir = context.getCacheDir().getAbsolutePath(); + File docsPath = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS); + if (docsPath == null) { + docsPath = context.getCacheDir(); + } + String docsDir = docsPath.getAbsolutePath(); + + // unzip libs and test files to filesDir + unzipAssets(context, filesDir, "assets.zip"); + + Log.i("DOTNET", "initRuntime"); + int retcode = initRuntime(filesDir, cacheDir, docsDir); + runOnMainSync(new Runnable() { + public void run() { + Bundle result = new Bundle(); + result.putInt("return-code", retcode); + // Xharness cli expects "test-results-path" with test results + result.putString("test-results-path", docsDir + "/testResults.xml"); + finish(retcode, result); + } + }); + } + + static void unzipAssets(Context context, String toPath, String zipName) { + AssetManager assetManager = context.getAssets(); + try { + InputStream inputStream = assetManager.open(zipName); + ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(inputStream)); + ZipEntry zipEntry; + byte[] buffer = new byte[4096]; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + String fileOrDirectory = zipEntry.getName(); + Uri.Builder builder = new Uri.Builder(); + builder.scheme("file"); + builder.appendPath(toPath); + builder.appendPath(fileOrDirectory); + String fullToPath = builder.build().getPath(); + if (zipEntry.isDirectory()) { + File directory = new File(fullToPath); + directory.mkdirs(); + continue; + } + Log.i("DOTNET", "Extracting asset to " + fullToPath); + int count = 0; + FileOutputStream fileOutputStream = new FileOutputStream(fullToPath); + while ((count = zipInputStream.read(buffer)) != -1) { + fileOutputStream.write(buffer, 0, count); + } + fileOutputStream.close(); + zipInputStream.closeEntry(); + } + zipInputStream.close(); + } catch (IOException e) { + Log.e("DOTNET", e.getLocalizedMessage()); + } + } + + native int initRuntime(String libsDir, String cacheDir, String docsDir); +} diff --git a/src/mono/msbuild/AndroidAppBuilder/Templates/runtime-android.c b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/runtime-android.c similarity index 95% rename from src/mono/msbuild/AndroidAppBuilder/Templates/runtime-android.c rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/runtime-android.c index 8cfdaaf4b998e..4a2af6a62ead7 100644 --- a/src/mono/msbuild/AndroidAppBuilder/Templates/runtime-android.c +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Templates/runtime-android.c @@ -146,7 +146,16 @@ mono_mobile_runtime_init (void) chdir (bundle_path); // TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES - monovm_initialize(0, NULL, NULL); + + const char* appctx_keys[2]; + appctx_keys[0] = "RUNTIME_IDENTIFIER"; + appctx_keys[1] = "APP_CONTEXT_BASE_DIRECTORY"; + + const char* appctx_values[2]; + appctx_values[0] = "%RID%"; + appctx_values[1] = bundle_path; + + monovm_initialize(2, appctx_keys, appctx_values); mono_debug_init (MONO_DEBUG_FORMAT_MONO); mono_install_assembly_preload_hook (assembly_preload_hook, NULL); diff --git a/src/mono/msbuild/AndroidAppBuilder/Utils.cs b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Utils.cs similarity index 95% rename from src/mono/msbuild/AndroidAppBuilder/Utils.cs rename to tools-local/tasks/mobile.tasks/AndroidAppBuilder/Utils.cs index a5e182465c741..bc23f927ae26f 100644 --- a/src/mono/msbuild/AndroidAppBuilder/Utils.cs +++ b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/Utils.cs @@ -26,7 +26,7 @@ public static string GetEmbeddedResource(string file) IDictionary? envVars = null, string? workingDir = null, bool ignoreErrors = false, - bool silent = false) + bool silent = true) { LogInfo($"Running: {path} {args}"); var outputBuilder = new StringBuilder(); @@ -52,7 +52,7 @@ public static string GetEmbeddedResource(string file) Process? process = Process.Start(processStartInfo); if (process == null) - throw new ArgumentException("Process.Start({path} {args}) returned null process"); + throw new ArgumentException($"Process.Start({path} {args}) returned null process"); process.ErrorDataReceived += (sender, e) => { @@ -60,8 +60,8 @@ public static string GetEmbeddedResource(string file) { LogError(e.Data); outputBuilder.AppendLine(e.Data); - errorBuilder.AppendLine(e.Data); } + errorBuilder.AppendLine(e.Data); }; process.OutputDataReceived += (sender, e) => { diff --git a/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.cs b/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.cs new file mode 100644 index 0000000000000..8f8643ae606d7 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -0,0 +1,256 @@ +// 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.Collections.Generic; +using System.Collections.Concurrent; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +public class MonoAOTCompiler : Microsoft.Build.Utilities.Task +{ + /// + /// Path to AOT cross-compiler binary (mono-aot-cross) + /// + [Required] + public string CompilerBinaryPath { get; set; } = ""!; + + /// + /// Assemblies to be AOTd. They need to be in a self-contained directory. + /// + /// Metadata: + /// - AotArguments: semicolon-separated list of options that will be passed to --aot= + /// - ProcessArguments: semicolon-separated list of options that will be passed to the AOT compiler itself + /// + [Required] + public ITaskItem[] Assemblies { get; set; } = Array.Empty(); + + /// + /// Assemblies which were AOT compiled. + /// + /// Successful AOT compilation will set the following metadata on the items: + /// - AssemblerFile (when using OutputType=AsmOnly) + /// - ObjectFile (when using OutputType=Normal) + /// - AotDataFile + /// - LlvmObjectFile (if using LLVM) + /// - LlvmBitcodeFile (if using LLVM-only) + /// + [Output] + public ITaskItem[]? CompiledAssemblies { get; set; } + + /// + /// Disable parallel AOT compilation + /// + public bool DisableParallelAot { get; set; } + + /// + /// Use LLVM for AOT compilation. + /// The cross-compiler must be built with LLVM support + /// + public bool UseLLVM { get; set; } + + /// + /// Choose between 'Normal', 'Full', 'LLVMOnly'. + /// LLVMOnly means to use only LLVM for FullAOT, AOT result will be a LLVM Bitcode file (the cross-compiler must be built with LLVM support) + /// + public string Mode { get; set; } = nameof(MonoAotMode.Normal); + + /// + /// Choose between 'Normal', 'AsmOnly' + /// AsmOnly means the AOT compiler will produce .s assembly code instead of an .o object file. + /// + public string OutputType { get; set; } = nameof(MonoAotOutputType.Normal); + + /// + /// Path to the directory where LLVM binaries (opt and llc) are found. + /// It's required if UseLLVM is set + /// + public string? LLVMPath { get; set; } + + /// + /// Path to the directory where msym artifacts are stored. + /// + public string? MsymPath { get; set; } + + ConcurrentBag compiledAssemblies = new ConcurrentBag(); + MonoAotMode parsedAotMode; + MonoAotOutputType parsedOutputType; + + public override bool Execute() + { + Utils.Logger = Log; + + if (string.IsNullOrEmpty(CompilerBinaryPath)) + { + throw new ArgumentException($"'{nameof(CompilerBinaryPath)}' is required.", nameof(CompilerBinaryPath)); + } + + if (!File.Exists(CompilerBinaryPath)) + { + throw new ArgumentException($"'{CompilerBinaryPath}' doesn't exist.", nameof(CompilerBinaryPath)); + } + + if (Assemblies.Length == 0) + { + throw new ArgumentException($"'{nameof(Assemblies)}' is required.", nameof(Assemblies)); + } + + if (UseLLVM && string.IsNullOrEmpty(LLVMPath)) + { + // prevent using some random llc/opt from PATH (installed with clang) + throw new ArgumentException($"'{nameof(LLVMPath)}' is required when '{nameof(UseLLVM)}' is true.", nameof(LLVMPath)); + } + + switch (Mode) + { + case "Normal": parsedAotMode = MonoAotMode.Normal; break; + case "Full": parsedAotMode = MonoAotMode.Full; break; + case "LLVMOnly": parsedAotMode = MonoAotMode.LLVMOnly; break; + default: + throw new ArgumentException($"'{nameof(Mode)}' must be one of: '{nameof(MonoAotMode.Normal)}', '{nameof(MonoAotMode.Full)}', '{nameof(MonoAotMode.LLVMOnly)}'. Received: '{Mode}'.", nameof(Mode)); + } + + switch (OutputType) + { + case "Normal": parsedOutputType = MonoAotOutputType.Normal; break; + case "AsmOnly": parsedOutputType = MonoAotOutputType.AsmOnly; break; + default: + throw new ArgumentException($"'{nameof(OutputType)}' must be one of: '{nameof(MonoAotOutputType.Normal)}', '{nameof(MonoAotOutputType.AsmOnly)}'. Received: '{OutputType}'.", nameof(OutputType)); + } + + if (parsedAotMode == MonoAotMode.LLVMOnly && !UseLLVM) + { + throw new ArgumentException($"'{nameof(UseLLVM)}' must be true when '{nameof(Mode)}' is {nameof(MonoAotMode.LLVMOnly)}.", nameof(UseLLVM)); + } + + Parallel.ForEach(Assemblies, + new ParallelOptions { MaxDegreeOfParallelism = DisableParallelAot ? 1 : Environment.ProcessorCount }, + assemblyItem => PrecompileLibrary (assemblyItem)); + + CompiledAssemblies = compiledAssemblies.ToArray(); + + return true; + } + + private void PrecompileLibrary(ITaskItem assemblyItem) + { + string assembly = assemblyItem.ItemSpec; + string directory = Path.GetDirectoryName(assembly)!; + var aotAssembly = new TaskItem(assembly); + var aotArgs = new List(); + var processArgs = new List(); + + var a = assemblyItem.GetMetadata("AotArguments"); + if (a != null) + { + aotArgs.AddRange(a.Split(";", StringSplitOptions.RemoveEmptyEntries)); + } + + var p = assemblyItem.GetMetadata("ProcessArguments"); + if (p != null) + { + processArgs.AddRange(p.Split(";", StringSplitOptions.RemoveEmptyEntries)); + } + + Utils.LogInfo($"[AOT] {assembly}"); + + processArgs.Add("--debug"); + + // add LLVM options + if (UseLLVM) + { + processArgs.Add("--llvm"); + + aotArgs.Add($"nodebug"); // can't use debug symbols with LLVM + aotArgs.Add($"llvm-path={LLVMPath}"); + } + else + { + processArgs.Add("--nollvm"); + } + + // compute output mode and file names + if (parsedAotMode == MonoAotMode.LLVMOnly) + { + aotArgs.Add("llvmonly"); + + string llvmBitcodeFile = Path.ChangeExtension(assembly, ".dll.bc"); + aotArgs.Add($"outfile={llvmBitcodeFile}"); + aotAssembly.SetMetadata("LlvmBitcodeFile", llvmBitcodeFile); + } + else + { + if (parsedAotMode == MonoAotMode.Full) + { + aotArgs.Add("full"); + } + + if (parsedOutputType == MonoAotOutputType.AsmOnly) + { + aotArgs.Add("asmonly"); + + string assemblerFile = Path.ChangeExtension(assembly, ".dll.s"); + aotArgs.Add($"outfile={assemblerFile}"); + aotAssembly.SetMetadata("AssemblerFile", assemblerFile); + } + else + { + string objectFile = Path.ChangeExtension(assembly, ".dll.o"); + aotArgs.Add($"outfile={objectFile}"); + aotAssembly.SetMetadata("ObjectFile", objectFile); + } + + if (UseLLVM) + { + string llvmObjectFile = Path.ChangeExtension(assembly, ".dll-llvm.o"); + aotArgs.Add($"llvm-outfile={llvmObjectFile}"); + aotAssembly.SetMetadata("LlvmObjectFile", llvmObjectFile); + } + } + + // pass msym-dir if specified + if (MsymPath != null) + { + aotArgs.Add($"msym-dir={MsymPath}"); + } + + string aotDataFile = Path.ChangeExtension(assembly, ".aotdata"); + aotArgs.Add($"data-outfile={aotDataFile}"); + aotAssembly.SetMetadata("AotDataFile", aotDataFile); + + // we need to quote the entire --aot arguments here to make sure it is parsed + // on Windows as one argument. Otherwise it will be split up into multiple + // values, which wont work. + processArgs.Add($"\"--aot={String.Join(",", aotArgs)}\""); + + processArgs.Add(assembly); + + var envVariables = new Dictionary + { + {"MONO_PATH", directory}, + {"MONO_ENV_OPTIONS", String.Empty} // we do not want options to be provided out of band to the cross compilers + }; + + // run the AOT compiler + Utils.RunProcess(CompilerBinaryPath, String.Join(" ", processArgs), envVariables, directory); + + compiledAssemblies.Add(aotAssembly); + } +} + +public enum MonoAotMode +{ + Normal, + Full, + LLVMOnly, +} + +public enum MonoAotOutputType +{ + Normal, + AsmOnly, +} \ No newline at end of file diff --git a/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.csproj b/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.csproj new file mode 100644 index 0000000000000..b487236cc3627 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.csproj @@ -0,0 +1,24 @@ + + + $(NetCoreAppCurrent) + Library + true + false + enable + + + + + + + + + + + + + + PreserveNewest + + + diff --git a/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.props b/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.props new file mode 100644 index 0000000000000..6824a7fc1c6f1 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/AotCompilerTask/MonoAOTCompiler.props @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tools-local/tasks/mobile.tasks/AotCompilerTask/Utils.cs b/tools-local/tasks/mobile.tasks/AotCompilerTask/Utils.cs new file mode 100644 index 0000000000000..ac649c9661843 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/AotCompilerTask/Utils.cs @@ -0,0 +1,88 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +internal class Utils +{ + public static string RunProcess( + string path, + string args = "", + IDictionary? envVars = null, + string? workingDir = null, + bool ignoreErrors = false) + { + LogInfo($"Running: {path} {args}"); + var outputBuilder = new StringBuilder(); + var errorBuilder = new StringBuilder(); + var processStartInfo = new ProcessStartInfo + { + FileName = path, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardError = true, + RedirectStandardOutput = true, + Arguments = args, + }; + + if (workingDir != null) + { + processStartInfo.WorkingDirectory = workingDir; + } + + if (envVars != null) + { + foreach (KeyValuePair envVar in envVars) + { + processStartInfo.EnvironmentVariables[envVar.Key] = envVar.Value; + } + } + + Process process = Process.Start(processStartInfo)!; + process.ErrorDataReceived += (sender, e) => + { + LogError(e.Data); + outputBuilder.AppendLine(e.Data); + errorBuilder.AppendLine(e.Data); + }; + process.OutputDataReceived += (sender, e) => + { + LogInfo(e.Data); + outputBuilder.AppendLine(e.Data); + }; + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(); + if (process.ExitCode != 0) + { + throw new Exception("Error: " + errorBuilder); + } + + return outputBuilder.ToString().Trim('\r','\n'); + } + + public static TaskLoggingHelper? Logger { get; set; } + + public static void LogInfo(string? msg) + { + if (msg != null) + { + Logger?.LogMessage(MessageImportance.High, msg); + } + } + + public static void LogError(string? msg) + { + if (msg != null) + { + Logger?.LogError(msg); + } + } +} diff --git a/src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.cs b/tools-local/tasks/mobile.tasks/AppleAppBuilder/AppleAppBuilder.cs similarity index 61% rename from src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.cs rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/AppleAppBuilder.cs index bdf5362a88818..39ba74d890f45 100644 --- a/src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.cs +++ b/tools-local/tasks/mobile.tasks/AppleAppBuilder/AppleAppBuilder.cs @@ -6,18 +6,13 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text; using System.Linq; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; public class AppleAppBuilderTask : Task { - /// - /// Path to arm64 AOT cross-compiler (mono-aot-cross) - /// It's not used for x64 (Simulator) - /// - public string? CrossCompiler { get; set; } - /// /// ProjectName is used as an app name, bundleId and xcode project name /// @@ -43,20 +38,20 @@ public class AppleAppBuilderTask : Task public string MainLibraryFileName { get; set; } = ""!; /// - /// Path to store build artifacts + /// List of paths to assemblies to be included in the app. For AOT builds the 'ObjectFile' metadata key needs to point to the object file. /// - public string? OutputDirectory { get; set; } + [Required] + public ITaskItem[] Assemblies { get; set; } = Array.Empty(); /// - /// Produce optimized binaries (e.g. use -O2 in AOT) - /// and use 'Release' config in xcode + /// Path to store build artifacts /// - public bool Optimized { get; set; } + public string? OutputDirectory { get; set; } /// - /// Disable parallel AOT compilation + /// Produce optimized binaries and use 'Release' config in xcode /// - public bool DisableParallelAot { get; set; } + public bool Optimized { get; set; } /// /// Target arch, can be "arm64" (device) or "x64" (simulator) at the moment @@ -96,24 +91,17 @@ public class AppleAppBuilderTask : Task /// public bool UseConsoleUITemplate { get; set; } - /// - /// Use LLVM for FullAOT - /// The cross-compiler must be built with LLVM support - /// - public bool UseLlvm { get; set; } - - /// - /// Path to LLVM binaries (opt and llc) - /// It's required if UseLlvm is set - /// - public string? LlvmPath { get; set; } - /// /// Path to *.app bundle /// [Output] public string AppBundlePath { get; set; } = ""!; + /// + /// Prefer FullAOT mode for Simulator over JIT + /// + public bool UseAotForSimulator { get; set; } + /// /// Path to xcode project /// @@ -124,10 +112,6 @@ public override bool Execute() { Utils.Logger = Log; bool isDevice = Arch.Equals("arm64", StringComparison.InvariantCultureIgnoreCase); - if (isDevice && string.IsNullOrEmpty(CrossCompiler)) - { - throw new ArgumentException("arm64 arch requires CrossCompiler"); - } if (!File.Exists(Path.Combine(AppDir, MainLibraryFileName))) { @@ -139,12 +123,6 @@ public override bool Execute() throw new ArgumentException($"ProjectName='{ProjectName}' should not contain spaces"); } - if (UseLlvm && string.IsNullOrEmpty(LlvmPath)) - { - // otherwise we might accidentally use some random llc/opt from PATH (installed with clang) - throw new ArgumentException($"LlvmPath shoun't be empty when UseLlvm is set"); - } - string[] excludes = new string[0]; if (ExcludeFromAppDir != null) { @@ -153,9 +131,6 @@ public override bool Execute() .Select(i => i.ItemSpec) .ToArray(); } - string[] libsToAot = Directory.GetFiles(AppDir, "*.dll") - .Where(f => !excludes.Contains(Path.GetFileName(f))) - .ToArray(); string binDir = Path.Combine(AppDir, $"bin-{ProjectName}-{Arch}"); if (!string.IsNullOrEmpty(OutputDirectory)) @@ -164,26 +139,31 @@ public override bool Execute() } Directory.CreateDirectory(binDir); - // run AOT compilation only for devices - if (isDevice) + var assemblerFiles = new List(); + foreach (ITaskItem file in Assemblies) { - if (string.IsNullOrEmpty(CrossCompiler)) - throw new InvalidOperationException("cross-compiler is not set"); + // use AOT files if available + var obj = file.GetMetadata("AssemblerFile"); + if (!String.IsNullOrEmpty(obj)) + { + assemblerFiles.Add(obj); + } + } - AotCompiler.PrecompileLibraries(CrossCompiler, Arch, !DisableParallelAot, binDir, libsToAot, - new Dictionary { {"MONO_PATH", AppDir} }, - Optimized, UseLlvm, LlvmPath); + if ((isDevice || UseAotForSimulator) && !assemblerFiles.Any()) + { + throw new InvalidOperationException("Need list of AOT files for device builds."); } // generate modules.m - AotCompiler.GenerateLinkAllFile( - Directory.GetFiles(binDir, "*.dll.o"), + GenerateLinkAllFile( + assemblerFiles, Path.Combine(binDir, "modules.m")); if (GenerateXcodeProject) { - XcodeProjectPath = Xcode.GenerateXCode(ProjectName, MainLibraryFileName, - AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, NativeMainSource); + XcodeProjectPath = Xcode.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles, + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, UseAotForSimulator, Optimized, NativeMainSource); if (BuildAppBundle) { @@ -203,4 +183,57 @@ public override bool Execute() return true; } + + private static void GenerateLinkAllFile(IEnumerable asmFiles, string outputFile) + { + // Generates 'modules.m' in order to register all managed libraries + // + // + // extern void *mono_aot_module_Lib1_info; + // extern void *mono_aot_module_Lib2_info; + // ... + // + // void mono_ios_register_modules (void) + // { + // mono_aot_register_module (mono_aot_module_Lib1_info); + // mono_aot_register_module (mono_aot_module_Lib2_info); + // ... + // } + + Utils.LogInfo("Generating 'modules.m'..."); + + var lsDecl = new StringBuilder(); + lsDecl + .AppendLine("#include ") + .AppendLine("#include ") + .AppendLine() + .AppendLine("#if TARGET_OS_IPHONE && (!TARGET_IPHONE_SIMULATOR || USE_AOT_FOR_SIMULATOR)") + .AppendLine(); + + var lsUsage = new StringBuilder(); + lsUsage + .AppendLine("void mono_ios_register_modules (void)") + .AppendLine("{"); + foreach (string asmFile in asmFiles) + { + string symbol = "mono_aot_module_" + + Path.GetFileName(asmFile) + .Replace(".dll.s", "") + .Replace(".", "_") + .Replace("-", "_") + "_info"; + + lsDecl.Append("extern void *").Append(symbol).Append(';').AppendLine(); + lsUsage.Append("\tmono_aot_register_module (").Append(symbol).Append(");").AppendLine(); + } + lsDecl + .AppendLine() + .Append(lsUsage) + .AppendLine("}") + .AppendLine() + .AppendLine("#endif") + .AppendLine(); + + File.WriteAllText(outputFile, lsDecl.ToString()); + Utils.LogInfo($"Saved to {outputFile}."); + } } diff --git a/src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.csproj b/tools-local/tasks/mobile.tasks/AppleAppBuilder/AppleAppBuilder.csproj similarity index 87% rename from src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.csproj rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/AppleAppBuilder.csproj index dd703fd583a9a..255150988f9c7 100644 --- a/src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.csproj +++ b/tools-local/tasks/mobile.tasks/AppleAppBuilder/AppleAppBuilder.csproj @@ -1,11 +1,10 @@ + $(NetCoreAppCurrent) Library - bin - $(NetCoreAppCurrent) - enable true false + enable @@ -17,7 +16,6 @@ - diff --git a/src/mono/msbuild/AppleAppBuilder/Templates/CMakeLists.txt.template b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/CMakeLists.txt.template similarity index 89% rename from src/mono/msbuild/AppleAppBuilder/Templates/CMakeLists.txt.template rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/CMakeLists.txt.template index 78afc51ecd1d1..ecd3d6c1e614d 100644 --- a/src/mono/msbuild/AppleAppBuilder/Templates/CMakeLists.txt.template +++ b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/CMakeLists.txt.template @@ -1,6 +1,7 @@ -cmake_minimum_required(VERSION 3.14.5) +cmake_minimum_required(VERSION 3.16) project(%ProjectName%) +enable_language(OBJC ASM) set(APP_RESOURCES %AppResources% @@ -15,6 +16,10 @@ add_executable( ${APP_RESOURCES} ) +%AotSources% + +%Defines% + include_directories("%MonoInclude%") set_target_properties(%ProjectName% PROPERTIES diff --git a/src/mono/msbuild/AppleAppBuilder/Templates/Info.plist.template b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/Info.plist.template similarity index 100% rename from src/mono/msbuild/AppleAppBuilder/Templates/Info.plist.template rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/Info.plist.template diff --git a/src/mono/msbuild/AppleAppBuilder/Templates/main-console.m b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/main-console.m similarity index 97% rename from src/mono/msbuild/AppleAppBuilder/Templates/main-console.m rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/main-console.m index 65dedbe328e3c..847d5787aae85 100644 --- a/src/mono/msbuild/AppleAppBuilder/Templates/main-console.m +++ b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/main-console.m @@ -48,7 +48,7 @@ - (void)viewDidLoad { summaryLabel.font = [UIFont boldSystemFontOfSize: 12]; summaryLabel.numberOfLines = 2; summaryLabel.textAlignment = NSTextAlignmentLeft; -#ifdef TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +#ifdef TARGET_OS_IPHONE && (!TARGET_IPHONE_SIMULATOR || USE_AOT_FOR_SIMULATOR) summaryLabel.text = @"Loading..."; #else summaryLabel.text = @"Jitting..."; diff --git a/src/mono/msbuild/AppleAppBuilder/Templates/main-simple.m b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/main-simple.m similarity index 100% rename from src/mono/msbuild/AppleAppBuilder/Templates/main-simple.m rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/main-simple.m diff --git a/src/mono/msbuild/AppleAppBuilder/Templates/runtime.h b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/runtime.h similarity index 100% rename from src/mono/msbuild/AppleAppBuilder/Templates/runtime.h rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/runtime.h diff --git a/src/mono/msbuild/AppleAppBuilder/Templates/runtime.m b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/runtime.m similarity index 97% rename from src/mono/msbuild/AppleAppBuilder/Templates/runtime.m rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/runtime.m index b575aa2ca8594..45b277365c29b 100644 --- a/src/mono/msbuild/AppleAppBuilder/Templates/runtime.m +++ b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Templates/runtime.m @@ -197,7 +197,7 @@ //%DllMap% } -#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +#if TARGET_OS_IPHONE && (!TARGET_IPHONE_SIMULATOR || USE_AOT_FOR_SIMULATOR) void mono_jit_set_aot_mode (MonoAotMode mode); void mono_ios_register_modules (void); #endif @@ -229,7 +229,7 @@ // TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES monovm_initialize(0, NULL, NULL); -#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +#if TARGET_OS_IPHONE && (!TARGET_IPHONE_SIMULATOR || USE_AOT_FOR_SIMULATOR) register_dllmap (); // register modules mono_ios_register_modules (); @@ -250,7 +250,7 @@ } mono_jit_init_version ("dotnet.ios", "mobile"); -#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +#if TARGET_OS_IPHONE && (!TARGET_IPHONE_SIMULATOR || USE_AOT_FOR_SIMULATOR) // device runtimes are configured to use lazy gc thread creation MONO_ENTER_GC_UNSAFE; mono_gc_init_finalizer_thread (); diff --git a/src/mono/msbuild/AppleAppBuilder/Utils.cs b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Utils.cs similarity index 100% rename from src/mono/msbuild/AppleAppBuilder/Utils.cs rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Utils.cs diff --git a/src/mono/msbuild/AppleAppBuilder/Xcode.cs b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Xcode.cs similarity index 81% rename from src/mono/msbuild/AppleAppBuilder/Xcode.cs rename to tools-local/tasks/mobile.tasks/AppleAppBuilder/Xcode.cs index 305e5d4576256..76ec75c0d3225 100644 --- a/src/mono/msbuild/AppleAppBuilder/Xcode.cs +++ b/tools-local/tasks/mobile.tasks/AppleAppBuilder/Xcode.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -14,15 +15,22 @@ internal class Xcode public static string GenerateXCode( string projectName, string entryPointLib, + IEnumerable asmFiles, string workspace, string binDir, string monoInclude, bool preferDylibs, bool useConsoleUiTemplate, + bool useAotForSimulator, + bool stripDebugSymbols, string? nativeMainSource = null) { // bundle everything as resources excluding native files - string[] excludes = {".dll.o", ".dll.s", ".dwarf", ".m", ".h", ".a", ".bc"}; + var excludes = new List { ".dll.o", ".dll.s", ".dwarf", ".m", ".h", ".a", ".bc", "libmonosgen-2.0.dylib" }; + if (stripDebugSymbols) + { + excludes.Add(".pdb"); + } string[] resources = Directory.GetFiles(workspace) .Where(f => !excludes.Any(e => f.EndsWith(e, StringComparison.InvariantCultureIgnoreCase))) @@ -57,7 +65,7 @@ internal class Xcode { string libName = Path.GetFileNameWithoutExtension(lib); // libmono must always be statically linked, for other librarires we can use dylibs - bool dylibExists = libName != "libmono" && dylibs.Any(dylib => Path.GetFileName(dylib) == libName + ".dylib"); + bool dylibExists = libName != "libmonosgen-2.0" && dylibs.Any(dylib => Path.GetFileName(dylib) == libName + ".dylib"); if (!preferDylibs || !dylibExists) { @@ -66,12 +74,20 @@ internal class Xcode toLink += $" \"-force_load {lib}\"{Environment.NewLine}"; } } - foreach (string lib in Directory.GetFiles(binDir, "*.dll.o")) + + string aotSources = ""; + foreach (string asm in asmFiles) { // these libraries are linked via modules.m - toLink += $" \"{lib}\"{Environment.NewLine}"; + var name = Path.GetFileNameWithoutExtension(asm); + aotSources += $"add_library({name} OBJECT {asm}){Environment.NewLine}"; + toLink += $" {name}{Environment.NewLine}"; } + cmakeLists = cmakeLists.Replace("%NativeLibrariesToLink%", toLink); + cmakeLists = cmakeLists.Replace("%AotSources%", aotSources); + cmakeLists = cmakeLists.Replace("%Defines%", + useAotForSimulator ? "add_definitions(-DUSE_AOT_FOR_SIMULATOR=1)" : ""); string plist = Utils.GetEmbeddedResource("Info.plist.template") .Replace("%BundleIdentifier%", projectName); @@ -139,7 +155,16 @@ internal class Xcode args.Append(" -configuration ").Append(config); Utils.RunProcess("xcodebuild", args.ToString(), workingDir: Path.GetDirectoryName(xcodePrjPath)); - return Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config + "-" + sdk, + + string appPath = Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config + "-" + sdk, Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); + + long appSize = new DirectoryInfo(appPath) + .EnumerateFiles("*", SearchOption.AllDirectories) + .Sum(file => file.Length); + + Utils.LogInfo($"\nAPP size: {(appSize / 1000_000.0):0.#} Mb.\n"); + + return appPath; } } diff --git a/tools-local/tasks/mobile.tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/tools-local/tasks/mobile.tasks/WasmAppBuilder/PInvokeTableGenerator.cs new file mode 100644 index 0000000000000..dd72774b5d988 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -0,0 +1,146 @@ +// -*- indent-tabs-mode: nil -*- +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Reflection; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +public class PInvokeTableGenerator : Task +{ + [Required] + public ITaskItem[]? Modules { get; set; } + [Required] + public ITaskItem[]? Assemblies { get; set; } + [Required] + public string? OutputPath { get; set; } + + public override bool Execute () { + GenPInvokeTable (Modules!.Select (item => item.ItemSpec).ToArray (), Assemblies!.Select (item => item.ItemSpec).ToArray ()); + return true; + } + + void GenPInvokeTable (string[] pinvokeModules, string[] assemblies) { + var modules = new Dictionary (); + foreach (var module in pinvokeModules) + modules [module] = module; + + var pinvokes = new List (); + + var resolver = new PathAssemblyResolver (assemblies); + var mlc = new MetadataLoadContext (resolver, "System.Private.CoreLib"); + foreach (var aname in assemblies) { + var a = mlc.LoadFromAssemblyPath (aname); + foreach (var type in a.GetTypes ()) + CollectPInvokes (pinvokes, type); + } + + Log.LogMessage (MessageImportance.Normal, $"Generating pinvoke table to '{OutputPath}'."); + + using (var w = File.CreateText (OutputPath!)) { + EmitPInvokeTable (w, modules, pinvokes); + } + } + + void CollectPInvokes (List pinvokes, Type type) { + foreach (var method in type.GetMethods (BindingFlags.DeclaredOnly|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance)) { + if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0) + continue; + var dllimport = method.CustomAttributes.First (attr => attr.AttributeType.Name == "DllImportAttribute"); + var module = (string)dllimport.ConstructorArguments [0].Value!; + var entrypoint = (string)dllimport.NamedArguments.First (arg => arg.MemberName == "EntryPoint").TypedValue.Value!; + pinvokes.Add (new PInvoke (entrypoint, module, method)); + } + } + + void EmitPInvokeTable (StreamWriter w, Dictionary modules, List pinvokes) { + w.WriteLine ("// GENERATED FILE, DO NOT MODIFY"); + w.WriteLine ("typedef struct {"); + w.WriteLine ("const char *name;"); + w.WriteLine ("void *func;"); + w.WriteLine ("} PinvokeImport;"); + w.WriteLine (); + + foreach (var pinvoke in pinvokes) { + if (modules.ContainsKey (pinvoke.Module)) + w.WriteLine (GenPInvokeDecl (pinvoke)); + } + + foreach (var module in modules.Keys) { + string symbol = module.Replace (".", "_") + "_imports"; + w.WriteLine ("static PinvokeImport " + symbol + " [] = {"); + foreach (var pinvoke in pinvokes) { + if (pinvoke.Module == module) + w.WriteLine ("{\"" + pinvoke.EntryPoint + "\", " + pinvoke.EntryPoint + "},"); + } + w.WriteLine ("{NULL, NULL}"); + w.WriteLine ("};"); + } + w.Write ("static void *pinvoke_tables[] = { "); + foreach (var module in modules.Keys) { + string symbol = module.Replace (".", "_") + "_imports"; + w.Write (symbol + ","); + } + w.WriteLine ("};"); + w.Write ("static char *pinvoke_names[] = { "); + foreach (var module in modules.Keys) { + w.Write ("\"" + module + "\"" + ","); + } + w.WriteLine ("};"); + } + + string MapType (Type t) { + string name = t.Name; + if (name == "Void") + return "void"; + else if (name == "Double") + return "double"; + else if (name == "Single") + return "float"; + else if (name == "Int64") + return "int64_t"; + else if (name == "UInt64") + return "uint64_t"; + else + return "int"; + } + + string GenPInvokeDecl (PInvoke pinvoke) { + var sb = new StringBuilder (); + var method = pinvoke.Method; + sb.Append (MapType (method.ReturnType)); + sb.Append ($" {pinvoke.EntryPoint} ("); + int pindex = 0; + var pars = method.GetParameters (); + foreach (var p in pars) { + if (pindex > 0) + sb.Append (","); + sb.Append (MapType (pars [pindex].ParameterType)); + pindex ++; + } + sb.Append (");"); + return sb.ToString (); + } +} + +class PInvoke +{ + public PInvoke (string entry_point, string module, MethodInfo method) { + EntryPoint = entry_point; + Module = module; + Method = method; + } + + public string EntryPoint; + public string Module; + public MethodInfo Method; +} diff --git a/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs b/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs new file mode 100644 index 0000000000000..ce6839f4f6275 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -0,0 +1,123 @@ +// -*- indent-tabs-mode: nil -*- +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Reflection; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +public class WasmAppBuilder : Task +{ + // FIXME: Document + + [Required] + public string? AppDir { get; set; } + [Required] + public string? RuntimePackDir { get; set; } + [Required] + public string? MainAssembly { get; set; } + [Required] + public string? MainJS { get; set; } + [Required] + public ITaskItem[]? AssemblySearchPaths { get; set; } + public ITaskItem[]? ExtraAssemblies { get; set; } + + Dictionary? Assemblies; + Resolver? Resolver; + + public override bool Execute () { + if (!File.Exists (MainAssembly)) + throw new ArgumentException ($"File MainAssembly='{MainAssembly}' doesn't exist."); + if (!File.Exists (MainJS)) + throw new ArgumentException ($"File MainJS='{MainJS}' doesn't exist."); + + var paths = new List (); + Assemblies = new Dictionary (); + + // Collect and load assemblies used by the app + foreach (var v in AssemblySearchPaths!) { + var dir = v.ItemSpec; + if (!Directory.Exists (dir)) + throw new ArgumentException ($"Directory '{dir}' doesn't exist or not a directory."); + paths.Add (dir); + } + Resolver = new Resolver (paths); + var mlc = new MetadataLoadContext (Resolver, "System.Private.CoreLib"); + + var mainAssembly = mlc.LoadFromAssemblyPath (MainAssembly); + Add (mlc, mainAssembly); + + if (ExtraAssemblies != null) { + foreach (var item in ExtraAssemblies) { + var refAssembly = mlc.LoadFromAssemblyPath (item.ItemSpec); + Add (mlc, refAssembly); + } + } + + // Create app + Directory.CreateDirectory (AppDir!); + Directory.CreateDirectory (Path.Join (AppDir, "managed")); + foreach (var assembly in Assemblies!.Values) + File.Copy (assembly.Location, Path.Join (AppDir, "managed", Path.GetFileName (assembly.Location)), true); + foreach (var f in new string [] { "dotnet.wasm", "dotnet.js" }) + File.Copy (Path.Join (RuntimePackDir, "native", "wasm", "runtimes", "release", f), Path.Join (AppDir, f), true); + File.Copy (MainJS!, Path.Join (AppDir, "runtime.js"), true); + + using (var sw = File.CreateText (Path.Join (AppDir, "mono-config.js"))) { + sw.WriteLine ("config = {"); + sw.WriteLine ("\tvfs_prefix: \"managed\","); + sw.WriteLine ("\tdeploy_prefix: \"managed\","); + sw.WriteLine ("\tenable_debugging: 0,"); + sw.WriteLine ("\tfile_list: ["); + foreach (var assembly in Assemblies.Values) { + sw.Write ("\"" + Path.GetFileName (assembly.Location) + "\""); + sw.Write (", "); + } + sw.WriteLine ("],"); + sw.WriteLine ("}"); + } + + using (var sw = File.CreateText (Path.Join (AppDir, "run-v8.sh"))) { + sw.WriteLine ("v8 --expose_wasm runtime.js -- --enable-gc --run " + Path.GetFileName (MainAssembly) + " $*"); + } + + return true; + } + + void Add (MetadataLoadContext mlc, Assembly assembly) { + Assemblies! [assembly.GetName ().Name!] = assembly; + foreach (var aname in assembly.GetReferencedAssemblies ()) { + var refAssembly = mlc.LoadFromAssemblyName (aname); + Add (mlc, refAssembly); + } + } +} + +class Resolver : MetadataAssemblyResolver +{ + List SearchPaths; + + public Resolver (List searchPaths) { + this.SearchPaths = searchPaths; + } + + public override Assembly? Resolve (MetadataLoadContext context, AssemblyName assemblyName) { + var name = assemblyName.Name; + foreach (var dir in SearchPaths) { + var path = Path.Combine (dir, name + ".dll"); + if (File.Exists (path)) { + Console.WriteLine (path); + return context.LoadFromAssemblyPath (path); + } + } + return null; + } +} diff --git a/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.csproj b/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.csproj new file mode 100644 index 0000000000000..ab82b35f70807 --- /dev/null +++ b/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -0,0 +1,23 @@ + + + $(NetCoreAppCurrent) + Library + false + enable + + + + + + + + + + + + + + + diff --git a/tools-local/tasks/tasks.proj b/tools-local/tasks/tasks.proj new file mode 100644 index 0000000000000..a81e2f9590eb6 --- /dev/null +++ b/tools-local/tasks/tasks.proj @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + $([MSBuild]::NormalizePath('$(ArtifactsObjDir)', '$(MSBuildProjectName)', 'Debug', 'build-semaphore.txt')) + + + + + + + \ No newline at end of file